Annotation of embedaddon/php/pear/install-pear-nozlib.phar, revision 1.1.1.2

1.1       misho       1: <?php
                      2: error_reporting(1803);
                      3: if (function_exists('mb_internal_encoding')) {
                      4:     mb_internal_encoding('ASCII');
                      5: }
                      6: if (!class_exists('PHP_Archive')) {/**
                      7:  * PHP_Archive Class (implements .phar)
                      8:  *
                      9:  * @package PHP_Archive
                     10:  * @category PHP
                     11:  */
                     12: /**
                     13:  * PHP_Archive Class (implements .phar)
                     14:  *
                     15:  * PHAR files a singular archive from which an entire application can run.
                     16:  * To use it, simply package it using {@see PHP_Archive_Creator} and use phar://
                     17:  * URIs to your includes. i.e. require_once 'phar://config.php' will include config.php
                     18:  * from the root of the PHAR file.
                     19:  *
                     20:  * Gz code borrowed from the excellent File_Archive package by Vincent Lascaux.
                     21:  *
                     22:  * @copyright Copyright David Shafik and Synaptic Media 2004. All rights reserved.
                     23:  * @author Davey Shafik <davey@synapticmedia.net>
                     24:  * @author Greg Beaver <cellog@php.net>
                     25:  * @link http://www.synapticmedia.net Synaptic Media
                     26:  * @version Id: Archive.php,v 1.52 2007/09/01 20:28:14 cellog Exp $
                     27:  * @package PHP_Archive
                     28:  * @category PHP
                     29:  */
                     30:  
                     31: class PHP_Archive
                     32: {
                     33:     const GZ = 0x00001000;
                     34:     const BZ2 = 0x00002000;
                     35:     const SIG = 0x00010000;
                     36:     const SHA1 = 0x0002;
                     37:     const MD5 = 0x0001;
                     38:     /**
                     39:      * Whether this archive is compressed with zlib
                     40:      *
                     41:      * @var bool
                     42:      */
                     43:     private $_compressed;
                     44:     /**
                     45:      * @var string Real path to the .phar archive
                     46:      */
                     47:     private $_archiveName = null;
                     48:     /**
                     49:      * Current file name in the phar
                     50:      * @var string
                     51:      */
                     52:     protected $currentFilename = null;
                     53:     /**
                     54:      * Length of current file in the phar
                     55:      * @var string
                     56:      */
                     57:     protected $internalFileLength = null;
                     58:     /**
                     59:      * Current file statistics (size, creation date, etc.)
                     60:      * @var string
                     61:      */
                     62:     protected $currentStat = null;
                     63:     /**
                     64:      * @var resource|null Pointer to open .phar
                     65:      */
                     66:     protected $fp = null;
                     67:     /**
                     68:      * @var int Current Position of the pointer
                     69:      */
                     70:     protected $position = 0;
                     71: 
                     72:     /**
                     73:      * Map actual realpath of phars to meta-data about the phar
                     74:      *
                     75:      * Data is indexed by the alias that is used by internal files.  In other
                     76:      * words, if a file is included via:
                     77:      * <code>
                     78:      * require_once 'phar://PEAR.phar/PEAR/Installer.php';
                     79:      * </code>
                     80:      * then the alias is "PEAR.phar"
                     81:      * 
                     82:      * Information stored is a boolean indicating whether this .phar is compressed
                     83:      * with zlib, another for bzip2, phar-specific meta-data, and
                     84:      * the precise offset of internal files
                     85:      * within the .phar, used with the {@link $_manifest} to load actual file contents
                     86:      * @var array
                     87:      */
                     88:     private static $_pharMapping = array();
                     89:     /**
                     90:      * Map real file paths to alias used
                     91:      *
                     92:      * @var array
                     93:      */
                     94:     private static $_pharFiles = array();
                     95:     /**
                     96:      * File listing for the .phar
                     97:      * 
                     98:      * The manifest is indexed per phar.
                     99:      * 
                    100:      * Files within the .phar are indexed by their relative path within the
                    101:      * .phar.  Each file has this information in its internal array
                    102:      *
                    103:      * - 0 = uncompressed file size
                    104:      * - 1 = timestamp of when file was added to phar
                    105:      * - 2 = offset of file within phar relative to internal file's start
                    106:      * - 3 = compressed file size (actual size in the phar)
                    107:      * @var array
                    108:      */
                    109:     private static $_manifest = array();
                    110:     /**
                    111:      * Absolute offset of internal files within the .phar, indexed by absolute
                    112:      * path to the .phar
                    113:      *
                    114:      * @var array
                    115:      */
                    116:     private static $_fileStart = array();
                    117:     /**
                    118:      * file name of the phar
                    119:      *
                    120:      * @var string
                    121:      */
                    122:     private $_basename;
                    123: 
                    124: 
                    125:     /**
                    126:      * Default MIME types used for the web front controller
                    127:      *
                    128:      * @var array
                    129:      */
                    130:     public static $defaultmimes = array(
                    131:             'aif' => 'audio/x-aiff',
                    132:             'aiff' => 'audio/x-aiff',
                    133:             'arc' => 'application/octet-stream',
                    134:             'arj' => 'application/octet-stream',
                    135:             'art' => 'image/x-jg',
                    136:             'asf' => 'video/x-ms-asf',
                    137:             'asx' => 'video/x-ms-asf',
                    138:             'avi' => 'video/avi',
                    139:             'bin' => 'application/octet-stream',
                    140:             'bm' => 'image/bmp',
                    141:             'bmp' => 'image/bmp',
                    142:             'bz2' => 'application/x-bzip2',
                    143:             'css' => 'text/css',
                    144:             'doc' => 'application/msword',
                    145:             'dot' => 'application/msword',
                    146:             'dv' => 'video/x-dv',
                    147:             'dvi' => 'application/x-dvi',
                    148:             'eps' => 'application/postscript',
                    149:             'exe' => 'application/octet-stream',
                    150:             'gif' => 'image/gif',
                    151:             'gz' => 'application/x-gzip',
                    152:             'gzip' => 'application/x-gzip',
                    153:             'htm' => 'text/html',
                    154:             'html' => 'text/html',
                    155:             'ico' => 'image/x-icon',
                    156:             'jpe' => 'image/jpeg',
                    157:             'jpg' => 'image/jpeg',
                    158:             'jpeg' => 'image/jpeg',
                    159:             'js' => 'application/x-javascript',
                    160:             'log' => 'text/plain',
                    161:             'mid' => 'audio/x-midi',
                    162:             'mov' => 'video/quicktime',
                    163:             'mp2' => 'audio/mpeg',
                    164:             'mp3' => 'audio/mpeg3',
                    165:             'mpg' => 'audio/mpeg',
                    166:             'pdf' => 'aplication/pdf',
                    167:             'png' => 'image/png',
                    168:             'rtf' => 'application/rtf',
                    169:             'tif' => 'image/tiff',
                    170:             'tiff' => 'image/tiff',
                    171:             'txt' => 'text/plain',
                    172:             'xml' => 'text/xml',
                    173:         );
                    174: 
                    175:     public static $defaultphp = array(
                    176:         'php' => true
                    177:         );
                    178: 
                    179:     public static $defaultphps = array(
                    180:         'phps' => true
                    181:         );
                    182: 
                    183:     public static $deny = array('/.+\.inc$/');
                    184: 
                    185:     public static function viewSource($archive, $file)
                    186:     {
                    187:         // security, idea borrowed from PHK
                    188:         if (!file_exists($archive . '.introspect')) {
                    189:             header("HTTP/1.0 404 Not Found");
                    190:             return false;
                    191:         }
                    192:         if (self::_fileExists($archive, $_GET['viewsource'])) {
                    193:             $source = highlight_file('phar://install-pear-nozlib.phar/' .
                    194:                 $_GET['viewsource'], true);
                    195:             header('Content-Type: text/html');
                    196:             header('Content-Length: ' . strlen($source));
                    197:             echo '<html><head><title>Source of ',
                    198:                 htmlspecialchars($_GET['viewsource']), '</title></head>';
                    199:             echo '<body><h1>Source of ',
                    200:                 htmlspecialchars($_GET['viewsource']), '</h1>';
                    201:             if (isset($_GET['introspect'])) {
                    202:                 echo '<a href="', htmlspecialchars($_SERVER['PHP_SELF']),
                    203:                     '?introspect=', urlencode(htmlspecialchars($_GET['introspect'])),
                    204:                     '">Return to ', htmlspecialchars($_GET['introspect']), '</a><br />';
                    205:             }
                    206:             echo $source;
                    207:             return false;
                    208:         } else {
                    209:             header("HTTP/1.0 404 Not Found");
                    210:             return false;
                    211:         }
                    212:         
                    213:     }
                    214: 
                    215:     public static function introspect($archive, $dir)
                    216:     {
                    217:         // security, idea borrowed from PHK
                    218:         if (!file_exists($archive . '.introspect')) {
                    219:             header("HTTP/1.0 404 Not Found");
                    220:             return false;
                    221:         }
                    222:         if (!$dir) {
                    223:             $dir = '/';
                    224:         }
                    225:         $dir = self::processFile($dir);
                    226:         if ($dir[0] != '/') {
                    227:             $dir = '/' . $dir;
                    228:         }
                    229:         try {
                    230:             $self = htmlspecialchars($_SERVER['PHP_SELF']);
                    231:             $iterate = new DirectoryIterator('phar://install-pear-nozlib.phar' . $dir);
                    232:             echo '<html><head><title>Introspect ', htmlspecialchars($dir),
                    233:                 '</title></head><body><h1>Introspect ', htmlspecialchars($dir),
                    234:                 '</h1><ul>';
                    235:             if ($dir != '/') {
                    236:                 echo '<li><a href="', $self, '?introspect=',
                    237:                     htmlspecialchars(dirname($dir)), '">..</a></li>';
                    238:             }
                    239:             foreach ($iterate as $entry) {
                    240:                 if ($entry->isDot()) continue;
                    241:                 $name = self::processFile($entry->getPathname());
                    242:                 $name = str_replace('phar://install-pear-nozlib.phar/', '', $name);
                    243:                 if ($entry->isDir()) {
                    244:                     echo '<li><a href="', $self, '?introspect=',
                    245:                         urlencode(htmlspecialchars($name)),
                    246:                         '">',
                    247:                         htmlspecialchars($entry->getFilename()), '/</a> [directory]</li>';
                    248:                 } else {
                    249:                     echo '<li><a href="', $self, '?introspect=',
                    250:                         urlencode(htmlspecialchars($dir)), '&viewsource=',
                    251:                         urlencode(htmlspecialchars($name)),
                    252:                         '">',
                    253:                         htmlspecialchars($entry->getFilename()), '</a></li>';
                    254:                 }
                    255:             }
                    256:             return false;
                    257:         } catch (Exception $e) {
                    258:             echo '<html><head><title>Directory not found: ',
                    259:                 htmlspecialchars($dir), '</title></head>',
                    260:                 '<body><h1>Directory not found: ', htmlspecialchars($dir), '</h1>',
                    261:                 '<p>Try <a href="', htmlspecialchars($_SERVER['PHP_SELF']), '?introspect=/">',
                    262:                 'This link</a></p></body></html>';
                    263:             return false;
                    264:         }
                    265:     }
                    266: 
                    267:     public static function webFrontController($initfile)
                    268:     {
                    269:         if (isset($_SERVER) && isset($_SERVER['REQUEST_URI'])) {
                    270:             $uri = parse_url($_SERVER['REQUEST_URI']);
                    271:             $archive = realpath($_SERVER['SCRIPT_FILENAME']);
                    272:             $subpath = str_replace('/' . basename($archive), '', $uri['path']);
                    273:             if (!$subpath || $subpath == '/') {
                    274:                 if (isset($_GET['viewsource'])) {
                    275:                     return self::viewSource($archive, $_GET['viewsource']);
                    276:                 }
                    277:                 if (isset($_GET['introspect'])) {
                    278:                     return self::introspect($archive, $_GET['introspect']);
                    279:                 }
                    280:                 $subpath = '/' . $initfile;
                    281:             }
                    282:             if (!self::_fileExists($archive, substr($subpath, 1))) {
                    283:                 header("HTTP/1.0 404 Not Found");
                    284:                 return false;
                    285:             }
                    286:             foreach (self::$deny as $pattern) {
                    287:                 if (preg_match($pattern, $subpath)) {
                    288:                     header("HTTP/1.0 404 Not Found");
                    289:                     return false;
                    290:                 }
                    291:             }
                    292:             $inf = pathinfo(basename($subpath));
                    293:             if (!isset($inf['extension'])) {
                    294:                 header('Content-Type: text/plain');
                    295:                 header('Content-Length: ' .
                    296:                     self::_filesize($archive, substr($subpath, 1)));
                    297:                 readfile('phar://install-pear-nozlib.phar' . $subpath);
                    298:                 return false;
                    299:             }
                    300:             if (isset(self::$defaultphp[$inf['extension']])) {
                    301:                 include 'phar://install-pear-nozlib.phar' . $subpath;
                    302:                 return false;
                    303:             }
                    304:             if (isset(self::$defaultmimes[$inf['extension']])) {
                    305:                 header('Content-Type: ' . self::$defaultmimes[$inf['extension']]);
                    306:                 header('Content-Length: ' .
                    307:                     self::_filesize($archive, substr($subpath, 1)));
                    308:                 readfile('phar://install-pear-nozlib.phar' . $subpath);
                    309:                 return false;
                    310:             }
                    311:             if (isset(self::$defaultphps[$inf['extension']])) {
                    312:                 header('Content-Type: text/html');
                    313:                 $c = highlight_file('phar://install-pear-nozlib.phar' . $subpath, true);
                    314:                 header('Content-Length: ' . strlen($c));
                    315:                 echo $c;
                    316:                 return false;
                    317:             }
                    318:             header('Content-Type: text/plain');
                    319:             header('Content-Length: ' .
                    320:                     self::_filesize($archive, substr($subpath, 1)));
                    321:             readfile('phar://install-pear-nozlib.phar' . $subpath);
                    322:         }
                    323:     }
                    324: 
                    325:     /**
                    326:      * Detect end of stub
                    327:      *
                    328:      * @param string $buffer stub past '__HALT_'.'COMPILER();'
                    329:      * @return end of stub, prior to length of manifest.
                    330:      */
                    331:     private static final function _endOfStubLength($buffer)
                    332:     {
                    333:         $pos = 0;
                    334:         if (!strlen($buffer)) {
                    335:             return $pos;
                    336:         }
                    337:         if (($buffer[0] == ' ' || $buffer[0] == "\n") && @substr($buffer, 1, 2) == '')
                    338:         {
                    339:             $pos += 3;
                    340:             if ($buffer[$pos] == "\r" && $buffer[$pos+1] == "\n") {
                    341:                 $pos += 2;
                    342:             }
                    343:             else if ($buffer[$pos] == "\n") {
                    344:                 $pos += 1;
                    345:             }
                    346:         }
                    347:         return $pos;
                    348:     }
                    349: 
                    350:     /**
                    351:      * Allows loading an external Phar archive without include()ing it
                    352:      *
                    353:      * @param string $file  phar package to load
                    354:      * @param string $alias alias to use
                    355:      * @throws Exception
                    356:      */
                    357:     public static final function loadPhar($file, $alias = NULL)
                    358:     {
                    359:         $file = realpath($file);
                    360:         if ($file) {
                    361:             $fp = fopen($file, 'rb');
                    362:             $buffer = '';
                    363:             while (!feof($fp)) {
                    364:                 $buffer .= fread($fp, 8192);
                    365:                 // don't break phars
                    366:                 if ($pos = strpos($buffer, '__HALT_COMPI' . 'LER();')) {
                    367:                     $buffer .= fread($fp, 5);
                    368:                     fclose($fp);
                    369:                     $pos += 18;
                    370:                     $pos += self::_endOfStubLength(substr($buffer, $pos));
                    371:                     return self::_mapPhar($file, $pos, $alias);
                    372:                 }
                    373:             }
                    374:             fclose($fp);
                    375:         }
                    376:     }
                    377: 
                    378:     /**
                    379:      * Map a full real file path to an alias used to refer to the .phar
                    380:      *
                    381:      * This function can only be called from the initialization of the .phar itself.
                    382:      * Any attempt to call from outside the .phar or to re-alias the .phar will fail
                    383:      * as a security measure.
                    384:      * @param string $alias
                    385:      * @param int $dataoffset the value of 42421                   
                    386:      */
                    387:     public static final function mapPhar($alias = NULL, $dataoffset = NULL)
                    388:     {
                    389:         try {
                    390:             $trace = debug_backtrace();
                    391:             $file = $trace[0]['file'];
                    392:             // this ensures that this is safe
                    393:             if (!in_array($file, get_included_files())) {
                    394:                 die('SECURITY ERROR: PHP_Archive::mapPhar can only be called from within ' .
                    395:                     'the phar that initiates it');
                    396:             }
                    397:             $file = realpath($file);
                    398:             if (!isset($dataoffset)) {
                    399:                 $dataoffset = constant('__COMPILER_HALT_OFFSET'.'__');
                    400:                 $fp = fopen($file, 'rb');
                    401:                 fseek($fp, $dataoffset, SEEK_SET);
                    402:                 $dataoffset = $dataoffset + self::_endOfStubLength(fread($fp, 5));
                    403:                 fclose($fp);
                    404:             }
                    405: 
                    406:             self::_mapPhar($file, $dataoffset);
                    407:         } catch (Exception $e) {
                    408:             die($e->getMessage());
                    409:         }
                    410:     }
                    411: 
                    412:     /**
                    413:      * Sub-function, allows recovery from errors
                    414:      *
                    415:      * @param unknown_type $file
                    416:      * @param unknown_type $dataoffset
                    417:      */
                    418:     private static function _mapPhar($file, $dataoffset, $alias = NULL)
                    419:     {
                    420:         $file = realpath($file);
                    421:         if (isset(self::$_manifest[$file])) {
                    422:             return;
                    423:         }
                    424:         if (!is_array(self::$_pharMapping)) {
                    425:             self::$_pharMapping = array();
                    426:         }
                    427:         $fp = fopen($file, 'rb');
                    428:         // seek to __HALT_COMPILER_OFFSET__
                    429:         fseek($fp, $dataoffset);
                    430:         $manifest_length = unpack('Vlen', fread($fp, 4));
                    431:         $manifest = '';
                    432:         $last = '1';
                    433:         while (strlen($last) && strlen($manifest) < $manifest_length['len']) {
                    434:             $read = 8192;
                    435:             if ($manifest_length['len'] - strlen($manifest) < 8192) {
                    436:                 $read = $manifest_length['len'] - strlen($manifest);
                    437:             }
                    438:             $last = fread($fp, $read);
                    439:             $manifest .= $last;
                    440:         }
                    441:         if (strlen($manifest) < $manifest_length['len']) {
                    442:             throw new Exception('ERROR: manifest length read was "' . 
                    443:                 strlen($manifest) .'" should be "' .
                    444:                 $manifest_length['len'] . '"');
                    445:         }
                    446:         $info = self::_unserializeManifest($manifest);
                    447:         if ($info['alias']) {
                    448:             $alias = $info['alias'];
                    449:             $explicit = true;
                    450:         } else {
                    451:             if (!isset($alias)) {
                    452:                 $alias = $file;
                    453:             }
                    454:             $explicit = false;
                    455:         }
                    456:         self::$_manifest[$file] = $info['manifest'];
                    457:         $compressed = $info['compressed'];
                    458:         self::$_fileStart[$file] = ftell($fp);
                    459:         fclose($fp);
                    460:         if ($compressed & 0x00001000) {
                    461:             if (!function_exists('gzinflate')) {
                    462:                 throw new Exception('Error: zlib extension is not enabled - gzinflate() function needed' .
                    463:                     ' for compressed .phars');
                    464:             }
                    465:         }
                    466:         if ($compressed & 0x00002000) {
                    467:             if (!function_exists('bzdecompress')) {
                    468:                 throw new Exception('Error: bzip2 extension is not enabled - bzdecompress() function needed' .
                    469:                     ' for compressed .phars');
                    470:             }
                    471:         }
                    472:         if (isset(self::$_pharMapping[$alias])) {
                    473:             throw new Exception('ERROR: PHP_Archive::mapPhar has already been called for alias "' .
                    474:                 $alias . '" cannot re-alias to "' . $file . '"');
                    475:         }
                    476:         self::$_pharMapping[$alias] = array($file, $compressed, $dataoffset, $explicit,
                    477:             $info['metadata']);
                    478:         self::$_pharFiles[$file] = $alias;
                    479:     }
                    480: 
                    481:     /**
                    482:      * extract the manifest into an internal array
                    483:      *
                    484:      * @param string $manifest
                    485:      * @return false|array
                    486:      */
                    487:     private static function _unserializeManifest($manifest)
                    488:     {
                    489:         // retrieve the number of files in the manifest
                    490:         $info = unpack('V', substr($manifest, 0, 4));
                    491:         $apiver = substr($manifest, 4, 2);
                    492:         $apiver = bin2hex($apiver);
                    493:         $apiver_dots = hexdec($apiver[0]) . '.' . hexdec($apiver[1]) . '.' . hexdec($apiver[2]);
                    494:         $majorcompat = hexdec($apiver[0]);
                    495:         $calcapi = explode('.', self::APIVersion());
                    496:         if ($calcapi[0] != $majorcompat) {
                    497:             throw new Exception('Phar is incompatible API version ' . $apiver_dots . ', but ' .
                    498:                 'PHP_Archive is API version '.self::APIVersion());
                    499:         }
                    500:         if ($calcapi[0] === '0') {
                    501:             if (self::APIVersion() != $apiver_dots) {
                    502:                 throw new Exception('Phar is API version ' . $apiver_dots .
                    503:                     ', but PHP_Archive is API version '.self::APIVersion(), E_USER_ERROR);
                    504:             }
                    505:         }
                    506:         $flags = unpack('V', substr($manifest, 6, 4));
                    507:         $ret = array('compressed' => $flags & 0x00003000);
                    508:         // signature is not verified by default in PHP_Archive, phar is better
                    509:         $ret['hassignature'] = $flags & 0x00010000;
                    510:         $aliaslen = unpack('V', substr($manifest, 10, 4));
                    511:         if ($aliaslen) {
                    512:             $ret['alias'] = substr($manifest, 14, $aliaslen[1]);
                    513:         } else {
                    514:             $ret['alias'] = false;
                    515:         }
                    516:         $manifest = substr($manifest, 14 + $aliaslen[1]);
                    517:         $metadatalen = unpack('V', substr($manifest, 0, 4));
                    518:         if ($metadatalen[1]) {
                    519:             $ret['metadata'] = unserialize(substr($manifest, 4, $metadatalen[1]));
                    520:             $manifest = substr($manifest, 4 + $metadatalen[1]);
                    521:         } else {
                    522:             $ret['metadata'] = null;
                    523:             $manifest = substr($manifest, 4);
                    524:         }
                    525:         $offset = 0;
                    526:         $start = 0;
                    527:         for ($i = 0; $i < $info[1]; $i++) {
                    528:             // length of the file name
                    529:             $len = unpack('V', substr($manifest, $start, 4));
                    530:             $start += 4;
                    531:             // file name
                    532:             $savepath = substr($manifest, $start, $len[1]);
                    533:             $start += $len[1];
                    534:             // retrieve manifest data:
                    535:             // 0 = uncompressed file size
                    536:             // 1 = timestamp of when file was added to phar
                    537:             // 2 = compressed filesize
                    538:             // 3 = crc32
                    539:             // 4 = flags
                    540:             // 5 = metadata length
                    541:             $ret['manifest'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($manifest, $start, 24)));
                    542:             $ret['manifest'][$savepath][3] = sprintf('%u', $ret['manifest'][$savepath][3]
                    543:                 & 0xffffffff);
                    544:             if ($ret['manifest'][$savepath][5]) {
                    545:                 $ret['manifest'][$savepath][6] = unserialize(substr($manifest, $start + 24,
                    546:                     $ret['manifest'][$savepath][5]));
                    547:             } else {
                    548:                 $ret['manifest'][$savepath][6] = null;
                    549:             }
                    550:             $ret['manifest'][$savepath][7] = $offset;
                    551:             $offset += $ret['manifest'][$savepath][2];
                    552:             $start += 24 + $ret['manifest'][$savepath][5];
                    553:         }
                    554:         return $ret;
                    555:     }
                    556: 
                    557:     /**
                    558:      * @param string
                    559:      */
                    560:     private static function processFile($path)
                    561:     {
                    562:         if ($path == '.') {
                    563:             return '';
                    564:         }
                    565:         $std = str_replace("\\", "/", $path);
                    566:         while ($std != ($std = ereg_replace("[^\/:?]+/\.\./", "", $std))) ;
                    567:         $std = str_replace("/./", "", $std);
                    568:         if (strlen($std) > 1 && $std[0] == '/') {
                    569:             $std = substr($std, 1);
                    570:         }
                    571:         if (strncmp($std, "./", 2) == 0) {
                    572:             return substr($std, 2);
                    573:         } else {
                    574:             return $std;
                    575:         }
                    576:     }
                    577: 
                    578:     /**
                    579:      * Seek in the master archive to a matching file or directory
                    580:      * @param string
                    581:      */
                    582:     protected function selectFile($path, $allowdirs = true)
                    583:     {
                    584:         $std = self::processFile($path);
                    585:         if (isset(self::$_manifest[$this->_archiveName][$path])) {
                    586:             $this->_setCurrentFile($path);
                    587:             return true;
                    588:         }
                    589:         if (!$allowdirs) {
                    590:             return 'Error: "' . $path . '" is not a file in phar "' . $this->_basename . '"';
                    591:         }
                    592:         foreach (self::$_manifest[$this->_archiveName] as $file => $info) {
                    593:             if (empty($std) ||
                    594:                   //$std is a directory
                    595:                   strncmp($std.'/', $path, strlen($std)+1) == 0) {
                    596:                 $this->currentFilename = $this->internalFileLength = $this->currentStat = null;
                    597:                 return true;
                    598:             }
                    599:         }
                    600:         return 'Error: "' . $path . '" not found in phar "' . $this->_basename . '"';
                    601:     }
                    602: 
                    603:     private function _setCurrentFile($path)
                    604:     {
                    605:         $this->currentStat = array(
                    606:             2 => 0100444, // file mode, readable by all, writeable by none
                    607:             4 => 0, // uid
                    608:             5 => 0, // gid
                    609:             7 => self::$_manifest[$this->_archiveName][$path][0], // size
                    610:             9 => self::$_manifest[$this->_archiveName][$path][1], // creation time
                    611:             );
                    612:         $this->currentFilename = $path;
                    613:         $this->internalFileLength = self::$_manifest[$this->_archiveName][$path][2];
                    614:         // seek to offset of file header within the .phar
                    615:         if (is_resource(@$this->fp)) {
                    616:             fseek($this->fp, self::$_fileStart[$this->_archiveName] + self::$_manifest[$this->_archiveName][$path][7]);
                    617:         }
                    618:     }
                    619: 
                    620:     private static function _fileExists($archive, $path)
                    621:     {
                    622:         return isset(self::$_manifest[$archive]) &&
                    623:             isset(self::$_manifest[$archive][$path]);
                    624:     }
                    625: 
                    626:     private static function _filesize($archive, $path)
                    627:     {
                    628:         return self::$_manifest[$archive][$path][0];
                    629:     }
                    630: 
                    631:     /**
                    632:      * Seek to a file within the master archive, and extract its contents
                    633:      * @param string
                    634:      * @return array|string an array containing an error message string is returned
                    635:      *                      upon error, otherwise the file contents are returned
                    636:      */
                    637:     public function extractFile($path)
                    638:     {
                    639:         $this->fp = @fopen($this->_archiveName, "rb");
                    640:         if (!$this->fp) {
                    641:             return array('Error: cannot open phar "' . $this->_archiveName . '"');
                    642:         }
                    643:         if (($e = $this->selectFile($path, false)) === true) {
                    644:             $data = '';
                    645:             $count = $this->internalFileLength;
                    646:             while ($count) {
                    647:                 if ($count < 8192) {
                    648:                     $data .= @fread($this->fp, $count);
                    649:                     $count = 0;
                    650:                 } else {
                    651:                     $count -= 8192;
                    652:                     $data .= @fread($this->fp, 8192);
                    653:                 }
                    654:             }
                    655:             @fclose($this->fp);
                    656:             if (self::$_manifest[$this->_archiveName][$path][4] & self::GZ) {
                    657:                 $data = gzinflate($data);
                    658:             } elseif (self::$_manifest[$this->_archiveName][$path][4] & self::BZ2) {
                    659:                 $data = bzdecompress($data);
                    660:             }
                    661:             if (!isset(self::$_manifest[$this->_archiveName][$path]['ok'])) {
                    662:                 if (strlen($data) != $this->currentStat[7]) {
                    663:                     return array("Not valid internal .phar file (size error {$size} != " .
                    664:                         $this->currentStat[7] . ")");
                    665:                 }
                    666:                 if (self::$_manifest[$this->_archiveName][$path][3] != sprintf("%u", crc32($data) & 0xffffffff)) {
                    667:                     return array("Not valid internal .phar file (checksum error)");
                    668:                 }
                    669:                 self::$_manifest[$this->_archiveName][$path]['ok'] = true;
                    670:             }
                    671:             return $data;
                    672:         } else {
                    673:             @fclose($this->fp);
                    674:             return array($e);
                    675:         }
                    676:     }
                    677: 
                    678:     /**
                    679:      * Parse urls like phar:///fullpath/to/my.phar/file.txt
                    680:      *
                    681:      * @param string $file
                    682:      * @return false|array
                    683:      */
                    684:     static protected function parseUrl($file)
                    685:     {
                    686:         if (substr($file, 0, 7) != 'phar://') {
                    687:             return false;
                    688:         }
                    689:         $file = substr($file, 7);
                    690:     
                    691:         $ret = array('scheme' => 'phar');
                    692:         $pos_p = strpos($file, '.phar.php');
                    693:         $pos_z = strpos($file, '.phar.gz');
                    694:         $pos_b = strpos($file, '.phar.bz2');
                    695:         if ($pos_p) {
                    696:             if ($pos_z) {
                    697:                 return false;
                    698:             }
                    699:             $ret['host'] = substr($file, 0, $pos_p + strlen('.phar.php'));
                    700:             $ret['path'] = substr($file, strlen($ret['host']));
                    701:         } elseif ($pos_z) {
                    702:             $ret['host'] = substr($file, 0, $pos_z + strlen('.phar.gz'));
                    703:             $ret['path'] = substr($file, strlen($ret['host']));
                    704:         } elseif ($pos_b) {
                    705:             $ret['host'] = substr($file, 0, $pos_z + strlen('.phar.bz2'));
                    706:             $ret['path'] = substr($file, strlen($ret['host']));
                    707:         } elseif (($pos_p = strpos($file, ".phar")) !== false) {
                    708:             $ret['host'] = substr($file, 0, $pos_p + strlen('.phar'));
                    709:             $ret['path'] = substr($file, strlen($ret['host']));
                    710:         } else {
                    711:             return false;
                    712:         }
                    713:         if (!$ret['path']) {
                    714:             $ret['path'] = '/';
                    715:         }
                    716:         return $ret;
                    717:     }
                    718:     
                    719:     /**
                    720:      * Locate the .phar archive in the include_path and detect the file to open within
                    721:      * the archive.
                    722:      *
                    723:      * Possible parameters are phar://pharname.phar/filename_within_phar.ext
                    724:      * @param string a file within the archive
                    725:      * @return string the filename within the .phar to retrieve
                    726:      */
                    727:     public function initializeStream($file)
                    728:     {
                    729:         $file = self::processFile($file);
                    730:         $info = @parse_url($file);
                    731:         if (!$info) {
                    732:             $info = self::parseUrl($file);
                    733:         }
                    734:         if (!$info) {
                    735:             return false;
                    736:         }
                    737:         if (!isset($info['host'])) {
                    738:             // malformed internal file
                    739:             return false;
                    740:         }
                    741:         if (!isset(self::$_pharFiles[$info['host']]) &&
                    742:               !isset(self::$_pharMapping[$info['host']])) {
                    743:             try {
                    744:                 self::loadPhar($info['host']);
                    745:                 // use alias from here out
                    746:                 $info['host'] = self::$_pharFiles[$info['host']];
                    747:             } catch (Exception $e) {
                    748:                 return false;
                    749:             }
                    750:         }
                    751:         if (!isset($info['path'])) {
                    752:             return false;
                    753:         } elseif (strlen($info['path']) > 1) {
                    754:             $info['path'] = substr($info['path'], 1);
                    755:         }
                    756:         if (isset(self::$_pharMapping[$info['host']])) {
                    757:             $this->_basename = $info['host'];
                    758:             $this->_archiveName = self::$_pharMapping[$info['host']][0];
                    759:             $this->_compressed = self::$_pharMapping[$info['host']][1];
                    760:         } elseif (isset(self::$_pharFiles[$info['host']])) {
                    761:             $this->_archiveName = $info['host'];
                    762:             $this->_basename = self::$_pharFiles[$info['host']];
                    763:             $this->_compressed = self::$_pharMapping[$this->_basename][1];
                    764:         }
                    765:         $file = $info['path'];
                    766:         return $file;
                    767:     }
                    768: 
                    769:     /**
                    770:      * Open the requested file - PHP streams API
                    771:      *
                    772:      * @param string $file String provided by the Stream wrapper
                    773:      * @access private
                    774:      */
                    775:     public function stream_open($file)
                    776:     {
                    777:         return $this->_streamOpen($file);
                    778:     }
                    779: 
                    780:     /**
                    781:      * @param string filename to opne, or directory name
                    782:      * @param bool if true, a directory will be matched, otherwise only files
                    783:      *             will be matched
                    784:      * @uses trigger_error()
                    785:      * @return bool success of opening
                    786:      * @access private
                    787:      */
                    788:     private function _streamOpen($file, $searchForDir = false)
                    789:     {
                    790:         $path = $this->initializeStream($file);
                    791:         if (!$path) {
                    792:             trigger_error('Error: Unknown phar in "' . $file . '"', E_USER_ERROR);
                    793:         }
                    794:         if (is_array($this->file = $this->extractFile($path))) {
                    795:             trigger_error($this->file[0], E_USER_ERROR);
                    796:             return false;
                    797:         }
                    798:         if ($path != $this->currentFilename) {
                    799:             if (!$searchForDir) {
                    800:                 trigger_error("Cannot open '$file', is a directory", E_USER_ERROR);
                    801:                 return false;
                    802:             } else {
                    803:                 $this->file = '';
                    804:                 return true;
                    805:             }
                    806:         }
                    807: 
                    808:         if (!is_null($this->file) && $this->file !== false) {
                    809:             return true;
                    810:         } else {
                    811:             return false;
                    812:         }
                    813:     }
                    814:     
                    815:     /**
                    816:      * Read the data - PHP streams API
                    817:      *
                    818:      * @param int
                    819:      * @access private
                    820:      */
                    821:     public function stream_read($count)
                    822:     {
                    823:         $ret = substr($this->file, $this->position, $count);
                    824:         $this->position += strlen($ret);
                    825:         return $ret;
                    826:     }
                    827:     
                    828:     /**
                    829:      * Whether we've hit the end of the file - PHP streams API
                    830:      * @access private
                    831:      */
                    832:     function stream_eof()
                    833:     {
                    834:         return $this->position >= $this->currentStat[7];
                    835:     }
                    836:     
                    837:     /**
                    838:      * For seeking the stream - PHP streams API
                    839:      * @param int
                    840:      * @param SEEK_SET|SEEK_CUR|SEEK_END
                    841:      * @access private
                    842:      */
                    843:     public function stream_seek($pos, $whence)
                    844:     {
                    845:         switch ($whence) {
                    846:             case SEEK_SET:
                    847:                 if ($pos < 0) {
                    848:                     return false;
                    849:                 }
                    850:                 $this->position = $pos;
                    851:                 break;
                    852:             case SEEK_CUR:
                    853:                 if ($pos + $this->currentStat[7] < 0) {
                    854:                     return false;
                    855:                 }
                    856:                 $this->position += $pos;
                    857:                 break;
                    858:             case SEEK_END:
                    859:                 if ($pos + $this->currentStat[7] < 0) {
                    860:                     return false;
                    861:                 }
                    862:                 $this->position = $pos + $this->currentStat[7];
                    863:                 break;
                    864:             default:
                    865:                 return false;
                    866:         }
                    867:         return true;
                    868:     }
                    869:     
                    870:     /**
                    871:      * The current position in the stream - PHP streams API
                    872:      * @access private
                    873:      */
                    874:     public function stream_tell()
                    875:     {
                    876:         return $this->position;
                    877:     }
                    878: 
                    879:     /**
                    880:      * The result of an fstat call, returns mod time from creation, and file size -
                    881:      * PHP streams API
                    882:      * @uses _stream_stat()
                    883:      * @access private
                    884:      */
                    885:     public function stream_stat()
                    886:     {
                    887:         return $this->_stream_stat();
                    888:     }
                    889: 
                    890:     /**
                    891:      * Retrieve statistics on a file or directory within the .phar
                    892:      * @param string file/directory to stat
                    893:      * @access private
                    894:      */
                    895:     public function _stream_stat($file = null)
                    896:     {
                    897:         $std = $file ? self::processFile($file) : $this->currentFilename;
                    898:         if ($file) {
                    899:             if (isset(self::$_manifest[$this->_archiveName][$file])) {
                    900:                 $this->_setCurrentFile($file);
                    901:                 $isdir = false;
                    902:             } else {
                    903:                 do {
                    904:                     $isdir = false;
                    905:                     if ($file == '/') {
                    906:                         break;
                    907:                     }
                    908:                     foreach (self::$_manifest[$this->_archiveName] as $path => $info) {
                    909:                         if (strpos($path, $file) === 0) {
                    910:                             if (strlen($path) > strlen($file) &&
                    911:                                   $path[strlen($file)] == '/') {
                    912:                                 break 2;
                    913:                             }
                    914:                         }
                    915:                     }
                    916:                     // no files exist and no directories match this string
                    917:                     return false;
                    918:                 } while (false);
                    919:                 $isdir = true;
                    920:             }
                    921:         } else {
                    922:             $isdir = false; // open streams must be files
                    923:         }
                    924:         $mode = $isdir ? 0040444 : 0100444;
                    925:         // 040000 = dir, 010000 = file
                    926:         // everything is readable, nothing is writeable
                    927:         return array(
                    928:            0, 0, $mode, 0, 0, 0, 0, 0, 0, 0, 0, 0, // non-associative indices
                    929:            'dev' => 0, 'ino' => 0,
                    930:            'mode' => $mode,
                    931:            'nlink' => 0, 'uid' => 0, 'gid' => 0, 'rdev' => 0, 'blksize' => 0, 'blocks' => 0,
                    932:            'size' => $this->currentStat[7],
                    933:            'atime' => $this->currentStat[9],
                    934:            'mtime' => $this->currentStat[9],
                    935:            'ctime' => $this->currentStat[9],
                    936:            );
                    937:     }
                    938: 
                    939:     /**
                    940:      * Stat a closed file or directory - PHP streams API
                    941:      * @param string
                    942:      * @param int
                    943:      * @access private
                    944:      */
                    945:     public function url_stat($url, $flags)
                    946:     {
                    947:         $path = $this->initializeStream($url);
                    948:         return $this->_stream_stat($path);
                    949:     }
                    950: 
                    951:     /**
                    952:      * Open a directory in the .phar for reading - PHP streams API
                    953:      * @param string directory name
                    954:      * @access private
                    955:      */
                    956:     public function dir_opendir($path)
                    957:     {
                    958:         $info = @parse_url($path);
                    959:         if (!$info) {
                    960:             $info = self::parseUrl($path);
                    961:             if (!$info) {
                    962:                 trigger_error('Error: "' . $path . '" is a file, and cannot be opened with opendir',
                    963:                     E_USER_ERROR);
                    964:                 return false;
                    965:             }
                    966:         }
                    967:         $path = !empty($info['path']) ?
                    968:             $info['host'] . $info['path'] : $info['host'] . '/';
                    969:         $path = $this->initializeStream('phar://' . $path);
                    970:         if (isset(self::$_manifest[$this->_archiveName][$path])) {
                    971:             trigger_error('Error: "' . $path . '" is a file, and cannot be opened with opendir',
                    972:                 E_USER_ERROR);
                    973:             return false;
                    974:         }
                    975:         if ($path == false) {
                    976:             trigger_error('Error: Unknown phar in "' . $file . '"', E_USER_ERROR);
                    977:             return false;
                    978:         }
                    979:         $this->fp = @fopen($this->_archiveName, "rb");
                    980:         if (!$this->fp) {
                    981:             trigger_error('Error: cannot open phar "' . $this->_archiveName . '"');
                    982:             return false;
                    983:         }
                    984:         $this->_dirFiles = array();
                    985:         foreach (self::$_manifest[$this->_archiveName] as $file => $info) {
                    986:             if ($path == '/') {
                    987:                 if (strpos($file, '/')) {
                    988:                     $a = explode('/', $file);
                    989:                     $this->_dirFiles[array_shift($a)] = true;
                    990:                 } else {
                    991:                     $this->_dirFiles[$file] = true;
                    992:                 }
                    993:             } elseif (strpos($file, $path) === 0) {
                    994:                 $fname = substr($file, strlen($path) + 1);
                    995:                 if (strpos($fname, '/')) {
                    996:                     // this is a directory
                    997:                     $a = explode('/', $fname);
                    998:                     $this->_dirFiles[array_shift($a)] = true;
                    999:                 } elseif ($file[strlen($path)] == '/') {
                   1000:                     // this is a file
                   1001:                     $this->_dirFiles[$fname] = true;
                   1002:                 }
                   1003:             }
                   1004:         }
                   1005:         @fclose($this->fp);
                   1006:         if (!count($this->_dirFiles)) {
                   1007:             return false;
                   1008:         }
                   1009:         @uksort($this->_dirFiles, 'strnatcmp');
                   1010:         return true;
                   1011:     }
                   1012: 
                   1013:     /**
                   1014:      * Read the next directory entry - PHP streams API
                   1015:      * @access private
                   1016:      */
                   1017:     public function dir_readdir()
                   1018:     {
                   1019:         $ret = key($this->_dirFiles);
                   1020:         @next($this->_dirFiles);
                   1021:         if (!$ret) {
                   1022:             return false;
                   1023:         }
                   1024:         return $ret;
                   1025:     }
                   1026: 
                   1027:     /**
                   1028:      * Close a directory handle opened with opendir() - PHP streams API
                   1029:      * @access private
                   1030:      */
                   1031:     public function dir_closedir()
                   1032:     {
                   1033:         $this->_dirFiles = array();
                   1034:         return true;
                   1035:     }
                   1036: 
                   1037:     /**
                   1038:      * Rewind to the first directory entry - PHP streams API
                   1039:      * @access private
                   1040:      */
                   1041:     public function dir_rewinddir()
                   1042:     {
                   1043:         @reset($this->_dirFiles);
                   1044:         return true;
                   1045:     }
                   1046: 
                   1047:     /**
                   1048:      * API version of this class
                   1049:      * @return string
                   1050:      */
                   1051:     public static final function APIVersion()
                   1052:     {
                   1053:         return '1.0.0';
                   1054:     }
                   1055: 
                   1056:     /**
                   1057:      * Retrieve Phar-specific metadata for a Phar archive
                   1058:      *
                   1059:      * @param string $phar full path to Phar archive, or alias
                   1060:      * @return null|mixed The value that was serialized for the Phar
                   1061:      *                    archive's metadata
                   1062:      * @throws Exception
                   1063:      */
                   1064:     public static function getPharMetadata($phar)
                   1065:     {
                   1066:         if (isset(self::$_pharFiles[$phar])) {
                   1067:             $phar = self::$_pharFiles[$phar];
                   1068:         }
                   1069:         if (!isset(self::$_pharMapping[$phar])) {
                   1070:             throw new Exception('Unknown Phar archive: "' . $phar . '"');
                   1071:         }
                   1072:         return self::$_pharMapping[$phar][4];
                   1073:     }
                   1074: 
                   1075:     /**
                   1076:      * Retrieve File-specific metadata for a Phar archive file
                   1077:      *
                   1078:      * @param string $phar full path to Phar archive, or alias
                   1079:      * @param string $file relative path to file within Phar archive
                   1080:      * @return null|mixed The value that was serialized for the Phar
                   1081:      *                    archive's metadata
                   1082:      * @throws Exception
                   1083:      */
                   1084:     public static function getFileMetadata($phar, $file)
                   1085:     {
                   1086:         if (!isset(self::$_pharFiles[$phar])) {
                   1087:             if (!isset(self::$_pharMapping[$phar])) {
                   1088:                 throw new Exception('Unknown Phar archive: "' . $phar . '"');
                   1089:             }
                   1090:             $phar = self::$_pharMapping[$phar][0];
                   1091:         }
                   1092:         if (!isset(self::$_manifest[$phar])) {
                   1093:             throw new Exception('Unknown Phar: "' . $phar . '"');
                   1094:         }
                   1095:         $file = self::processFile($file);
                   1096:         if (!isset(self::$_manifest[$phar][$file])) {
                   1097:             throw new Exception('Unknown file "' . $file . '" within Phar "'. $phar . '"');
                   1098:         }
                   1099:         return self::$_manifest[$phar][$file][6];
                   1100:     }
                   1101: 
                   1102:     /**
                   1103:      * @return list of supported signature algorithmns.
                   1104:      */
                   1105:     public static function getsupportedsignatures()
                   1106:     {
                   1107:         $ret = array('MD5', 'SHA-1');
                   1108:         if (extension_loaded('hash')) {
                   1109:             $ret[] = 'SHA-256';
                   1110:             $ret[] = 'SHA-512';
                   1111:         }
                   1112:         return $ret;
                   1113:     }
                   1114: }}
                   1115: if (!class_exists('Phar')) {
                   1116:     PHP_Archive::mapPhar(null, 42421                   );
                   1117: } else {
                   1118:     try {
                   1119:         Phar::mapPhar();
                   1120:     } catch (Exception $e) {
                   1121:         echo $e->getMessage();
                   1122:     }
                   1123: }
                   1124: if (class_exists('PHP_Archive') && !in_array('phar', stream_get_wrappers())) {
                   1125:     stream_wrapper_register('phar', 'PHP_Archive');
                   1126: }
                   1127: 
                   1128: @ini_set('memory_limit', -1);
                   1129: if (extension_loaded('phar')) {if (isset($_SERVER) && isset($_SERVER['REQUEST_URI'])) {
                   1130:     $uri = parse_url($_SERVER['REQUEST_URI']);
                   1131:     $archive = realpath($_SERVER['SCRIPT_FILENAME']);
                   1132:     $subpath = str_replace('/' . basename($archive), '', $uri['path']);
                   1133:     $mimetypes = array (
                   1134:   'aif' => 'audio/x-aiff',
                   1135:   'aiff' => 'audio/x-aiff',
                   1136:   'arc' => 'application/octet-stream',
                   1137:   'arj' => 'application/octet-stream',
                   1138:   'art' => 'image/x-jg',
                   1139:   'asf' => 'video/x-ms-asf',
                   1140:   'asx' => 'video/x-ms-asf',
                   1141:   'avi' => 'video/avi',
                   1142:   'bin' => 'application/octet-stream',
                   1143:   'bm' => 'image/bmp',
                   1144:   'bmp' => 'image/bmp',
                   1145:   'bz2' => 'application/x-bzip2',
                   1146:   'css' => 'text/css',
                   1147:   'doc' => 'application/msword',
                   1148:   'dot' => 'application/msword',
                   1149:   'dv' => 'video/x-dv',
                   1150:   'dvi' => 'application/x-dvi',
                   1151:   'eps' => 'application/postscript',
                   1152:   'exe' => 'application/octet-stream',
                   1153:   'gif' => 'image/gif',
                   1154:   'gz' => 'application/x-gzip',
                   1155:   'gzip' => 'application/x-gzip',
                   1156:   'htm' => 'text/html',
                   1157:   'html' => 'text/html',
                   1158:   'ico' => 'image/x-icon',
                   1159:   'jpe' => 'image/jpeg',
                   1160:   'jpg' => 'image/jpeg',
                   1161:   'jpeg' => 'image/jpeg',
                   1162:   'js' => 'application/x-javascript',
                   1163:   'log' => 'text/plain',
                   1164:   'mid' => 'audio/x-midi',
                   1165:   'mov' => 'video/quicktime',
                   1166:   'mp2' => 'audio/mpeg',
                   1167:   'mp3' => 'audio/mpeg3',
                   1168:   'mpg' => 'audio/mpeg',
                   1169:   'pdf' => 'aplication/pdf',
                   1170:   'png' => 'image/png',
                   1171:   'rtf' => 'application/rtf',
                   1172:   'tif' => 'image/tiff',
                   1173:   'tiff' => 'image/tiff',
                   1174:   'txt' => 'text/plain',
                   1175:   'xml' => 'text/xml',
                   1176: );
                   1177:     $phpfiles = array (
                   1178:   'php' => true,
                   1179: );
                   1180:     $phpsfiles = array (
                   1181:   'phps' => true,
                   1182: );
                   1183:     $deny = array (
                   1184:   0 => '/.+\\.inc$/',
                   1185: );
                   1186:     $subpath = str_replace('/' . basename($archive), '', $uri['path']);
                   1187:     if (!$subpath || $subpath == '/') {
                   1188:         $subpath = '/PEAR.php';
                   1189:     }
                   1190:     if ($subpath[0] != '/') {
                   1191:         $subpath = '/' . $subpath;
                   1192:     }
                   1193:     if (!@file_exists('phar://' . $archive . $subpath)) {
                   1194:         header("HTTP/1.0 404 Not Found");
                   1195:         exit;
                   1196:     }
                   1197: 
                   1198:     foreach ($deny as $pattern) {
                   1199:         if (preg_match($pattern, $subpath)) {
                   1200:             header("HTTP/1.0 404 Not Found");
                   1201:             exit;
                   1202:         }
                   1203:     }
                   1204:     $inf = pathinfo(basename($subpath));
                   1205:     if (!isset($inf['extension'])) {
                   1206:         header('Content-Type: text/plain');
                   1207:         header('Content-Length: ' . filesize('phar://' . $archive . $subpath));
                   1208:         readfile('phar://' . $archive . $subpath);
                   1209:         exit;
                   1210:     }
                   1211:     if (isset($phpfiles[$inf['extension']])) {
                   1212:         include 'phar://' . $archive . '/' . $subpath;
                   1213:         exit;
                   1214:     }
                   1215:     if (isset($mimetypes[$inf['extension']])) {
                   1216:         header('Content-Type: ' . $mimetypes[$inf['extension']]);
                   1217:         header('Content-Length: ' . filesize('phar://' . $archive . $subpath));
                   1218:         readfile('phar://' . $archive . $subpath);
                   1219:         exit;
                   1220:     }
                   1221:     if (isset($phpsfiles[$inf['extension']])) {
                   1222:         header('Content-Type: text/html');
                   1223:         $c = highlight_file('phar://' . $archive . $subpath, true);
                   1224:         header('Content-Length: ' . strlen($c));
                   1225:         echo $c;
                   1226:         exit;
                   1227:     }
                   1228:     header('Content-Type: text/plain');
                   1229:     header('Content-Length: ' . filesize('phar://' . $archive . '/' . $subpath));
                   1230:     readfile('phar://' . $archive . '/' . $subpath);
                   1231:     exit;
                   1232: }} else {if (!empty($_SERVER['REQUEST_URI'])) {PHP_Archive::webFrontController('PEAR.php');exit;}}
                   1233: 
                   1234: 
                   1235: 
                   1236: require_once 'phar://install-pear-nozlib.phar/index.php';
1.1.1.2 ! misho    1237: __HALT_COMPILER();\k&install-pear-nozlib.pharArchive/Tar.php£&³PQ£&ñÊ|Om&Archive_Tar-1.3.11.tar„&³PQ„&, Öm&Console/Getopt.phpÂ4³PQÂ4èÌl1m&Console_Getopt-1.3.1.tarT³PQTΞm&        index.phpm*³PQm*emäm&OS/Guess.phpÁ)³PQÁ)LO„m&PEAR-1.9.4.tarˆ³PQˆ3]åm&PEAR.php³„³PQ³„ï›Jsm&PEAR/Autoloader.phpï³PQï¶¤m&PEAR/Builder.phpöA³PQöA¹thm&PEAR/ChannelFile.phpîdzPQîÇ&êMom&PEAR/ChannelFile/Parser.php<³PQ<IŽ$äm&PEAR/Command.php
        !          1238: 2³PQ
        !          1239: 2%´ÉCm&PEAR/Command/Auth.phpƒ
        !          1240: ³PQƒ
        !          1241: s`.m&PEAR/Command/Auth.xml̳PQÌå4™{m&PEAR/Command/Build.phpu     ³PQu ¯W(   m&PEAR/Command/Build.xml&³PQ&ºcªm&PEAR/Command/Channels.php'„³PQ'„»Ÿêm&PEAR/Command/Channels.xmlz³PQzâwƒŽm&PEAR/Command/Common.php‰ ³PQ‰ —dMÁm&PEAR/Command/Config.php“<³PQ“<ž`m&PEAR/Command/Config.xml6
³PQ6
²«øsm&PEAR/Command/Install.php2dzPQ2ÇbÔžCm&PEAR/Command/Install.xml~!³PQ~!2¡Vm&PEAR/Command/Mirror.php³PQp³7m&PEAR/Command/Mirror.xmli³PQiÝ„<m&PEAR/Command/Package.phpšž³PQšž®õCm&PEAR/Command/Package.xml6³PQ6Z hm&PEAR/Command/Pickle.php'?³PQ'?þå[Vm&PEAR/Command/Pickle.xml›³PQ›dÖ£Sm&PEAR/Command/Registry.php}µ³PQ}µ„:£m&PEAR/Command/Registry.xmlþ³PQþÿøêum&PEAR/Command/Remote.php
        !          1242: v³PQ
        !          1243: v[/7<m&PEAR/Command/Remote.xmlï³PQï
ó\ûm&PEAR/Command/Test.phpJ/³PQJ/pï m&PEAR/Command/Test.xmli³PQi—%Fm&PEAR/Common.phpf³PQfd\€ém&PEAR/Config.php-
        !          1244: &³PQ-
        !          1245: &Áâ>Òm&PEAR/Dependency2.phpƳPQÆÕŒFm&PEAR/DependencyDB.phpø^³PQø^<©°m&PEAR/Downloader.php&³PQ&@CŸum&PEAR/Downloader/Package.php©*&³PQ©*&9ãæém&PEAR/ErrorStack.php΄³PQ΄–qa6m&PEAR/Exception.php¶6³PQ¶6,€—m&PEAR/FixPHP5PEARWarnings.php™³PQ™ßq‚Cm&PEAR/Frontend.phpd³PQdò3/.m&PEAR/Frontend/CLI.php³d³PQ³dËxÕ}m&PEAR/Installer.phpù&³PQù&ø_m&PEAR/Installer/Role.php£³PQ£YñÐ*m&PEAR/Installer/Role/Cfg.php³PQ¸©ïm&PEAR/Installer/Role/Cfg.xml¥&³PQ¥&äì/m&PEAR/Installer/Role/Common.php›³PQ›&÷Ïm&PEAR/Installer/Role/Data.phpS³PQS·ÜŒm&PEAR/Installer/Role/Data.xml’&³PQ’&fszm&PEAR/Installer/Role/Doc.phpP³PQP_ˆ°/m&PEAR/Installer/Role/Doc.xml‘&³PQ‘&h&P*m&PEAR/Installer/Role/Ext.phpP³PQP^zÞwm&PEAR/Installer/Role/Ext.xmlB&³PQB&ÃìÆm&PEAR/Installer/Role/Php.phpP³PQPËÊsçm&PEAR/Installer/Role/Php.xml­&³PQ­&zqm&PEAR/Installer/Role/Script.phpY³PQY¼2"m&PEAR/Installer/Role/Script.xml°&³PQ°&@v§Ðm&PEAR/Installer/Role/Src.phpµ³PQµð¶£m&PEAR/Installer/Role/Src.xml"&³PQ"&püÃm&PEAR/Installer/Role/Test.phpS³PQS‡xÙ_m&PEAR/Installer/Role/Test.xml’&³PQ’&B] m&PEAR/Installer/Role/Www.phpL³PQLÊam&PEAR/Installer/Role/Www.xml¤&³PQ¤&>1HŠm&PEAR/PackageFile.phpæ>³PQæ>ÄTÊm&!PEAR/PackageFile/Generator/v1.phpvųPQvŵAw×m&!PEAR/PackageFile/Generator/v2.php_ƒ³PQ_ƒ¤k9am&PEAR/PackageFile/Parser/v1.phpò@³PQò@;#Þm&PEAR/PackageFile/Parser/v2.phpØ³PQØÌÝØm&PEAR/PackageFile/v1.php_ȳPQ_ÈÕÛæÏm&PEAR/PackageFile/v2.phpo&³PQo&žˆR¨m&PEAR/PackageFile/v2/rw.php­ö³PQ­öX;¼m&!PEAR/PackageFile/v2/Validator.phpiP&³PQiP&y©%m&PEAR/Packager.phpسPQØuwŠm&PEAR/Registry.php8+&³PQ8+&>´ m&
PEAR/REST.php™C³PQ™C©Yølm&PEAR/REST/10.phpC€³PQC€ÜE%Wm&PEAR/REST/11.phpv,³PQv,ºýgsm&PEAR/REST/13.php®-³PQ®-A±Km&PEAR/RunTest.phpñ³PQñ¬UÝ9m&PEAR/Start.phpÍ7³PQÍ7 ø}#m&PEAR/Start/CLI.phpmR³PQmRãFÆm&PEAR/Task/Common.php³PQÁpMÕm&PEAR/Task/Postinstallscript.phpœ8³PQœ8…Úwm&"PEAR/Task/Postinstallscript/rw.phpî³PQîâçŒSm&PEAR/Task/Replace.php¿³PQ¿ƒ²\m&PEAR/Task/Replace/rw.phpr³PQrÉÍÕm&PEAR/Task/Unixeol.php  ³PQ LÕ™%m&PEAR/Task/Unixeol/rw.php‚³PQ‚ÇuL m&PEAR/Task/Windowseol.php ³PQ ´WJm&PEAR/Task/Windowseol/rw.php—³PQ—h²m&PEAR/Validate.phpwV³PQwV²Ÿ>m&PEAR/Validator/PECL.php¢³PQ¢b¤¯nm&PEAR/XMLParser.phpK³PQK¿Ž„m&     PEAR5.php?³PQ?ßxÊm&Structures/Graph.php½³PQ½rÀ*m&,Structures/Graph/Manipulator/AcyclicTest.phpß³PQß1sÏm&2Structures/Graph/Manipulator/TopologicalSorter.phpº³PQº¥Eûm&Structures/Graph/Node.phpr+³PQr+ûD_m&Structures_Graph-1.0.4.tar,³PQ,‰”f‘m&
        !          1246: System.php]O³PQ]OyÔ½m&XML/Util.php
w³PQ
w¢‚om&XML_Util-1.2.1.tarâ&³PQâ&7l \m&<?php
1.1       misho    1247: /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
                   1248: 
                   1249: /**
                   1250:  * File::CSV
                   1251:  *
                   1252:  * PHP versions 4 and 5
                   1253:  *
                   1254:  * Copyright (c) 1997-2008,
                   1255:  * Vincent Blavet <vincent@phpconcept.net>
                   1256:  * All rights reserved.
                   1257:  *
                   1258:  * Redistribution and use in source and binary forms, with or without
                   1259:  * modification, are permitted provided that the following conditions are met:
                   1260:  *
                   1261:  *     * Redistributions of source code must retain the above copyright notice,
                   1262:  *       this list of conditions and the following disclaimer.
                   1263:  *     * Redistributions in binary form must reproduce the above copyright
                   1264:  *       notice, this list of conditions and the following disclaimer in the
                   1265:  *       documentation and/or other materials provided with the distribution.
                   1266:  *
                   1267:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
                   1268:  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                   1269:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                   1270:  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
                   1271:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                   1272:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                   1273:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
                   1274:  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
                   1275:  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
                   1276:  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                   1277:  *
                   1278:  * @category  File_Formats
                   1279:  * @package   Archive_Tar
                   1280:  * @author    Vincent Blavet <vincent@phpconcept.net>
                   1281:  * @copyright 1997-2010 The Authors
                   1282:  * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    1283:  * @version   CVS: $Id$
1.1       misho    1284:  * @link      http://pear.php.net/package/Archive_Tar
                   1285:  */
                   1286: 
                   1287: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   1288: 
                   1289: define('ARCHIVE_TAR_ATT_SEPARATOR', 90001);
                   1290: define('ARCHIVE_TAR_END_BLOCK', pack("a512", ''));
                   1291: 
                   1292: /**
                   1293: * Creates a (compressed) Tar archive
                   1294: *
                   1295: * @package Archive_Tar
                   1296: * @author  Vincent Blavet <vincent@phpconcept.net>
                   1297: * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    1298: * @version $Revision$
1.1       misho    1299: */
                   1300: class Archive_Tar extends PEAR
                   1301: {
                   1302:     /**
                   1303:     * @var string Name of the Tar
                   1304:     */
                   1305:     var $_tarname='';
                   1306: 
                   1307:     /**
                   1308:     * @var boolean if true, the Tar file will be gzipped
                   1309:     */
                   1310:     var $_compress=false;
                   1311: 
                   1312:     /**
                   1313:     * @var string Type of compression : 'none', 'gz' or 'bz2'
                   1314:     */
                   1315:     var $_compress_type='none';
                   1316: 
                   1317:     /**
                   1318:     * @var string Explode separator
                   1319:     */
                   1320:     var $_separator=' ';
                   1321: 
                   1322:     /**
                   1323:     * @var file descriptor
                   1324:     */
                   1325:     var $_file=0;
                   1326: 
                   1327:     /**
                   1328:     * @var string Local Tar name of a remote Tar (http:// or ftp://)
                   1329:     */
                   1330:     var $_temp_tarname='';
                   1331: 
                   1332:     /**
                   1333:     * @var string regular expression for ignoring files or directories
                   1334:     */
                   1335:     var $_ignore_regexp='';
                   1336: 
                   1337:     /**
                   1338:      * @var object PEAR_Error object
                   1339:      */
                   1340:     var $error_object=null; 
                   1341: 
                   1342:     // {{{ constructor
                   1343:     /**
                   1344:     * Archive_Tar Class constructor. This flavour of the constructor only
                   1345:     * declare a new Archive_Tar object, identifying it by the name of the
                   1346:     * tar file.
                   1347:     * If the compress argument is set the tar will be read or created as a
                   1348:     * gzip or bz2 compressed TAR file.
                   1349:     *
                   1350:     * @param string $p_tarname  The name of the tar archive to create
                   1351:     * @param string $p_compress can be null, 'gz' or 'bz2'. This
                   1352:     *               parameter indicates if gzip or bz2 compression
                   1353:     *               is required.  For compatibility reason the
                   1354:     *               boolean value 'true' means 'gz'.
                   1355:     *
                   1356:     * @access public
                   1357:     */
                   1358:     function Archive_Tar($p_tarname, $p_compress = null)
                   1359:     {
                   1360:         $this->PEAR();
                   1361:         $this->_compress = false;
                   1362:         $this->_compress_type = 'none';
                   1363:         if (($p_compress === null) || ($p_compress == '')) {
                   1364:             if (@file_exists($p_tarname)) {
                   1365:                 if ($fp = @fopen($p_tarname, "rb")) {
                   1366:                     // look for gzip magic cookie
                   1367:                     $data = fread($fp, 2);
                   1368:                     fclose($fp);
                   1369:                     if ($data == "\37\213") {
                   1370:                         $this->_compress = true;
                   1371:                         $this->_compress_type = 'gz';
                   1372:                         // No sure it's enought for a magic code ....
                   1373:                     } elseif ($data == "BZ") {
                   1374:                         $this->_compress = true;
                   1375:                         $this->_compress_type = 'bz2';
                   1376:                     }
                   1377:                 }
                   1378:             } else {
                   1379:                 // probably a remote file or some file accessible
                   1380:                 // through a stream interface
                   1381:                 if (substr($p_tarname, -2) == 'gz') {
                   1382:                     $this->_compress = true;
                   1383:                     $this->_compress_type = 'gz';
                   1384:                 } elseif ((substr($p_tarname, -3) == 'bz2') ||
                   1385:                           (substr($p_tarname, -2) == 'bz')) {
                   1386:                     $this->_compress = true;
                   1387:                     $this->_compress_type = 'bz2';
                   1388:                 }
                   1389:             }
                   1390:         } else {
                   1391:             if (($p_compress === true) || ($p_compress == 'gz')) {
                   1392:                 $this->_compress = true;
                   1393:                 $this->_compress_type = 'gz';
                   1394:             } else if ($p_compress == 'bz2') {
                   1395:                 $this->_compress = true;
                   1396:                 $this->_compress_type = 'bz2';
                   1397:             } else {
                   1398:                 $this->_error("Unsupported compression type '$p_compress'\n".
                   1399:                     "Supported types are 'gz' and 'bz2'.\n");
                   1400:                 return false;
                   1401:             }
                   1402:         }
                   1403:         $this->_tarname = $p_tarname;
                   1404:         if ($this->_compress) { // assert zlib or bz2 extension support
                   1405:             if ($this->_compress_type == 'gz')
                   1406:                 $extname = 'zlib';
                   1407:             else if ($this->_compress_type == 'bz2')
                   1408:                 $extname = 'bz2';
                   1409: 
                   1410:             if (!extension_loaded($extname)) {
                   1411:                 PEAR::loadExtension($extname);
                   1412:             }
                   1413:             if (!extension_loaded($extname)) {
                   1414:                 $this->_error("The extension '$extname' couldn't be found.\n".
                   1415:                     "Please make sure your version of PHP was built ".
                   1416:                     "with '$extname' support.\n");
                   1417:                 return false;
                   1418:             }
                   1419:         }
                   1420:     }
                   1421:     // }}}
                   1422: 
                   1423:     // {{{ destructor
                   1424:     function _Archive_Tar()
                   1425:     {
                   1426:         $this->_close();
                   1427:         // ----- Look for a local copy to delete
                   1428:         if ($this->_temp_tarname != '')
                   1429:             @unlink($this->_temp_tarname);
                   1430:         $this->_PEAR();
                   1431:     }
                   1432:     // }}}
                   1433: 
                   1434:     // {{{ create()
                   1435:     /**
                   1436:     * This method creates the archive file and add the files / directories
                   1437:     * that are listed in $p_filelist.
                   1438:     * If a file with the same name exist and is writable, it is replaced
                   1439:     * by the new tar.
                   1440:     * The method return false and a PEAR error text.
                   1441:     * The $p_filelist parameter can be an array of string, each string
                   1442:     * representing a filename or a directory name with their path if
                   1443:     * needed. It can also be a single string with names separated by a
                   1444:     * single blank.
                   1445:     * For each directory added in the archive, the files and
                   1446:     * sub-directories are also added.
                   1447:     * See also createModify() method for more details.
                   1448:     *
                   1449:     * @param array $p_filelist An array of filenames and directory names, or a
                   1450:     *              single string with names separated by a single
                   1451:     *              blank space.
                   1452:     *
                   1453:     * @return true on success, false on error.
                   1454:     * @see    createModify()
                   1455:     * @access public
                   1456:     */
                   1457:     function create($p_filelist)
                   1458:     {
                   1459:         return $this->createModify($p_filelist, '', '');
                   1460:     }
                   1461:     // }}}
                   1462: 
                   1463:     // {{{ add()
                   1464:     /**
                   1465:     * This method add the files / directories that are listed in $p_filelist in
                   1466:     * the archive. If the archive does not exist it is created.
                   1467:     * The method return false and a PEAR error text.
                   1468:     * The files and directories listed are only added at the end of the archive,
                   1469:     * even if a file with the same name is already archived.
                   1470:     * See also createModify() method for more details.
                   1471:     *
                   1472:     * @param array $p_filelist An array of filenames and directory names, or a
                   1473:     *              single string with names separated by a single
                   1474:     *              blank space.
                   1475:     *
                   1476:     * @return true on success, false on error.
                   1477:     * @see    createModify()
                   1478:     * @access public
                   1479:     */
                   1480:     function add($p_filelist)
                   1481:     {
                   1482:         return $this->addModify($p_filelist, '', '');
                   1483:     }
                   1484:     // }}}
                   1485: 
                   1486:     // {{{ extract()
1.1.1.2 ! misho    1487:     function extract($p_path='', $p_preserve=false)
1.1       misho    1488:     {
1.1.1.2 ! misho    1489:         return $this->extractModify($p_path, '', $p_preserve);
1.1       misho    1490:     }
                   1491:     // }}}
                   1492: 
                   1493:     // {{{ listContent()
                   1494:     function listContent()
                   1495:     {
                   1496:         $v_list_detail = array();
                   1497: 
                   1498:         if ($this->_openRead()) {
                   1499:             if (!$this->_extractList('', $v_list_detail, "list", '', '')) {
                   1500:                 unset($v_list_detail);
                   1501:                 $v_list_detail = 0;
                   1502:             }
                   1503:             $this->_close();
                   1504:         }
                   1505: 
                   1506:         return $v_list_detail;
                   1507:     }
                   1508:     // }}}
                   1509: 
                   1510:     // {{{ createModify()
                   1511:     /**
                   1512:     * This method creates the archive file and add the files / directories
                   1513:     * that are listed in $p_filelist.
                   1514:     * If the file already exists and is writable, it is replaced by the
                   1515:     * new tar. It is a create and not an add. If the file exists and is
                   1516:     * read-only or is a directory it is not replaced. The method return
                   1517:     * false and a PEAR error text.
                   1518:     * The $p_filelist parameter can be an array of string, each string
                   1519:     * representing a filename or a directory name with their path if
                   1520:     * needed. It can also be a single string with names separated by a
                   1521:     * single blank.
                   1522:     * The path indicated in $p_remove_dir will be removed from the
                   1523:     * memorized path of each file / directory listed when this path
                   1524:     * exists. By default nothing is removed (empty path '')
                   1525:     * The path indicated in $p_add_dir will be added at the beginning of
                   1526:     * the memorized path of each file / directory listed. However it can
                   1527:     * be set to empty ''. The adding of a path is done after the removing
                   1528:     * of path.
                   1529:     * The path add/remove ability enables the user to prepare an archive
                   1530:     * for extraction in a different path than the origin files are.
                   1531:     * See also addModify() method for file adding properties.
                   1532:     *
                   1533:     * @param array  $p_filelist   An array of filenames and directory names,
                   1534:     *                             or a single string with names separated by
                   1535:     *                             a single blank space.
                   1536:     * @param string $p_add_dir    A string which contains a path to be added
                   1537:     *                             to the memorized path of each element in
                   1538:     *                             the list.
                   1539:     * @param string $p_remove_dir A string which contains a path to be
                   1540:     *                             removed from the memorized path of each
                   1541:     *                             element in the list, when relevant.
                   1542:     *
                   1543:     * @return boolean true on success, false on error.
                   1544:     * @access public
                   1545:     * @see addModify()
                   1546:     */
                   1547:     function createModify($p_filelist, $p_add_dir, $p_remove_dir='')
                   1548:     {
                   1549:         $v_result = true;
                   1550: 
                   1551:         if (!$this->_openWrite())
                   1552:             return false;
                   1553: 
                   1554:         if ($p_filelist != '') {
                   1555:             if (is_array($p_filelist))
                   1556:                 $v_list = $p_filelist;
                   1557:             elseif (is_string($p_filelist))
                   1558:                 $v_list = explode($this->_separator, $p_filelist);
                   1559:             else {
                   1560:                 $this->_cleanFile();
                   1561:                 $this->_error('Invalid file list');
                   1562:                 return false;
                   1563:             }
                   1564: 
                   1565:             $v_result = $this->_addList($v_list, $p_add_dir, $p_remove_dir);
                   1566:         }
                   1567: 
                   1568:         if ($v_result) {
                   1569:             $this->_writeFooter();
                   1570:             $this->_close();
                   1571:         } else
                   1572:             $this->_cleanFile();
                   1573: 
                   1574:         return $v_result;
                   1575:     }
                   1576:     // }}}
                   1577: 
                   1578:     // {{{ addModify()
                   1579:     /**
                   1580:     * This method add the files / directories listed in $p_filelist at the
                   1581:     * end of the existing archive. If the archive does not yet exists it
                   1582:     * is created.
                   1583:     * The $p_filelist parameter can be an array of string, each string
                   1584:     * representing a filename or a directory name with their path if
                   1585:     * needed. It can also be a single string with names separated by a
                   1586:     * single blank.
                   1587:     * The path indicated in $p_remove_dir will be removed from the
                   1588:     * memorized path of each file / directory listed when this path
                   1589:     * exists. By default nothing is removed (empty path '')
                   1590:     * The path indicated in $p_add_dir will be added at the beginning of
                   1591:     * the memorized path of each file / directory listed. However it can
                   1592:     * be set to empty ''. The adding of a path is done after the removing
                   1593:     * of path.
                   1594:     * The path add/remove ability enables the user to prepare an archive
                   1595:     * for extraction in a different path than the origin files are.
                   1596:     * If a file/dir is already in the archive it will only be added at the
                   1597:     * end of the archive. There is no update of the existing archived
                   1598:     * file/dir. However while extracting the archive, the last file will
                   1599:     * replace the first one. This results in a none optimization of the
                   1600:     * archive size.
                   1601:     * If a file/dir does not exist the file/dir is ignored. However an
                   1602:     * error text is send to PEAR error.
                   1603:     * If a file/dir is not readable the file/dir is ignored. However an
                   1604:     * error text is send to PEAR error.
                   1605:     *
                   1606:     * @param array  $p_filelist   An array of filenames and directory
                   1607:     *                             names, or a single string with names
                   1608:     *                             separated by a single blank space.
                   1609:     * @param string $p_add_dir    A string which contains a path to be
                   1610:     *                             added to the memorized path of each
                   1611:     *                             element in the list.
                   1612:     * @param string $p_remove_dir A string which contains a path to be
                   1613:     *                             removed from the memorized path of
                   1614:     *                             each element in the list, when
                   1615:     *                             relevant.
                   1616:     *
                   1617:     * @return true on success, false on error.
                   1618:     * @access public
                   1619:     */
                   1620:     function addModify($p_filelist, $p_add_dir, $p_remove_dir='')
                   1621:     {
                   1622:         $v_result = true;
                   1623: 
                   1624:         if (!$this->_isArchive())
                   1625:             $v_result = $this->createModify($p_filelist, $p_add_dir,
                   1626:                                             $p_remove_dir);
                   1627:         else {
                   1628:             if (is_array($p_filelist))
                   1629:                 $v_list = $p_filelist;
                   1630:             elseif (is_string($p_filelist))
                   1631:                 $v_list = explode($this->_separator, $p_filelist);
                   1632:             else {
                   1633:                 $this->_error('Invalid file list');
                   1634:                 return false;
                   1635:             }
                   1636: 
                   1637:             $v_result = $this->_append($v_list, $p_add_dir, $p_remove_dir);
                   1638:         }
                   1639: 
                   1640:         return $v_result;
                   1641:     }
                   1642:     // }}}
                   1643: 
                   1644:     // {{{ addString()
                   1645:     /**
                   1646:     * This method add a single string as a file at the
                   1647:     * end of the existing archive. If the archive does not yet exists it
                   1648:     * is created.
                   1649:     *
                   1650:     * @param string $p_filename A string which contains the full
                   1651:     *                           filename path that will be associated
                   1652:     *                           with the string.
                   1653:     * @param string $p_string   The content of the file added in
                   1654:     *                           the archive.
1.1.1.2 ! misho    1655:     * @param int    $p_datetime A custom date/time (unix timestamp)
        !          1656:     *                           for the file (optional).
1.1       misho    1657:     *
                   1658:     * @return true on success, false on error.
                   1659:     * @access public
                   1660:     */
1.1.1.2 ! misho    1661:     function addString($p_filename, $p_string, $p_datetime = false)
1.1       misho    1662:     {
                   1663:         $v_result = true;
                   1664: 
                   1665:         if (!$this->_isArchive()) {
                   1666:             if (!$this->_openWrite()) {
                   1667:                 return false;
                   1668:             }
                   1669:             $this->_close();
                   1670:         }
                   1671: 
                   1672:         if (!$this->_openAppend())
                   1673:             return false;
                   1674: 
                   1675:         // Need to check the get back to the temporary file ? ....
1.1.1.2 ! misho    1676:         $v_result = $this->_addString($p_filename, $p_string, $p_datetime);
1.1       misho    1677: 
                   1678:         $this->_writeFooter();
                   1679: 
                   1680:         $this->_close();
                   1681: 
                   1682:         return $v_result;
                   1683:     }
                   1684:     // }}}
                   1685: 
                   1686:     // {{{ extractModify()
                   1687:     /**
                   1688:     * This method extract all the content of the archive in the directory
                   1689:     * indicated by $p_path. When relevant the memorized path of the
                   1690:     * files/dir can be modified by removing the $p_remove_path path at the
                   1691:     * beginning of the file/dir path.
                   1692:     * While extracting a file, if the directory path does not exists it is
                   1693:     * created.
                   1694:     * While extracting a file, if the file already exists it is replaced
                   1695:     * without looking for last modification date.
                   1696:     * While extracting a file, if the file already exists and is write
                   1697:     * protected, the extraction is aborted.
                   1698:     * While extracting a file, if a directory with the same name already
                   1699:     * exists, the extraction is aborted.
                   1700:     * While extracting a directory, if a file with the same name already
                   1701:     * exists, the extraction is aborted.
                   1702:     * While extracting a file/directory if the destination directory exist
                   1703:     * and is write protected, or does not exist but can not be created,
                   1704:     * the extraction is aborted.
                   1705:     * If after extraction an extracted file does not show the correct
                   1706:     * stored file size, the extraction is aborted.
                   1707:     * When the extraction is aborted, a PEAR error text is set and false
                   1708:     * is returned. However the result can be a partial extraction that may
                   1709:     * need to be manually cleaned.
                   1710:     *
1.1.1.2 ! misho    1711:     * @param string  $p_path        The path of the directory where the
        !          1712:     *                               files/dir need to by extracted.
        !          1713:     * @param string  $p_remove_path Part of the memorized path that can be
        !          1714:     *                               removed if present at the beginning of
        !          1715:     *                               the file/dir path.
        !          1716:     * @param boolean $p_preserve    Preserve user/group ownership of files
1.1       misho    1717:     *
                   1718:     * @return boolean true on success, false on error.
                   1719:     * @access public
                   1720:     * @see    extractList()
                   1721:     */
1.1.1.2 ! misho    1722:     function extractModify($p_path, $p_remove_path, $p_preserve=false)
1.1       misho    1723:     {
                   1724:         $v_result = true;
                   1725:         $v_list_detail = array();
                   1726: 
                   1727:         if ($v_result = $this->_openRead()) {
                   1728:             $v_result = $this->_extractList($p_path, $v_list_detail,
1.1.1.2 ! misho    1729:                 "complete", 0, $p_remove_path, $p_preserve);
1.1       misho    1730:             $this->_close();
                   1731:         }
                   1732: 
                   1733:         return $v_result;
                   1734:     }
                   1735:     // }}}
                   1736: 
                   1737:     // {{{ extractInString()
                   1738:     /**
                   1739:     * This method extract from the archive one file identified by $p_filename.
                   1740:     * The return value is a string with the file content, or NULL on error.
                   1741:     *
                   1742:     * @param string $p_filename The path of the file to extract in a string.
                   1743:     *
                   1744:     * @return a string with the file content or NULL.
                   1745:     * @access public
                   1746:     */
                   1747:     function extractInString($p_filename)
                   1748:     {
                   1749:         if ($this->_openRead()) {
                   1750:             $v_result = $this->_extractInString($p_filename);
                   1751:             $this->_close();
                   1752:         } else {
                   1753:             $v_result = null;
                   1754:         }
                   1755: 
                   1756:         return $v_result;
                   1757:     }
                   1758:     // }}}
                   1759: 
                   1760:     // {{{ extractList()
                   1761:     /**
                   1762:     * This method extract from the archive only the files indicated in the
                   1763:     * $p_filelist. These files are extracted in the current directory or
                   1764:     * in the directory indicated by the optional $p_path parameter.
                   1765:     * If indicated the $p_remove_path can be used in the same way as it is
                   1766:     * used in extractModify() method.
                   1767:     *
1.1.1.2 ! misho    1768:     * @param array   $p_filelist    An array of filenames and directory names,
        !          1769:     *                               or a single string with names separated
        !          1770:     *                               by a single blank space.
        !          1771:     * @param string  $p_path        The path of the directory where the
        !          1772:     *                               files/dir need to by extracted.
        !          1773:     * @param string  $p_remove_path Part of the memorized path that can be
        !          1774:     *                               removed if present at the beginning of
        !          1775:     *                               the file/dir path.
        !          1776:     * @param boolean $p_preserve    Preserve user/group ownership of files
1.1       misho    1777:     *
                   1778:     * @return true on success, false on error.
                   1779:     * @access public
                   1780:     * @see    extractModify()
                   1781:     */
1.1.1.2 ! misho    1782:     function extractList($p_filelist, $p_path='', $p_remove_path='', $p_preserve=false)
1.1       misho    1783:     {
                   1784:         $v_result = true;
                   1785:         $v_list_detail = array();
                   1786: 
                   1787:         if (is_array($p_filelist))
                   1788:             $v_list = $p_filelist;
                   1789:         elseif (is_string($p_filelist))
                   1790:             $v_list = explode($this->_separator, $p_filelist);
                   1791:         else {
                   1792:             $this->_error('Invalid string list');
                   1793:             return false;
                   1794:         }
                   1795: 
                   1796:         if ($v_result = $this->_openRead()) {
                   1797:             $v_result = $this->_extractList($p_path, $v_list_detail, "partial",
1.1.1.2 ! misho    1798:                 $v_list, $p_remove_path, $p_preserve);
1.1       misho    1799:             $this->_close();
                   1800:         }
                   1801: 
                   1802:         return $v_result;
                   1803:     }
                   1804:     // }}}
                   1805: 
                   1806:     // {{{ setAttribute()
                   1807:     /**
                   1808:     * This method set specific attributes of the archive. It uses a variable
                   1809:     * list of parameters, in the format attribute code + attribute values :
                   1810:     * $arch->setAttribute(ARCHIVE_TAR_ATT_SEPARATOR, ',');
                   1811:     *
                   1812:     * @param mixed $argv variable list of attributes and values
                   1813:     *
                   1814:     * @return true on success, false on error.
                   1815:     * @access public
                   1816:     */
                   1817:     function setAttribute()
                   1818:     {
                   1819:         $v_result = true;
                   1820: 
                   1821:         // ----- Get the number of variable list of arguments
                   1822:         if (($v_size = func_num_args()) == 0) {
                   1823:             return true;
                   1824:         }
                   1825: 
                   1826:         // ----- Get the arguments
                   1827:         $v_att_list = &func_get_args();
                   1828: 
                   1829:         // ----- Read the attributes
                   1830:         $i=0;
                   1831:         while ($i<$v_size) {
                   1832: 
                   1833:             // ----- Look for next option
                   1834:             switch ($v_att_list[$i]) {
                   1835:                 // ----- Look for options that request a string value
                   1836:                 case ARCHIVE_TAR_ATT_SEPARATOR :
                   1837:                     // ----- Check the number of parameters
                   1838:                     if (($i+1) >= $v_size) {
                   1839:                         $this->_error('Invalid number of parameters for '
                   1840:                                                              .'attribute ARCHIVE_TAR_ATT_SEPARATOR');
                   1841:                         return false;
                   1842:                     }
                   1843: 
                   1844:                     // ----- Get the value
                   1845:                     $this->_separator = $v_att_list[$i+1];
                   1846:                     $i++;
                   1847:                 break;
                   1848: 
                   1849:                 default :
                   1850:                     $this->_error('Unknow attribute code '.$v_att_list[$i].'');
                   1851:                     return false;
                   1852:             }
                   1853: 
                   1854:             // ----- Next attribute
                   1855:             $i++;
                   1856:         }
                   1857: 
                   1858:         return $v_result;
                   1859:     }
                   1860:     // }}}
                   1861: 
                   1862:     // {{{ setIgnoreRegexp()
                   1863:     /**
                   1864:     * This method sets the regular expression for ignoring files and directories
                   1865:     * at import, for example:
                   1866:     * $arch->setIgnoreRegexp("#CVS|\.svn#");
                   1867:     *
                   1868:     * @param string $regexp regular expression defining which files or directories to ignore
                   1869:     *
                   1870:     * @access public
                   1871:     */
                   1872:     function setIgnoreRegexp($regexp)
                   1873:     {
                   1874:        $this->_ignore_regexp = $regexp;
                   1875:     }
                   1876:     // }}}
                   1877: 
                   1878:     // {{{ setIgnoreList()
                   1879:     /**
                   1880:     * This method sets the regular expression for ignoring all files and directories
                   1881:     * matching the filenames in the array list at import, for example:
                   1882:     * $arch->setIgnoreList(array('CVS', '.svn', 'bin/tool'));
                   1883:     *
                   1884:     * @param array $list a list of file or directory names to ignore
                   1885:     *
                   1886:     * @access public
                   1887:     */
                   1888:     function setIgnoreList($list)
                   1889:     {
                   1890:        $regexp = str_replace(array('#', '.', '^', '$'), array('\#', '\.', '\^', '\$'), $list);
                   1891:        $regexp = '#/'.join('$|/', $list).'#';
                   1892:        $this->setIgnoreRegexp($regexp);
                   1893:     }
                   1894:     // }}}
                   1895: 
                   1896:     // {{{ _error()
                   1897:     function _error($p_message)
                   1898:     {
                   1899:         $this->error_object = &$this->raiseError($p_message); 
                   1900:     }
                   1901:     // }}}
                   1902: 
                   1903:     // {{{ _warning()
                   1904:     function _warning($p_message)
                   1905:     {
                   1906:         $this->error_object = &$this->raiseError($p_message); 
                   1907:     }
                   1908:     // }}}
                   1909: 
                   1910:     // {{{ _isArchive()
                   1911:     function _isArchive($p_filename=null)
                   1912:     {
                   1913:         if ($p_filename == null) {
                   1914:             $p_filename = $this->_tarname;
                   1915:         }
                   1916:         clearstatcache();
                   1917:         return @is_file($p_filename) && !@is_link($p_filename);
                   1918:     }
                   1919:     // }}}
                   1920: 
                   1921:     // {{{ _openWrite()
                   1922:     function _openWrite()
                   1923:     {
1.1.1.2 ! misho    1924:         if ($this->_compress_type == 'gz' && function_exists('gzopen'))
1.1       misho    1925:             $this->_file = @gzopen($this->_tarname, "wb9");
1.1.1.2 ! misho    1926:         else if ($this->_compress_type == 'bz2' && function_exists('bzopen'))
1.1       misho    1927:             $this->_file = @bzopen($this->_tarname, "w");
                   1928:         else if ($this->_compress_type == 'none')
                   1929:             $this->_file = @fopen($this->_tarname, "wb");
1.1.1.2 ! misho    1930:         else {
1.1       misho    1931:             $this->_error('Unknown or missing compression type ('
                   1932:                                      .$this->_compress_type.')');
1.1.1.2 ! misho    1933:             return false;
        !          1934:         }
1.1       misho    1935: 
                   1936:         if ($this->_file == 0) {
                   1937:             $this->_error('Unable to open in write mode \''
                   1938:                                      .$this->_tarname.'\'');
                   1939:             return false;
                   1940:         }
                   1941: 
                   1942:         return true;
                   1943:     }
                   1944:     // }}}
                   1945: 
                   1946:     // {{{ _openRead()
                   1947:     function _openRead()
                   1948:     {
                   1949:         if (strtolower(substr($this->_tarname, 0, 7)) == 'http://') {
                   1950: 
                   1951:           // ----- Look if a local copy need to be done
                   1952:           if ($this->_temp_tarname == '') {
                   1953:               $this->_temp_tarname = uniqid('tar').'.tmp';
                   1954:               if (!$v_file_from = @fopen($this->_tarname, 'rb')) {
                   1955:                 $this->_error('Unable to open in read mode \''
                   1956:                                              .$this->_tarname.'\'');
                   1957:                 $this->_temp_tarname = '';
                   1958:                 return false;
                   1959:               }
                   1960:               if (!$v_file_to = @fopen($this->_temp_tarname, 'wb')) {
                   1961:                 $this->_error('Unable to open in write mode \''
                   1962:                                              .$this->_temp_tarname.'\'');
                   1963:                 $this->_temp_tarname = '';
                   1964:                 return false;
                   1965:               }
                   1966:               while ($v_data = @fread($v_file_from, 1024))
                   1967:                   @fwrite($v_file_to, $v_data);
                   1968:               @fclose($v_file_from);
                   1969:               @fclose($v_file_to);
                   1970:           }
                   1971: 
                   1972:           // ----- File to open if the local copy
                   1973:           $v_filename = $this->_temp_tarname;
                   1974: 
                   1975:         } else
                   1976:           // ----- File to open if the normal Tar file
                   1977:           $v_filename = $this->_tarname;
                   1978: 
1.1.1.2 ! misho    1979:         if ($this->_compress_type == 'gz' && function_exists('gzopen'))
1.1       misho    1980:             $this->_file = @gzopen($v_filename, "rb");
1.1.1.2 ! misho    1981:         else if ($this->_compress_type == 'bz2' && function_exists('bzopen'))
1.1       misho    1982:             $this->_file = @bzopen($v_filename, "r");
                   1983:         else if ($this->_compress_type == 'none')
                   1984:             $this->_file = @fopen($v_filename, "rb");
1.1.1.2 ! misho    1985:         else {
1.1       misho    1986:             $this->_error('Unknown or missing compression type ('
                   1987:                                      .$this->_compress_type.')');
1.1.1.2 ! misho    1988:             return false;
        !          1989:         }
1.1       misho    1990: 
                   1991:         if ($this->_file == 0) {
                   1992:             $this->_error('Unable to open in read mode \''.$v_filename.'\'');
                   1993:             return false;
                   1994:         }
                   1995: 
                   1996:         return true;
                   1997:     }
                   1998:     // }}}
                   1999: 
                   2000:     // {{{ _openReadWrite()
                   2001:     function _openReadWrite()
                   2002:     {
                   2003:         if ($this->_compress_type == 'gz')
                   2004:             $this->_file = @gzopen($this->_tarname, "r+b");
                   2005:         else if ($this->_compress_type == 'bz2') {
                   2006:             $this->_error('Unable to open bz2 in read/write mode \''
                   2007:                                      .$this->_tarname.'\' (limitation of bz2 extension)');
                   2008:             return false;
                   2009:         } else if ($this->_compress_type == 'none')
                   2010:             $this->_file = @fopen($this->_tarname, "r+b");
1.1.1.2 ! misho    2011:         else {
1.1       misho    2012:             $this->_error('Unknown or missing compression type ('
                   2013:                                      .$this->_compress_type.')');
1.1.1.2 ! misho    2014:             return false;
        !          2015:         }
1.1       misho    2016: 
                   2017:         if ($this->_file == 0) {
                   2018:             $this->_error('Unable to open in read/write mode \''
                   2019:                                      .$this->_tarname.'\'');
                   2020:             return false;
                   2021:         }
                   2022: 
                   2023:         return true;
                   2024:     }
                   2025:     // }}}
                   2026: 
                   2027:     // {{{ _close()
                   2028:     function _close()
                   2029:     {
                   2030:         //if (isset($this->_file)) {
                   2031:         if (is_resource($this->_file)) {
                   2032:             if ($this->_compress_type == 'gz')
                   2033:                 @gzclose($this->_file);
                   2034:             else if ($this->_compress_type == 'bz2')
                   2035:                 @bzclose($this->_file);
                   2036:             else if ($this->_compress_type == 'none')
                   2037:                 @fclose($this->_file);
                   2038:             else
                   2039:                 $this->_error('Unknown or missing compression type ('
                   2040:                                              .$this->_compress_type.')');
                   2041: 
                   2042:             $this->_file = 0;
                   2043:         }
                   2044: 
                   2045:         // ----- Look if a local copy need to be erase
                   2046:         // Note that it might be interesting to keep the url for a time : ToDo
                   2047:         if ($this->_temp_tarname != '') {
                   2048:             @unlink($this->_temp_tarname);
                   2049:             $this->_temp_tarname = '';
                   2050:         }
                   2051: 
                   2052:         return true;
                   2053:     }
                   2054:     // }}}
                   2055: 
                   2056:     // {{{ _cleanFile()
                   2057:     function _cleanFile()
                   2058:     {
                   2059:         $this->_close();
                   2060: 
                   2061:         // ----- Look for a local copy
                   2062:         if ($this->_temp_tarname != '') {
                   2063:             // ----- Remove the local copy but not the remote tarname
                   2064:             @unlink($this->_temp_tarname);
                   2065:             $this->_temp_tarname = '';
                   2066:         } else {
                   2067:             // ----- Remove the local tarname file
                   2068:             @unlink($this->_tarname);
                   2069:         }
                   2070:         $this->_tarname = '';
                   2071: 
                   2072:         return true;
                   2073:     }
                   2074:     // }}}
                   2075: 
                   2076:     // {{{ _writeBlock()
                   2077:     function _writeBlock($p_binary_data, $p_len=null)
                   2078:     {
                   2079:       if (is_resource($this->_file)) {
                   2080:           if ($p_len === null) {
                   2081:               if ($this->_compress_type == 'gz')
                   2082:                   @gzputs($this->_file, $p_binary_data);
                   2083:               else if ($this->_compress_type == 'bz2')
                   2084:                   @bzwrite($this->_file, $p_binary_data);
                   2085:               else if ($this->_compress_type == 'none')
                   2086:                   @fputs($this->_file, $p_binary_data);
                   2087:               else
                   2088:                   $this->_error('Unknown or missing compression type ('
                   2089:                                                .$this->_compress_type.')');
                   2090:           } else {
                   2091:               if ($this->_compress_type == 'gz')
                   2092:                   @gzputs($this->_file, $p_binary_data, $p_len);
                   2093:               else if ($this->_compress_type == 'bz2')
                   2094:                   @bzwrite($this->_file, $p_binary_data, $p_len);
                   2095:               else if ($this->_compress_type == 'none')
                   2096:                   @fputs($this->_file, $p_binary_data, $p_len);
                   2097:               else
                   2098:                   $this->_error('Unknown or missing compression type ('
                   2099:                                                .$this->_compress_type.')');
                   2100: 
                   2101:           }
                   2102:       }
                   2103:       return true;
                   2104:     }
                   2105:     // }}}
                   2106: 
                   2107:     // {{{ _readBlock()
                   2108:     function _readBlock()
                   2109:     {
                   2110:       $v_block = null;
                   2111:       if (is_resource($this->_file)) {
                   2112:           if ($this->_compress_type == 'gz')
                   2113:               $v_block = @gzread($this->_file, 512);
                   2114:           else if ($this->_compress_type == 'bz2')
                   2115:               $v_block = @bzread($this->_file, 512);
                   2116:           else if ($this->_compress_type == 'none')
                   2117:               $v_block = @fread($this->_file, 512);
                   2118:           else
                   2119:               $this->_error('Unknown or missing compression type ('
                   2120:                                        .$this->_compress_type.')');
                   2121:       }
                   2122:       return $v_block;
                   2123:     }
                   2124:     // }}}
                   2125: 
                   2126:     // {{{ _jumpBlock()
                   2127:     function _jumpBlock($p_len=null)
                   2128:     {
                   2129:       if (is_resource($this->_file)) {
                   2130:           if ($p_len === null)
                   2131:               $p_len = 1;
                   2132: 
                   2133:           if ($this->_compress_type == 'gz') {
                   2134:               @gzseek($this->_file, gztell($this->_file)+($p_len*512));
                   2135:           }
                   2136:           else if ($this->_compress_type == 'bz2') {
                   2137:               // ----- Replace missing bztell() and bzseek()
                   2138:               for ($i=0; $i<$p_len; $i++)
                   2139:                   $this->_readBlock();
                   2140:           } else if ($this->_compress_type == 'none')
                   2141:               @fseek($this->_file, $p_len*512, SEEK_CUR);
                   2142:           else
                   2143:               $this->_error('Unknown or missing compression type ('
                   2144:                                        .$this->_compress_type.')');
                   2145: 
                   2146:       }
                   2147:       return true;
                   2148:     }
                   2149:     // }}}
                   2150: 
                   2151:     // {{{ _writeFooter()
                   2152:     function _writeFooter()
                   2153:     {
                   2154:       if (is_resource($this->_file)) {
                   2155:           // ----- Write the last 0 filled block for end of archive
                   2156:           $v_binary_data = pack('a1024', '');
                   2157:           $this->_writeBlock($v_binary_data);
                   2158:       }
                   2159:       return true;
                   2160:     }
                   2161:     // }}}
                   2162: 
                   2163:     // {{{ _addList()
                   2164:     function _addList($p_list, $p_add_dir, $p_remove_dir)
                   2165:     {
                   2166:       $v_result=true;
                   2167:       $v_header = array();
                   2168: 
                   2169:       // ----- Remove potential windows directory separator
                   2170:       $p_add_dir = $this->_translateWinPath($p_add_dir);
                   2171:       $p_remove_dir = $this->_translateWinPath($p_remove_dir, false);
                   2172: 
                   2173:       if (!$this->_file) {
                   2174:           $this->_error('Invalid file descriptor');
                   2175:           return false;
                   2176:       }
                   2177: 
                   2178:       if (sizeof($p_list) == 0)
                   2179:           return true;
                   2180: 
                   2181:       foreach ($p_list as $v_filename) {
                   2182:           if (!$v_result) {
                   2183:               break;
                   2184:           }
                   2185: 
                   2186:         // ----- Skip the current tar name
                   2187:         if ($v_filename == $this->_tarname)
                   2188:             continue;
                   2189: 
                   2190:         if ($v_filename == '')
                   2191:             continue;
                   2192: 
                   2193:                // ----- ignore files and directories matching the ignore regular expression
                   2194:                if ($this->_ignore_regexp && preg_match($this->_ignore_regexp, '/'.$v_filename)) {
                   2195:             $this->_warning("File '$v_filename' ignored");
                   2196:                    continue;
                   2197:                }
                   2198: 
                   2199:         if (!file_exists($v_filename) && !is_link($v_filename)) {
                   2200:             $this->_warning("File '$v_filename' does not exist");
                   2201:             continue;
                   2202:         }
                   2203: 
                   2204:         // ----- Add the file or directory header
                   2205:         if (!$this->_addFile($v_filename, $v_header, $p_add_dir, $p_remove_dir))
                   2206:             return false;
                   2207: 
                   2208:         if (@is_dir($v_filename) && !@is_link($v_filename)) {
                   2209:             if (!($p_hdir = opendir($v_filename))) {
                   2210:                 $this->_warning("Directory '$v_filename' can not be read");
                   2211:                 continue;
                   2212:             }
                   2213:             while (false !== ($p_hitem = readdir($p_hdir))) {
                   2214:                 if (($p_hitem != '.') && ($p_hitem != '..')) {
                   2215:                     if ($v_filename != ".")
                   2216:                         $p_temp_list[0] = $v_filename.'/'.$p_hitem;
                   2217:                     else
                   2218:                         $p_temp_list[0] = $p_hitem;
                   2219: 
                   2220:                     $v_result = $this->_addList($p_temp_list,
                   2221:                                                                    $p_add_dir,
                   2222:                                                                                                $p_remove_dir);
                   2223:                 }
                   2224:             }
                   2225: 
                   2226:             unset($p_temp_list);
                   2227:             unset($p_hdir);
                   2228:             unset($p_hitem);
                   2229:         }
                   2230:       }
                   2231: 
                   2232:       return $v_result;
                   2233:     }
                   2234:     // }}}
                   2235: 
                   2236:     // {{{ _addFile()
                   2237:     function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir)
                   2238:     {
                   2239:       if (!$this->_file) {
                   2240:           $this->_error('Invalid file descriptor');
                   2241:           return false;
                   2242:       }
                   2243: 
                   2244:       if ($p_filename == '') {
                   2245:           $this->_error('Invalid file name');
                   2246:           return false;
                   2247:       }
                   2248: 
                   2249:       // ----- Calculate the stored filename
                   2250:       $p_filename = $this->_translateWinPath($p_filename, false);;
                   2251:       $v_stored_filename = $p_filename;
                   2252:       if (strcmp($p_filename, $p_remove_dir) == 0) {
                   2253:           return true;
                   2254:       }
                   2255:       if ($p_remove_dir != '') {
                   2256:           if (substr($p_remove_dir, -1) != '/')
                   2257:               $p_remove_dir .= '/';
                   2258: 
                   2259:           if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir)
                   2260:               $v_stored_filename = substr($p_filename, strlen($p_remove_dir));
                   2261:       }
                   2262:       $v_stored_filename = $this->_translateWinPath($v_stored_filename);
                   2263:       if ($p_add_dir != '') {
                   2264:           if (substr($p_add_dir, -1) == '/')
                   2265:               $v_stored_filename = $p_add_dir.$v_stored_filename;
                   2266:           else
                   2267:               $v_stored_filename = $p_add_dir.'/'.$v_stored_filename;
                   2268:       }
                   2269: 
                   2270:       $v_stored_filename = $this->_pathReduction($v_stored_filename);
                   2271: 
                   2272:       if ($this->_isArchive($p_filename)) {
                   2273:           if (($v_file = @fopen($p_filename, "rb")) == 0) {
                   2274:               $this->_warning("Unable to open file '".$p_filename
                   2275:                                          ."' in binary read mode");
                   2276:               return true;
                   2277:           }
                   2278: 
                   2279:           if (!$this->_writeHeader($p_filename, $v_stored_filename))
                   2280:               return false;
                   2281: 
                   2282:           while (($v_buffer = fread($v_file, 512)) != '') {
                   2283:               $v_binary_data = pack("a512", "$v_buffer");
                   2284:               $this->_writeBlock($v_binary_data);
                   2285:           }
                   2286: 
                   2287:           fclose($v_file);
                   2288: 
                   2289:       } else {
                   2290:           // ----- Only header for dir
                   2291:           if (!$this->_writeHeader($p_filename, $v_stored_filename))
                   2292:               return false;
                   2293:       }
                   2294: 
                   2295:       return true;
                   2296:     }
                   2297:     // }}}
                   2298: 
                   2299:     // {{{ _addString()
1.1.1.2 ! misho    2300:     function _addString($p_filename, $p_string, $p_datetime = false)
1.1       misho    2301:     {
                   2302:       if (!$this->_file) {
                   2303:           $this->_error('Invalid file descriptor');
                   2304:           return false;
                   2305:       }
                   2306: 
                   2307:       if ($p_filename == '') {
                   2308:           $this->_error('Invalid file name');
                   2309:           return false;
                   2310:       }
                   2311: 
                   2312:       // ----- Calculate the stored filename
                   2313:       $p_filename = $this->_translateWinPath($p_filename, false);;
1.1.1.2 ! misho    2314:       
        !          2315:       // ----- If datetime is not specified, set current time
        !          2316:       if ($p_datetime === false) {
        !          2317:           $p_datetime = time();
        !          2318:       }
1.1       misho    2319: 
                   2320:       if (!$this->_writeHeaderBlock($p_filename, strlen($p_string),
1.1.1.2 ! misho    2321:                                     $p_datetime, 384, "", 0, 0))
1.1       misho    2322:           return false;
                   2323: 
                   2324:       $i=0;
                   2325:       while (($v_buffer = substr($p_string, (($i++)*512), 512)) != '') {
                   2326:           $v_binary_data = pack("a512", $v_buffer);
                   2327:           $this->_writeBlock($v_binary_data);
                   2328:       }
                   2329: 
                   2330:       return true;
                   2331:     }
                   2332:     // }}}
                   2333: 
                   2334:     // {{{ _writeHeader()
                   2335:     function _writeHeader($p_filename, $p_stored_filename)
                   2336:     {
                   2337:         if ($p_stored_filename == '')
                   2338:             $p_stored_filename = $p_filename;
                   2339:         $v_reduce_filename = $this->_pathReduction($p_stored_filename);
                   2340: 
                   2341:         if (strlen($v_reduce_filename) > 99) {
                   2342:           if (!$this->_writeLongHeader($v_reduce_filename))
                   2343:             return false;
                   2344:         }
                   2345: 
                   2346:         $v_info = lstat($p_filename);
                   2347:         $v_uid = sprintf("%07s", DecOct($v_info[4]));
                   2348:         $v_gid = sprintf("%07s", DecOct($v_info[5]));
                   2349:         $v_perms = sprintf("%07s", DecOct($v_info['mode'] & 000777));
                   2350: 
                   2351:         $v_mtime = sprintf("%011s", DecOct($v_info['mtime']));
                   2352: 
                   2353:         $v_linkname = '';
                   2354: 
                   2355:         if (@is_link($p_filename)) {
                   2356:           $v_typeflag = '2';
                   2357:           $v_linkname = readlink($p_filename);
                   2358:           $v_size = sprintf("%011s", DecOct(0));
                   2359:         } elseif (@is_dir($p_filename)) {
                   2360:           $v_typeflag = "5";
                   2361:           $v_size = sprintf("%011s", DecOct(0));
                   2362:         } else {
                   2363:           $v_typeflag = '0';
                   2364:           clearstatcache();
                   2365:           $v_size = sprintf("%011s", DecOct($v_info['size']));
                   2366:         }
                   2367: 
                   2368:         $v_magic = 'ustar ';
                   2369: 
                   2370:         $v_version = ' ';
                   2371:         
                   2372:         if (function_exists('posix_getpwuid'))
                   2373:         {
                   2374:           $userinfo = posix_getpwuid($v_info[4]);
                   2375:           $groupinfo = posix_getgrgid($v_info[5]);
                   2376:           
                   2377:           $v_uname = $userinfo['name'];
                   2378:           $v_gname = $groupinfo['name'];
                   2379:         }
                   2380:         else
                   2381:         {
                   2382:           $v_uname = '';
                   2383:           $v_gname = '';
                   2384:         }
                   2385: 
                   2386:         $v_devmajor = '';
                   2387: 
                   2388:         $v_devminor = '';
                   2389: 
                   2390:         $v_prefix = '';
                   2391: 
                   2392:         $v_binary_data_first = pack("a100a8a8a8a12a12",
                   2393:                                            $v_reduce_filename, $v_perms, $v_uid,
                   2394:                                                                        $v_gid, $v_size, $v_mtime);
                   2395:         $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12",
                   2396:                                           $v_typeflag, $v_linkname, $v_magic,
                   2397:                                                                   $v_version, $v_uname, $v_gname,
                   2398:                                                                   $v_devmajor, $v_devminor, $v_prefix, '');
                   2399: 
                   2400:         // ----- Calculate the checksum
                   2401:         $v_checksum = 0;
                   2402:         // ..... First part of the header
                   2403:         for ($i=0; $i<148; $i++)
                   2404:             $v_checksum += ord(substr($v_binary_data_first,$i,1));
                   2405:         // ..... Ignore the checksum value and replace it by ' ' (space)
                   2406:         for ($i=148; $i<156; $i++)
                   2407:             $v_checksum += ord(' ');
                   2408:         // ..... Last part of the header
                   2409:         for ($i=156, $j=0; $i<512; $i++, $j++)
                   2410:             $v_checksum += ord(substr($v_binary_data_last,$j,1));
                   2411: 
                   2412:         // ----- Write the first 148 bytes of the header in the archive
                   2413:         $this->_writeBlock($v_binary_data_first, 148);
                   2414: 
                   2415:         // ----- Write the calculated checksum
                   2416:         $v_checksum = sprintf("%06s ", DecOct($v_checksum));
                   2417:         $v_binary_data = pack("a8", $v_checksum);
                   2418:         $this->_writeBlock($v_binary_data, 8);
                   2419: 
                   2420:         // ----- Write the last 356 bytes of the header in the archive
                   2421:         $this->_writeBlock($v_binary_data_last, 356);
                   2422: 
                   2423:         return true;
                   2424:     }
                   2425:     // }}}
                   2426: 
                   2427:     // {{{ _writeHeaderBlock()
                   2428:     function _writeHeaderBlock($p_filename, $p_size, $p_mtime=0, $p_perms=0,
                   2429:                                   $p_type='', $p_uid=0, $p_gid=0)
                   2430:     {
                   2431:         $p_filename = $this->_pathReduction($p_filename);
                   2432: 
                   2433:         if (strlen($p_filename) > 99) {
                   2434:           if (!$this->_writeLongHeader($p_filename))
                   2435:             return false;
                   2436:         }
                   2437: 
                   2438:         if ($p_type == "5") {
                   2439:           $v_size = sprintf("%011s", DecOct(0));
                   2440:         } else {
                   2441:           $v_size = sprintf("%011s", DecOct($p_size));
                   2442:         }
                   2443: 
                   2444:         $v_uid = sprintf("%07s", DecOct($p_uid));
                   2445:         $v_gid = sprintf("%07s", DecOct($p_gid));
                   2446:         $v_perms = sprintf("%07s", DecOct($p_perms & 000777));
                   2447: 
                   2448:         $v_mtime = sprintf("%11s", DecOct($p_mtime));
                   2449: 
                   2450:         $v_linkname = '';
                   2451: 
                   2452:         $v_magic = 'ustar ';
                   2453: 
                   2454:         $v_version = ' ';
                   2455: 
                   2456:         if (function_exists('posix_getpwuid'))
                   2457:         {
                   2458:           $userinfo = posix_getpwuid($p_uid);
                   2459:           $groupinfo = posix_getgrgid($p_gid);
                   2460:           
                   2461:           $v_uname = $userinfo['name'];
                   2462:           $v_gname = $groupinfo['name'];
                   2463:         }
                   2464:         else
                   2465:         {
                   2466:           $v_uname = '';
                   2467:           $v_gname = '';
                   2468:         }
                   2469:         
                   2470:         $v_devmajor = '';
                   2471: 
                   2472:         $v_devminor = '';
                   2473: 
                   2474:         $v_prefix = '';
                   2475: 
                   2476:         $v_binary_data_first = pack("a100a8a8a8a12A12",
                   2477:                                            $p_filename, $v_perms, $v_uid, $v_gid,
                   2478:                                                                        $v_size, $v_mtime);
                   2479:         $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12",
                   2480:                                           $p_type, $v_linkname, $v_magic,
                   2481:                                                                   $v_version, $v_uname, $v_gname,
                   2482:                                                                   $v_devmajor, $v_devminor, $v_prefix, '');
                   2483: 
                   2484:         // ----- Calculate the checksum
                   2485:         $v_checksum = 0;
                   2486:         // ..... First part of the header
                   2487:         for ($i=0; $i<148; $i++)
                   2488:             $v_checksum += ord(substr($v_binary_data_first,$i,1));
                   2489:         // ..... Ignore the checksum value and replace it by ' ' (space)
                   2490:         for ($i=148; $i<156; $i++)
                   2491:             $v_checksum += ord(' ');
                   2492:         // ..... Last part of the header
                   2493:         for ($i=156, $j=0; $i<512; $i++, $j++)
                   2494:             $v_checksum += ord(substr($v_binary_data_last,$j,1));
                   2495: 
                   2496:         // ----- Write the first 148 bytes of the header in the archive
                   2497:         $this->_writeBlock($v_binary_data_first, 148);
                   2498: 
                   2499:         // ----- Write the calculated checksum
                   2500:         $v_checksum = sprintf("%06s ", DecOct($v_checksum));
                   2501:         $v_binary_data = pack("a8", $v_checksum);
                   2502:         $this->_writeBlock($v_binary_data, 8);
                   2503: 
                   2504:         // ----- Write the last 356 bytes of the header in the archive
                   2505:         $this->_writeBlock($v_binary_data_last, 356);
                   2506: 
                   2507:         return true;
                   2508:     }
                   2509:     // }}}
                   2510: 
                   2511:     // {{{ _writeLongHeader()
                   2512:     function _writeLongHeader($p_filename)
                   2513:     {
                   2514:         $v_size = sprintf("%11s ", DecOct(strlen($p_filename)));
                   2515: 
                   2516:         $v_typeflag = 'L';
                   2517: 
                   2518:         $v_linkname = '';
                   2519: 
                   2520:         $v_magic = '';
                   2521: 
                   2522:         $v_version = '';
                   2523: 
                   2524:         $v_uname = '';
                   2525: 
                   2526:         $v_gname = '';
                   2527: 
                   2528:         $v_devmajor = '';
                   2529: 
                   2530:         $v_devminor = '';
                   2531: 
                   2532:         $v_prefix = '';
                   2533: 
                   2534:         $v_binary_data_first = pack("a100a8a8a8a12a12",
                   2535:                                            '././@LongLink', 0, 0, 0, $v_size, 0);
                   2536:         $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12",
                   2537:                                           $v_typeflag, $v_linkname, $v_magic,
                   2538:                                                                   $v_version, $v_uname, $v_gname,
                   2539:                                                                   $v_devmajor, $v_devminor, $v_prefix, '');
                   2540: 
                   2541:         // ----- Calculate the checksum
                   2542:         $v_checksum = 0;
                   2543:         // ..... First part of the header
                   2544:         for ($i=0; $i<148; $i++)
                   2545:             $v_checksum += ord(substr($v_binary_data_first,$i,1));
                   2546:         // ..... Ignore the checksum value and replace it by ' ' (space)
                   2547:         for ($i=148; $i<156; $i++)
                   2548:             $v_checksum += ord(' ');
                   2549:         // ..... Last part of the header
                   2550:         for ($i=156, $j=0; $i<512; $i++, $j++)
                   2551:             $v_checksum += ord(substr($v_binary_data_last,$j,1));
                   2552: 
                   2553:         // ----- Write the first 148 bytes of the header in the archive
                   2554:         $this->_writeBlock($v_binary_data_first, 148);
                   2555: 
                   2556:         // ----- Write the calculated checksum
                   2557:         $v_checksum = sprintf("%06s ", DecOct($v_checksum));
                   2558:         $v_binary_data = pack("a8", $v_checksum);
                   2559:         $this->_writeBlock($v_binary_data, 8);
                   2560: 
                   2561:         // ----- Write the last 356 bytes of the header in the archive
                   2562:         $this->_writeBlock($v_binary_data_last, 356);
                   2563: 
                   2564:         // ----- Write the filename as content of the block
                   2565:         $i=0;
                   2566:         while (($v_buffer = substr($p_filename, (($i++)*512), 512)) != '') {
                   2567:             $v_binary_data = pack("a512", "$v_buffer");
                   2568:             $this->_writeBlock($v_binary_data);
                   2569:         }
                   2570: 
                   2571:         return true;
                   2572:     }
                   2573:     // }}}
                   2574: 
                   2575:     // {{{ _readHeader()
                   2576:     function _readHeader($v_binary_data, &$v_header)
                   2577:     {
                   2578:         if (strlen($v_binary_data)==0) {
                   2579:             $v_header['filename'] = '';
                   2580:             return true;
                   2581:         }
                   2582: 
                   2583:         if (strlen($v_binary_data) != 512) {
                   2584:             $v_header['filename'] = '';
                   2585:             $this->_error('Invalid block size : '.strlen($v_binary_data));
                   2586:             return false;
                   2587:         }
                   2588: 
                   2589:         if (!is_array($v_header)) {
                   2590:             $v_header = array();
                   2591:         }
                   2592:         // ----- Calculate the checksum
                   2593:         $v_checksum = 0;
                   2594:         // ..... First part of the header
                   2595:         for ($i=0; $i<148; $i++)
                   2596:             $v_checksum+=ord(substr($v_binary_data,$i,1));
                   2597:         // ..... Ignore the checksum value and replace it by ' ' (space)
                   2598:         for ($i=148; $i<156; $i++)
                   2599:             $v_checksum += ord(' ');
                   2600:         // ..... Last part of the header
                   2601:         for ($i=156; $i<512; $i++)
                   2602:            $v_checksum+=ord(substr($v_binary_data,$i,1));
                   2603: 
1.1.1.2 ! misho    2604:         if (version_compare(PHP_VERSION,"5.5.0-dev")<0) {
        !          2605:             $fmt = "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" .
        !          2606:                    "a8checksum/a1typeflag/a100link/a6magic/a2version/" .
        !          2607:                    "a32uname/a32gname/a8devmajor/a8devminor/a131prefix";
        !          2608:         } else {
        !          2609:             $fmt = "Z100filename/Z8mode/Z8uid/Z8gid/Z12size/Z12mtime/" .
        !          2610:                    "Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" .
        !          2611:                    "Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix";
        !          2612:         }
        !          2613:         $v_data = unpack($fmt, $v_binary_data);
        !          2614: 
        !          2615:         if (strlen($v_data["prefix"]) > 0) {
        !          2616:             $v_data["filename"] = "$v_data[prefix]/$v_data[filename]";
        !          2617:         }
1.1       misho    2618: 
                   2619:         // ----- Extract the checksum
                   2620:         $v_header['checksum'] = OctDec(trim($v_data['checksum']));
                   2621:         if ($v_header['checksum'] != $v_checksum) {
                   2622:             $v_header['filename'] = '';
                   2623: 
                   2624:             // ----- Look for last block (empty block)
                   2625:             if (($v_checksum == 256) && ($v_header['checksum'] == 0))
                   2626:                 return true;
                   2627: 
                   2628:             $this->_error('Invalid checksum for file "'.$v_data['filename']
                   2629:                                      .'" : '.$v_checksum.' calculated, '
                   2630:                                                  .$v_header['checksum'].' expected');
                   2631:             return false;
                   2632:         }
                   2633: 
                   2634:         // ----- Extract the properties
                   2635:         $v_header['filename'] = $v_data['filename'];
                   2636:         if ($this->_maliciousFilename($v_header['filename'])) {
                   2637:             $this->_error('Malicious .tar detected, file "' . $v_header['filename'] .
                   2638:                 '" will not install in desired directory tree');
                   2639:             return false;
                   2640:         }
                   2641:         $v_header['mode'] = OctDec(trim($v_data['mode']));
                   2642:         $v_header['uid'] = OctDec(trim($v_data['uid']));
                   2643:         $v_header['gid'] = OctDec(trim($v_data['gid']));
                   2644:         $v_header['size'] = OctDec(trim($v_data['size']));
                   2645:         $v_header['mtime'] = OctDec(trim($v_data['mtime']));
                   2646:         if (($v_header['typeflag'] = $v_data['typeflag']) == "5") {
                   2647:           $v_header['size'] = 0;
                   2648:         }
                   2649:         $v_header['link'] = trim($v_data['link']);
                   2650:         /* ----- All these fields are removed form the header because
                   2651:                they do not carry interesting info
                   2652:         $v_header[magic] = trim($v_data[magic]);
                   2653:         $v_header[version] = trim($v_data[version]);
                   2654:         $v_header[uname] = trim($v_data[uname]);
                   2655:         $v_header[gname] = trim($v_data[gname]);
                   2656:         $v_header[devmajor] = trim($v_data[devmajor]);
                   2657:         $v_header[devminor] = trim($v_data[devminor]);
                   2658:         */
                   2659: 
                   2660:         return true;
                   2661:     }
                   2662:     // }}}
                   2663: 
                   2664:     // {{{ _maliciousFilename()
                   2665:     /**
                   2666:      * Detect and report a malicious file name
                   2667:      *
                   2668:      * @param string $file
                   2669:      *
                   2670:      * @return bool
                   2671:      * @access private
                   2672:      */
                   2673:     function _maliciousFilename($file)
                   2674:     {
                   2675:         if (strpos($file, '/../') !== false) {
                   2676:             return true;
                   2677:         }
                   2678:         if (strpos($file, '../') === 0) {
                   2679:             return true;
                   2680:         }
                   2681:         return false;
                   2682:     }
                   2683:     // }}}
                   2684: 
                   2685:     // {{{ _readLongHeader()
                   2686:     function _readLongHeader(&$v_header)
                   2687:     {
                   2688:       $v_filename = '';
                   2689:       $n = floor($v_header['size']/512);
                   2690:       for ($i=0; $i<$n; $i++) {
                   2691:         $v_content = $this->_readBlock();
                   2692:         $v_filename .= $v_content;
                   2693:       }
                   2694:       if (($v_header['size'] % 512) != 0) {
                   2695:         $v_content = $this->_readBlock();
                   2696:         $v_filename .= trim($v_content);
                   2697:       }
                   2698: 
                   2699:       // ----- Read the next header
                   2700:       $v_binary_data = $this->_readBlock();
                   2701: 
                   2702:       if (!$this->_readHeader($v_binary_data, $v_header))
                   2703:         return false;
                   2704: 
                   2705:       $v_filename = trim($v_filename);
                   2706:       $v_header['filename'] = $v_filename;
                   2707:         if ($this->_maliciousFilename($v_filename)) {
                   2708:             $this->_error('Malicious .tar detected, file "' . $v_filename .
                   2709:                 '" will not install in desired directory tree');
                   2710:             return false;
                   2711:       }
                   2712: 
                   2713:       return true;
                   2714:     }
                   2715:     // }}}
                   2716: 
                   2717:     // {{{ _extractInString()
                   2718:     /**
                   2719:     * This method extract from the archive one file identified by $p_filename.
                   2720:     * The return value is a string with the file content, or null on error.
                   2721:     *
                   2722:     * @param string $p_filename The path of the file to extract in a string.
                   2723:     *
                   2724:     * @return a string with the file content or null.
                   2725:     * @access private
                   2726:     */
                   2727:     function _extractInString($p_filename)
                   2728:     {
                   2729:         $v_result_str = "";
                   2730: 
                   2731:         While (strlen($v_binary_data = $this->_readBlock()) != 0)
                   2732:         {
                   2733:           if (!$this->_readHeader($v_binary_data, $v_header))
                   2734:             return null;
                   2735: 
                   2736:           if ($v_header['filename'] == '')
                   2737:             continue;
                   2738: 
                   2739:           // ----- Look for long filename
                   2740:           if ($v_header['typeflag'] == 'L') {
                   2741:             if (!$this->_readLongHeader($v_header))
                   2742:               return null;
                   2743:           }
                   2744: 
                   2745:           if ($v_header['filename'] == $p_filename) {
                   2746:               if ($v_header['typeflag'] == "5") {
                   2747:                   $this->_error('Unable to extract in string a directory '
                   2748:                                                .'entry {'.$v_header['filename'].'}');
                   2749:                   return null;
                   2750:               } else {
                   2751:                   $n = floor($v_header['size']/512);
                   2752:                   for ($i=0; $i<$n; $i++) {
                   2753:                       $v_result_str .= $this->_readBlock();
                   2754:                   }
                   2755:                   if (($v_header['size'] % 512) != 0) {
                   2756:                       $v_content = $this->_readBlock();
                   2757:                       $v_result_str .= substr($v_content, 0,
                   2758:                                                                  ($v_header['size'] % 512));
                   2759:                   }
                   2760:                   return $v_result_str;
                   2761:               }
                   2762:           } else {
                   2763:               $this->_jumpBlock(ceil(($v_header['size']/512)));
                   2764:           }
                   2765:         }
                   2766: 
                   2767:         return null;
                   2768:     }
                   2769:     // }}}
                   2770: 
                   2771:     // {{{ _extractList()
                   2772:     function _extractList($p_path, &$p_list_detail, $p_mode,
1.1.1.2 ! misho    2773:                           $p_file_list, $p_remove_path, $p_preserve=false)
1.1       misho    2774:     {
                   2775:     $v_result=true;
                   2776:     $v_nb = 0;
                   2777:     $v_extract_all = true;
                   2778:     $v_listing = false;
                   2779: 
                   2780:     $p_path = $this->_translateWinPath($p_path, false);
                   2781:     if ($p_path == '' || (substr($p_path, 0, 1) != '/'
                   2782:            && substr($p_path, 0, 3) != "../" && !strpos($p_path, ':'))) {
                   2783:       $p_path = "./".$p_path;
                   2784:     }
                   2785:     $p_remove_path = $this->_translateWinPath($p_remove_path);
                   2786: 
                   2787:     // ----- Look for path to remove format (should end by /)
                   2788:     if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/'))
                   2789:       $p_remove_path .= '/';
                   2790:     $p_remove_path_size = strlen($p_remove_path);
                   2791: 
                   2792:     switch ($p_mode) {
                   2793:       case "complete" :
                   2794:         $v_extract_all = true;
                   2795:         $v_listing = false;
                   2796:       break;
                   2797:       case "partial" :
                   2798:           $v_extract_all = false;
                   2799:           $v_listing = false;
                   2800:       break;
                   2801:       case "list" :
                   2802:           $v_extract_all = false;
                   2803:           $v_listing = true;
                   2804:       break;
                   2805:       default :
                   2806:         $this->_error('Invalid extract mode ('.$p_mode.')');
                   2807:         return false;
                   2808:     }
                   2809: 
                   2810:     clearstatcache();
                   2811: 
                   2812:     while (strlen($v_binary_data = $this->_readBlock()) != 0)
                   2813:     {
                   2814:       $v_extract_file = FALSE;
                   2815:       $v_extraction_stopped = 0;
                   2816: 
                   2817:       if (!$this->_readHeader($v_binary_data, $v_header))
                   2818:         return false;
                   2819: 
                   2820:       if ($v_header['filename'] == '') {
                   2821:         continue;
                   2822:       }
                   2823: 
                   2824:       // ----- Look for long filename
                   2825:       if ($v_header['typeflag'] == 'L') {
                   2826:         if (!$this->_readLongHeader($v_header))
                   2827:           return false;
                   2828:       }
                   2829: 
                   2830:       if ((!$v_extract_all) && (is_array($p_file_list))) {
                   2831:         // ----- By default no unzip if the file is not found
                   2832:         $v_extract_file = false;
                   2833: 
                   2834:         for ($i=0; $i<sizeof($p_file_list); $i++) {
                   2835:           // ----- Look if it is a directory
                   2836:           if (substr($p_file_list[$i], -1) == '/') {
                   2837:             // ----- Look if the directory is in the filename path
                   2838:             if ((strlen($v_header['filename']) > strlen($p_file_list[$i]))
                   2839:                            && (substr($v_header['filename'], 0, strlen($p_file_list[$i]))
                   2840:                                    == $p_file_list[$i])) {
                   2841:               $v_extract_file = true;
                   2842:               break;
                   2843:             }
                   2844:           }
                   2845: 
                   2846:           // ----- It is a file, so compare the file names
                   2847:           elseif ($p_file_list[$i] == $v_header['filename']) {
                   2848:             $v_extract_file = true;
                   2849:             break;
                   2850:           }
                   2851:         }
                   2852:       } else {
                   2853:         $v_extract_file = true;
                   2854:       }
                   2855: 
                   2856:       // ----- Look if this file need to be extracted
                   2857:       if (($v_extract_file) && (!$v_listing))
                   2858:       {
                   2859:         if (($p_remove_path != '')
1.1.1.2 ! misho    2860:             && (substr($v_header['filename'].'/', 0, $p_remove_path_size)
        !          2861:                            == $p_remove_path)) {
1.1       misho    2862:           $v_header['filename'] = substr($v_header['filename'],
                   2863:                                                 $p_remove_path_size);
1.1.1.2 ! misho    2864:           if( $v_header['filename'] == '' ){
        !          2865:             continue;
        !          2866:           }
        !          2867:         }
1.1       misho    2868:         if (($p_path != './') && ($p_path != '/')) {
                   2869:           while (substr($p_path, -1) == '/')
                   2870:             $p_path = substr($p_path, 0, strlen($p_path)-1);
                   2871: 
                   2872:           if (substr($v_header['filename'], 0, 1) == '/')
                   2873:               $v_header['filename'] = $p_path.$v_header['filename'];
                   2874:           else
                   2875:             $v_header['filename'] = $p_path.'/'.$v_header['filename'];
                   2876:         }
                   2877:         if (file_exists($v_header['filename'])) {
                   2878:           if (   (@is_dir($v_header['filename']))
                   2879:                      && ($v_header['typeflag'] == '')) {
                   2880:             $this->_error('File '.$v_header['filename']
                   2881:                                      .' already exists as a directory');
                   2882:             return false;
                   2883:           }
                   2884:           if (   ($this->_isArchive($v_header['filename']))
                   2885:                      && ($v_header['typeflag'] == "5")) {
                   2886:             $this->_error('Directory '.$v_header['filename']
                   2887:                                      .' already exists as a file');
                   2888:             return false;
                   2889:           }
                   2890:           if (!is_writeable($v_header['filename'])) {
                   2891:             $this->_error('File '.$v_header['filename']
                   2892:                                      .' already exists and is write protected');
                   2893:             return false;
                   2894:           }
                   2895:           if (filemtime($v_header['filename']) > $v_header['mtime']) {
                   2896:             // To be completed : An error or silent no replace ?
                   2897:           }
                   2898:         }
                   2899: 
                   2900:         // ----- Check the directory availability and create it if necessary
                   2901:         elseif (($v_result
                   2902:                         = $this->_dirCheck(($v_header['typeflag'] == "5"
                   2903:                                                    ?$v_header['filename']
                   2904:                                                                        :dirname($v_header['filename'])))) != 1) {
                   2905:             $this->_error('Unable to create path for '.$v_header['filename']);
                   2906:             return false;
                   2907:         }
                   2908: 
                   2909:         if ($v_extract_file) {
                   2910:           if ($v_header['typeflag'] == "5") {
                   2911:             if (!@file_exists($v_header['filename'])) {
                   2912:                 if (!@mkdir($v_header['filename'], 0777)) {
                   2913:                     $this->_error('Unable to create directory {'
                   2914:                                                      .$v_header['filename'].'}');
                   2915:                     return false;
                   2916:                 }
                   2917:             }
                   2918:           } elseif ($v_header['typeflag'] == "2") {
                   2919:               if (@file_exists($v_header['filename'])) {
                   2920:                   @unlink($v_header['filename']);
                   2921:               }
                   2922:               if (!@symlink($v_header['link'], $v_header['filename'])) {
                   2923:                   $this->_error('Unable to extract symbolic link {'
                   2924:                                 .$v_header['filename'].'}');
                   2925:                   return false;
                   2926:               }
                   2927:           } else {
                   2928:               if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) {
                   2929:                   $this->_error('Error while opening {'.$v_header['filename']
                   2930:                                                .'} in write binary mode');
                   2931:                   return false;
                   2932:               } else {
                   2933:                   $n = floor($v_header['size']/512);
                   2934:                   for ($i=0; $i<$n; $i++) {
                   2935:                       $v_content = $this->_readBlock();
                   2936:                       fwrite($v_dest_file, $v_content, 512);
                   2937:                   }
                   2938:             if (($v_header['size'] % 512) != 0) {
                   2939:               $v_content = $this->_readBlock();
                   2940:               fwrite($v_dest_file, $v_content, ($v_header['size'] % 512));
                   2941:             }
                   2942: 
                   2943:             @fclose($v_dest_file);
1.1.1.2 ! misho    2944:             
        !          2945:             if ($p_preserve) {
        !          2946:                 @chown($v_header['filename'], $v_header['uid']);
        !          2947:                 @chgrp($v_header['filename'], $v_header['gid']);
        !          2948:             }
1.1       misho    2949: 
                   2950:             // ----- Change the file mode, mtime
                   2951:             @touch($v_header['filename'], $v_header['mtime']);
                   2952:             if ($v_header['mode'] & 0111) {
                   2953:                 // make file executable, obey umask
                   2954:                 $mode = fileperms($v_header['filename']) | (~umask() & 0111);
                   2955:                 @chmod($v_header['filename'], $mode);
                   2956:             }
                   2957:           }
                   2958: 
                   2959:           // ----- Check the file size
                   2960:           clearstatcache();
                   2961:           if (!is_file($v_header['filename'])) {
                   2962:               $this->_error('Extracted file '.$v_header['filename']
                   2963:                             .'does not exist. Archive may be corrupted.');
                   2964:               return false;
                   2965:           }
                   2966:           
                   2967:           $filesize = filesize($v_header['filename']);
                   2968:           if ($filesize != $v_header['size']) {
                   2969:               $this->_error('Extracted file '.$v_header['filename']
                   2970:                             .' does not have the correct file size \''
                   2971:                             .$filesize
                   2972:                             .'\' ('.$v_header['size']
                   2973:                             .' expected). Archive may be corrupted.');
                   2974:               return false;
                   2975:           }
                   2976:           }
                   2977:         } else {
                   2978:           $this->_jumpBlock(ceil(($v_header['size']/512)));
                   2979:         }
                   2980:       } else {
                   2981:           $this->_jumpBlock(ceil(($v_header['size']/512)));
                   2982:       }
                   2983: 
                   2984:       /* TBC : Seems to be unused ...
                   2985:       if ($this->_compress)
                   2986:         $v_end_of_file = @gzeof($this->_file);
                   2987:       else
                   2988:         $v_end_of_file = @feof($this->_file);
                   2989:         */
                   2990: 
                   2991:       if ($v_listing || $v_extract_file || $v_extraction_stopped) {
                   2992:         // ----- Log extracted files
                   2993:         if (($v_file_dir = dirname($v_header['filename']))
                   2994:                    == $v_header['filename'])
                   2995:           $v_file_dir = '';
                   2996:         if ((substr($v_header['filename'], 0, 1) == '/') && ($v_file_dir == ''))
                   2997:           $v_file_dir = '/';
                   2998: 
                   2999:         $p_list_detail[$v_nb++] = $v_header;
                   3000:         if (is_array($p_file_list) && (count($p_list_detail) == count($p_file_list))) {
                   3001:             return true;
                   3002:         }
                   3003:       }
                   3004:     }
                   3005: 
                   3006:         return true;
                   3007:     }
                   3008:     // }}}
                   3009: 
                   3010:     // {{{ _openAppend()
                   3011:     function _openAppend()
                   3012:     {
                   3013:         if (filesize($this->_tarname) == 0)
                   3014:           return $this->_openWrite();
                   3015: 
                   3016:         if ($this->_compress) {
                   3017:             $this->_close();
                   3018: 
                   3019:             if (!@rename($this->_tarname, $this->_tarname.".tmp")) {
                   3020:                 $this->_error('Error while renaming \''.$this->_tarname
                   3021:                                              .'\' to temporary file \''.$this->_tarname
                   3022:                                                          .'.tmp\'');
                   3023:                 return false;
                   3024:             }
                   3025: 
                   3026:             if ($this->_compress_type == 'gz')
                   3027:                 $v_temp_tar = @gzopen($this->_tarname.".tmp", "rb");
                   3028:             elseif ($this->_compress_type == 'bz2')
                   3029:                 $v_temp_tar = @bzopen($this->_tarname.".tmp", "r");
                   3030: 
                   3031:             if ($v_temp_tar == 0) {
                   3032:                 $this->_error('Unable to open file \''.$this->_tarname
                   3033:                                              .'.tmp\' in binary read mode');
                   3034:                 @rename($this->_tarname.".tmp", $this->_tarname);
                   3035:                 return false;
                   3036:             }
                   3037: 
                   3038:             if (!$this->_openWrite()) {
                   3039:                 @rename($this->_tarname.".tmp", $this->_tarname);
                   3040:                 return false;
                   3041:             }
                   3042: 
                   3043:             if ($this->_compress_type == 'gz') {
1.1.1.2 ! misho    3044:                 $end_blocks = 0;
        !          3045:                 
1.1       misho    3046:                 while (!@gzeof($v_temp_tar)) {
                   3047:                     $v_buffer = @gzread($v_temp_tar, 512);
1.1.1.2 ! misho    3048:                     if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
        !          3049:                         $end_blocks++;
1.1       misho    3050:                         // do not copy end blocks, we will re-make them
                   3051:                         // after appending
                   3052:                         continue;
1.1.1.2 ! misho    3053:                     } elseif ($end_blocks > 0) {
        !          3054:                         for ($i = 0; $i < $end_blocks; $i++) {
        !          3055:                             $this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
        !          3056:                         }
        !          3057:                         $end_blocks = 0;
1.1       misho    3058:                     }
                   3059:                     $v_binary_data = pack("a512", $v_buffer);
                   3060:                     $this->_writeBlock($v_binary_data);
                   3061:                 }
                   3062: 
                   3063:                 @gzclose($v_temp_tar);
                   3064:             }
                   3065:             elseif ($this->_compress_type == 'bz2') {
1.1.1.2 ! misho    3066:                 $end_blocks = 0;
        !          3067:                 
1.1       misho    3068:                 while (strlen($v_buffer = @bzread($v_temp_tar, 512)) > 0) {
1.1.1.2 ! misho    3069:                     if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
        !          3070:                         $end_blocks++;
        !          3071:                         // do not copy end blocks, we will re-make them
        !          3072:                         // after appending
1.1       misho    3073:                         continue;
1.1.1.2 ! misho    3074:                     } elseif ($end_blocks > 0) {
        !          3075:                         for ($i = 0; $i < $end_blocks; $i++) {
        !          3076:                             $this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
        !          3077:                         }
        !          3078:                         $end_blocks = 0;
1.1       misho    3079:                     }
                   3080:                     $v_binary_data = pack("a512", $v_buffer);
                   3081:                     $this->_writeBlock($v_binary_data);
                   3082:                 }
                   3083: 
                   3084:                 @bzclose($v_temp_tar);
                   3085:             }
                   3086: 
                   3087:             if (!@unlink($this->_tarname.".tmp")) {
                   3088:                 $this->_error('Error while deleting temporary file \''
                   3089:                                              .$this->_tarname.'.tmp\'');
                   3090:             }
                   3091: 
                   3092:         } else {
                   3093:             // ----- For not compressed tar, just add files before the last
                   3094:                        //       one or two 512 bytes block
                   3095:             if (!$this->_openReadWrite())
                   3096:                return false;
                   3097: 
                   3098:             clearstatcache();
                   3099:             $v_size = filesize($this->_tarname);
                   3100: 
                   3101:             // We might have zero, one or two end blocks.
                   3102:             // The standard is two, but we should try to handle
                   3103:             // other cases.
                   3104:             fseek($this->_file, $v_size - 1024);
                   3105:             if (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) {
                   3106:                 fseek($this->_file, $v_size - 1024);
                   3107:             }
                   3108:             elseif (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) {
                   3109:                 fseek($this->_file, $v_size - 512);
                   3110:             }
                   3111:         }
                   3112: 
                   3113:         return true;
                   3114:     }
                   3115:     // }}}
                   3116: 
                   3117:     // {{{ _append()
                   3118:     function _append($p_filelist, $p_add_dir='', $p_remove_dir='')
                   3119:     {
                   3120:         if (!$this->_openAppend())
                   3121:             return false;
                   3122: 
                   3123:         if ($this->_addList($p_filelist, $p_add_dir, $p_remove_dir))
                   3124:            $this->_writeFooter();
                   3125: 
                   3126:         $this->_close();
                   3127: 
                   3128:         return true;
                   3129:     }
                   3130:     // }}}
                   3131: 
                   3132:     // {{{ _dirCheck()
                   3133: 
                   3134:     /**
                   3135:      * Check if a directory exists and create it (including parent
                   3136:      * dirs) if not.
                   3137:      *
                   3138:      * @param string $p_dir directory to check
                   3139:      *
                   3140:      * @return bool true if the directory exists or was created
                   3141:      */
                   3142:     function _dirCheck($p_dir)
                   3143:     {
                   3144:         clearstatcache();
                   3145:         if ((@is_dir($p_dir)) || ($p_dir == ''))
                   3146:             return true;
                   3147: 
                   3148:         $p_parent_dir = dirname($p_dir);
                   3149: 
                   3150:         if (($p_parent_dir != $p_dir) &&
                   3151:             ($p_parent_dir != '') &&
                   3152:             (!$this->_dirCheck($p_parent_dir)))
                   3153:              return false;
                   3154: 
                   3155:         if (!@mkdir($p_dir, 0777)) {
                   3156:             $this->_error("Unable to create directory '$p_dir'");
                   3157:             return false;
                   3158:         }
                   3159: 
                   3160:         return true;
                   3161:     }
                   3162: 
                   3163:     // }}}
                   3164: 
                   3165:     // {{{ _pathReduction()
                   3166: 
                   3167:     /**
                   3168:      * Compress path by changing for example "/dir/foo/../bar" to "/dir/bar",
                   3169:      * rand emove double slashes.
                   3170:      *
                   3171:      * @param string $p_dir path to reduce
                   3172:      *
                   3173:      * @return string reduced path
                   3174:      *
                   3175:      * @access private
                   3176:      *
                   3177:      */
                   3178:     function _pathReduction($p_dir)
                   3179:     {
                   3180:         $v_result = '';
                   3181: 
                   3182:         // ----- Look for not empty path
                   3183:         if ($p_dir != '') {
                   3184:             // ----- Explode path by directory names
                   3185:             $v_list = explode('/', $p_dir);
                   3186: 
                   3187:             // ----- Study directories from last to first
                   3188:             for ($i=sizeof($v_list)-1; $i>=0; $i--) {
                   3189:                 // ----- Look for current path
                   3190:                 if ($v_list[$i] == ".") {
                   3191:                     // ----- Ignore this directory
                   3192:                     // Should be the first $i=0, but no check is done
                   3193:                 }
                   3194:                 else if ($v_list[$i] == "..") {
                   3195:                     // ----- Ignore it and ignore the $i-1
                   3196:                     $i--;
                   3197:                 }
                   3198:                 else if (   ($v_list[$i] == '')
                   3199:                                         && ($i!=(sizeof($v_list)-1))
                   3200:                                                 && ($i!=0)) {
                   3201:                     // ----- Ignore only the double '//' in path,
                   3202:                     // but not the first and last /
                   3203:                 } else {
                   3204:                     $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?'/'
                   3205:                                                    .$v_result:'');
                   3206:                 }
                   3207:             }
                   3208:         }
1.1.1.2 ! misho    3209:         
        !          3210:         if (defined('OS_WINDOWS') && OS_WINDOWS) {
        !          3211:             $v_result = strtr($v_result, '\\', '/');
        !          3212:         }
        !          3213:         
1.1       misho    3214:         return $v_result;
                   3215:     }
                   3216: 
                   3217:     // }}}
                   3218: 
                   3219:     // {{{ _translateWinPath()
                   3220:     function _translateWinPath($p_path, $p_remove_disk_letter=true)
                   3221:     {
                   3222:       if (defined('OS_WINDOWS') && OS_WINDOWS) {
                   3223:           // ----- Look for potential disk letter
                   3224:           if (   ($p_remove_disk_letter)
                   3225:                      && (($v_position = strpos($p_path, ':')) != false)) {
                   3226:               $p_path = substr($p_path, $v_position+1);
                   3227:           }
                   3228:           // ----- Change potential windows directory separator
                   3229:           if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) {
                   3230:               $p_path = strtr($p_path, '\\', '/');
                   3231:           }
                   3232:       }
                   3233:       return $p_path;
                   3234:     }
                   3235:     // }}}
                   3236: 
                   3237: }
                   3238: ?>
1.1.1.2 ! misho    3239: package.xml0000644000175000017500000002540212105433221012167 0ustar  druiddruid<?xml version="1.0" encoding="UTF-8"?>
        !          3240: <package packagerversion="1.9.4" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
1.1       misho    3241:  <name>Archive_Tar</name>
                   3242:  <channel>pear.php.net</channel>
                   3243:  <summary>Tar file management class</summary>
                   3244:  <description>This class provides handling of tar files in PHP.
                   3245: It supports creating, listing, extracting and adding to tar files.
                   3246: Gzip support is available if PHP has the zlib extension built-in or
                   3247: loaded. Bz2 compression is also supported with the bz2 extension loaded.</description>
                   3248:  <lead>
                   3249:   <name>Vincent Blavet</name>
                   3250:   <user>vblavet</user>
                   3251:   <email>vincent@phpconcept.net</email>
                   3252:   <active>no</active>
                   3253:  </lead>
                   3254:  <lead>
                   3255:   <name>Greg Beaver</name>
                   3256:   <user>cellog</user>
                   3257:   <email>greg@chiaraquartet.net</email>
                   3258:   <active>no</active>
                   3259:  </lead>
                   3260:  <lead>
                   3261:   <name>Michiel Rook</name>
                   3262:   <user>mrook</user>
                   3263:   <email>mrook@php.net</email>
                   3264:   <active>yes</active>
                   3265:  </lead>
                   3266:  <helper>
                   3267:   <name>Stig Bakken</name>
                   3268:   <user>ssb</user>
                   3269:   <email>stig@php.net</email>
                   3270:   <active>no</active>
                   3271:  </helper>
1.1.1.2 ! misho    3272:  <date>2013-02-09</date>
        !          3273:  <time>11:44:17</time>
1.1       misho    3274:  <version>
1.1.1.2 ! misho    3275:   <release>1.3.11</release>
1.1       misho    3276:   <api>1.3.1</api>
                   3277:  </version>
                   3278:  <stability>
                   3279:   <release>stable</release>
                   3280:   <api>stable</api>
                   3281:  </stability>
                   3282:  <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
                   3283:  <notes>
1.1.1.2 ! misho    3284: * Fix Bug #19746: Broken with PHP 5.5 [mrook]
        !          3285:  * Implement Feature #11258: Custom date/time in files added on-the-fly [mrook]
1.1       misho    3286:  </notes>
                   3287:  <contents>
                   3288:   <dir name="/">
1.1.1.2 ! misho    3289:    <file baseinstalldir="/" md5sum="c6a0c1df229783f55d2c3e5e93c46d6e" name="Archive/Tar.php" role="php" />
1.1       misho    3290:    <file baseinstalldir="/" md5sum="29b03715377b18b1fafcff98a99cc9a7" name="docs/Archive_Tar.txt" role="doc" />
                   3291:   </dir>
                   3292:  </contents>
                   3293:  <compatible>
                   3294:   <name>PEAR</name>
                   3295:   <channel>pear.php.net</channel>
                   3296:   <min>1.8.0</min>
                   3297:   <max>1.9.10</max>
                   3298:  </compatible>
                   3299:  <dependencies>
                   3300:   <required>
                   3301:    <php>
                   3302:     <min>4.3.0</min>
                   3303:    </php>
                   3304:    <pearinstaller>
                   3305:     <min>1.5.4</min>
                   3306:    </pearinstaller>
                   3307:   </required>
                   3308:  </dependencies>
                   3309:  <phprelease />
                   3310:  <changelog>
                   3311:   <release>
                   3312:    <version>
1.1.1.2 ! misho    3313:     <release>1.3.10</release>
        !          3314:     <api>1.3.1</api>
        !          3315:    </version>
        !          3316:    <stability>
        !          3317:     <release>stable</release>
        !          3318:     <api>stable</api>
        !          3319:    </stability>
        !          3320:    <date>2012-04-10</date>
        !          3321:    <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD
        !          3322:    License</license>
        !          3323:    <notes>
        !          3324: * Fix Bug #13361: Unable to add() some files (ex. mp3) [mrook]
        !          3325:  * Fix Bug #19330: Class creates incorrect (non-readable) tar.gz file
        !          3326:  * [mrook]
        !          3327:    </notes>
        !          3328:   </release>
        !          3329:   <release>
        !          3330:    <version>
        !          3331:     <release>1.3.9</release>
        !          3332:     <api>1.3.1</api>
        !          3333:    </version>
        !          3334:    <stability>
        !          3335:     <release>stable</release>
        !          3336:     <api>stable</api>
        !          3337:    </stability>
        !          3338:    <date>2012-02-27</date>
        !          3339:    <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD   License</license>
        !          3340:    <notes>
        !          3341: * Fix Bug #16759: No error thrown from missing PHP zlib functions [mrook]
        !          3342:  * Fix Bug #18877: Incorrect handling of backslashes in filenames on Linux [mrook]
        !          3343:  * Fix Bug #19085: Error while packaging [mrook]
        !          3344:  * Fix Bug #19289: Invalid tar file generated [mrook]
        !          3345:    </notes>
        !          3346:   </release>
        !          3347:   <release>
        !          3348:    <version>
        !          3349:     <release>1.3.8</release>
        !          3350:     <api>1.3.1</api>
        !          3351:    </version>
        !          3352:    <stability>
        !          3353:     <release>stable</release>
        !          3354:     <api>stable</api>
        !          3355:    </stability>
        !          3356:    <date>2011-10-14</date>
        !          3357:    <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
        !          3358:    <notes>
        !          3359: * Fix Bug #17853: Test failure: dirtraversal.phpt [mrook]
        !          3360:  * Fix Bug #18512: dead links are not saved in tar file [mrook]
        !          3361:  * Fix Bug #18702: Unpacks incorrectly on long file names using header prefix [mrook]
        !          3362:  * Implement Feature #10145: Patch to return a Pear Error Object on failure [mrook]
        !          3363:  * Implement Feature #17491: Option to preserve permissions [mrook]
        !          3364:  * Implement Feature #17813: Prevent PHP notice when extracting corrupted archive [mrook]
        !          3365:    </notes>
        !          3366:   </release>
        !          3367:   <release>
        !          3368:    <version>
        !          3369:     <release>1.3.7</release>
        !          3370:     <api>1.3.1</api>
        !          3371:    </version>
        !          3372:    <stability>
        !          3373:     <release>stable</release>
        !          3374:     <api>stable</api>
        !          3375:    </stability>
        !          3376:    <date>2010-04-26</date>
        !          3377:    <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
        !          3378:    <notes>
        !          3379: PEAR compatibility update
        !          3380:    </notes>
        !          3381:   </release>
        !          3382:   <release>
        !          3383:    <version>
1.1       misho    3384:     <release>1.3.6</release>
                   3385:     <api>1.3.1</api>
                   3386:    </version>
                   3387:    <stability>
                   3388:     <release>stable</release>
                   3389:     <api>stable</api>
                   3390:    </stability>
                   3391:    <date>2010-03-09</date>
                   3392:    <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
                   3393:    <notes>
                   3394: * Fix Bug #16963: extractList can&apos;t extract zipped files from big tar [mrook]
                   3395:  * Implement Feature #4013: Ignoring files and directories on creating an archive. [mrook]
                   3396:    </notes>
                   3397:   </release>
                   3398:   <release>
                   3399:    <version>
                   3400:     <release>1.3.5</release>
                   3401:     <api>1.3.1</api>
                   3402:    </version>
                   3403:    <stability>
                   3404:     <release>stable</release>
                   3405:     <api>stable</api>
                   3406:    </stability>
                   3407:    <date>2009-12-31</date>
                   3408:    <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
                   3409:    <notes>
                   3410: * Fix Bug #16958: Update &apos;compatible&apos; tag in package.xml [mrook]
                   3411:    </notes>
                   3412:   </release>
                   3413:   <release>
                   3414:    <version>
                   3415:     <release>1.3.4</release>
                   3416:     <api>1.3.1</api>
                   3417:    </version>
                   3418:    <stability>
                   3419:     <release>stable</release>
                   3420:     <api>stable</api>
                   3421:    </stability>
                   3422:    <date>2009-12-30</date>
                   3423:    <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
                   3424:    <notes>
                   3425: * Fix Bug #11871: wrong result of ::listContent() if filename begins or ends with space [mrook]
                   3426:  * Fix Bug #12462: invalid tar magic [mrook]
                   3427:  * Fix Bug #13918: Long filenames may get up to 511 0x00 bytes appended on read [mrook]
                   3428:  * Fix Bug #16202: Bogus modification times [mrook]
                   3429:  * Implement Feature #16212: Die is not exception [mrook]
                   3430:    </notes>
                   3431:   </release>
                   3432:   <release>
                   3433:    <version>
                   3434:     <release>1.3.3</release>
                   3435:     <api>1.3.1</api>
                   3436:    </version>
                   3437:    <stability>
                   3438:     <release>stable</release>
                   3439:     <api>stable</api>
                   3440:    </stability>
                   3441:    <date>2009-03-27</date>
                   3442:    <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
                   3443:    <notes>
                   3444: Change the license to New BSD license
                   3445: 
                   3446:    minor bugfix release
                   3447:    * fix Bug #9921 compression with bzip2 fails [cellog]
                   3448:    * fix Bug #11594 _readLongHeader leaves 0 bytes in filename [jamessas]
                   3449:    * fix Bug #11769 Incorrect symlink handing [fajar99]
                   3450:    </notes>
                   3451:   </release>
                   3452:   <release>
                   3453:    <version>
                   3454:     <release>1.3.2</release>
                   3455:     <api>1.3.1</api>
                   3456:    </version>
                   3457:    <stability>
                   3458:     <release>stable</release>
                   3459:     <api>stable</api>
                   3460:    </stability>
                   3461:    <date>2007-01-03</date>
                   3462:    <license uri="http://www.php.net/license">PHP License</license>
                   3463:    <notes>
                   3464: Correct Bug #4016
                   3465: Remove duplicate remove error display with &apos;@&apos;
                   3466: Correct Bug #3909 : Check existence of OS_WINDOWS constant
                   3467: Correct Bug #5452 fix for &quot;lone zero block&quot; when untarring packages
                   3468: Change filemode (from pear-core/Archive/Tar.php v.1.21)
                   3469: Correct Bug #6486 Can not extract symlinks
                   3470: Correct Bug #6933 Archive_Tar (Tar file management class) Directory traversal
                   3471: Correct Bug #8114 Files added on-the-fly not storing date
                   3472: Correct Bug #9352 Bug on _dirCheck function over nfs path
                   3473:    </notes>
                   3474:   </release>
                   3475:   <release>
                   3476:    <version>
                   3477:     <release>1.3.1</release>
                   3478:     <api>1.3.1</api>
                   3479:    </version>
                   3480:    <stability>
                   3481:     <release>stable</release>
                   3482:     <api>stable</api>
                   3483:    </stability>
                   3484:    <date>2005-03-17</date>
                   3485:    <license uri="http://www.php.net/license">PHP License</license>
                   3486:    <notes>
                   3487: Correct Bug #3855
                   3488:    </notes>
                   3489:   </release>
                   3490:   <release>
                   3491:    <version>
                   3492:     <release>1.3.0</release>
                   3493:     <api>1.3.0</api>
                   3494:    </version>
                   3495:    <stability>
                   3496:     <release>stable</release>
                   3497:     <api>stable</api>
                   3498:    </stability>
                   3499:    <date>2005-03-06</date>
                   3500:    <license uri="http://www.php.net/license">PHP License</license>
                   3501:    <notes>
                   3502: Bugs correction (2475, 2488, 2135, 2176)
                   3503:    </notes>
                   3504:   </release>
                   3505:   <release>
                   3506:    <version>
                   3507:     <release>1.2</release>
                   3508:     <api>1.2</api>
                   3509:    </version>
                   3510:    <stability>
                   3511:     <release>stable</release>
                   3512:     <api>stable</api>
                   3513:    </stability>
                   3514:    <date>2004-05-08</date>
                   3515:    <license uri="http://www.php.net/license">PHP License</license>
                   3516:    <notes>
                   3517: Add support for other separator than the space char and bug
                   3518:        correction
                   3519:    </notes>
                   3520:   </release>
                   3521:   <release>
                   3522:    <version>
                   3523:     <release>1.1</release>
                   3524:     <api>1.1</api>
                   3525:    </version>
                   3526:    <stability>
                   3527:     <release>stable</release>
                   3528:     <api>stable</api>
                   3529:    </stability>
                   3530:    <date>2003-05-28</date>
                   3531:    <license uri="http://www.php.net/license">PHP License</license>
                   3532:    <notes>
                   3533: * Add support for BZ2 compression
                   3534: * Add support for add and extract without using temporary files : methods addString() and extractInString()
                   3535:    </notes>
                   3536:   </release>
                   3537:   <release>
                   3538:    <version>
                   3539:     <release>1.0</release>
                   3540:     <api>1.0</api>
                   3541:    </version>
                   3542:    <stability>
                   3543:     <release>stable</release>
                   3544:     <api>stable</api>
                   3545:    </stability>
                   3546:    <date>2003-01-24</date>
                   3547:    <license uri="http://www.php.net/license">PHP License</license>
                   3548:    <notes>
                   3549: Change status to stable
                   3550:    </notes>
                   3551:   </release>
                   3552:   <release>
                   3553:    <version>
                   3554:     <release>0.10-b1</release>
                   3555:     <api>0.10-b1</api>
                   3556:    </version>
                   3557:    <stability>
                   3558:     <release>beta</release>
                   3559:     <api>beta</api>
                   3560:    </stability>
                   3561:    <date>2003-01-08</date>
                   3562:    <license uri="http://www.php.net/license">PHP License</license>
                   3563:    <notes>
                   3564: Add support for long filenames (greater than 99 characters)
                   3565:    </notes>
                   3566:   </release>
                   3567:   <release>
                   3568:    <version>
                   3569:     <release>0.9</release>
                   3570:     <api>0.9</api>
                   3571:    </version>
                   3572:    <stability>
                   3573:     <release>stable</release>
                   3574:     <api>stable</api>
                   3575:    </stability>
                   3576:    <date>2002-05-27</date>
                   3577:    <license uri="http://www.php.net/license">PHP License</license>
                   3578:    <notes>
                   3579: Auto-detect gzip&apos;ed files
                   3580:    </notes>
                   3581:   </release>
                   3582:   <release>
                   3583:    <version>
                   3584:     <release>0.4</release>
                   3585:     <api>0.4</api>
                   3586:    </version>
                   3587:    <stability>
                   3588:     <release>stable</release>
                   3589:     <api>stable</api>
                   3590:    </stability>
                   3591:    <date>2002-05-20</date>
                   3592:    <license uri="http://www.php.net/license">PHP License</license>
                   3593:    <notes>
                   3594: Windows bugfix: use forward slashes inside archives
                   3595:    </notes>
                   3596:   </release>
                   3597:   <release>
                   3598:    <version>
                   3599:     <release>0.2</release>
                   3600:     <api>0.2</api>
                   3601:    </version>
                   3602:    <stability>
                   3603:     <release>stable</release>
                   3604:     <api>stable</api>
                   3605:    </stability>
                   3606:    <date>2002-02-18</date>
                   3607:    <license uri="http://www.php.net/license">PHP License</license>
                   3608:    <notes>
                   3609: From initial commit to stable
                   3610:    </notes>
                   3611:   </release>
                   3612:   <release>
                   3613:    <version>
                   3614:     <release>0.3</release>
                   3615:     <api>0.3</api>
                   3616:    </version>
                   3617:    <stability>
                   3618:     <release>stable</release>
                   3619:     <api>stable</api>
                   3620:    </stability>
                   3621:    <date>2002-04-13</date>
                   3622:    <license uri="http://www.php.net/license">PHP License</license>
                   3623:    <notes>
                   3624: Windows bugfix: used wrong directory separators
                   3625:    </notes>
                   3626:   </release>
                   3627:  </changelog>
                   3628: </package>
1.1.1.2 ! misho    3629: Archive_Tar-1.3.11/Archive/Tar.php0000644000175000017500000020257612105433221015611 0ustar  druiddruid<?php
1.1       misho    3630: /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
                   3631: 
                   3632: /**
                   3633:  * File::CSV
                   3634:  *
                   3635:  * PHP versions 4 and 5
                   3636:  *
                   3637:  * Copyright (c) 1997-2008,
                   3638:  * Vincent Blavet <vincent@phpconcept.net>
                   3639:  * All rights reserved.
                   3640:  *
                   3641:  * Redistribution and use in source and binary forms, with or without
                   3642:  * modification, are permitted provided that the following conditions are met:
                   3643:  *
                   3644:  *     * Redistributions of source code must retain the above copyright notice,
                   3645:  *       this list of conditions and the following disclaimer.
                   3646:  *     * Redistributions in binary form must reproduce the above copyright
                   3647:  *       notice, this list of conditions and the following disclaimer in the
                   3648:  *       documentation and/or other materials provided with the distribution.
                   3649:  *
                   3650:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
                   3651:  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                   3652:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                   3653:  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
                   3654:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                   3655:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                   3656:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
                   3657:  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
                   3658:  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
                   3659:  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                   3660:  *
1.1.1.2 ! misho    3661:  * @category  File_Formats
        !          3662:  * @package   Archive_Tar
        !          3663:  * @author    Vincent Blavet <vincent@phpconcept.net>
        !          3664:  * @copyright 1997-2010 The Authors
        !          3665:  * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
        !          3666:  * @version   CVS: $Id$
        !          3667:  * @link      http://pear.php.net/package/Archive_Tar
1.1       misho    3668:  */
                   3669: 
                   3670: require_once 'PEAR.php';
                   3671: 
1.1.1.2 ! misho    3672: define('ARCHIVE_TAR_ATT_SEPARATOR', 90001);
        !          3673: define('ARCHIVE_TAR_END_BLOCK', pack("a512", ''));
1.1       misho    3674: 
                   3675: /**
                   3676: * Creates a (compressed) Tar archive
                   3677: *
1.1.1.2 ! misho    3678: * @package Archive_Tar
        !          3679: * @author  Vincent Blavet <vincent@phpconcept.net>
        !          3680: * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
        !          3681: * @version $Revision$
1.1       misho    3682: */
                   3683: class Archive_Tar extends PEAR
                   3684: {
                   3685:     /**
                   3686:     * @var string Name of the Tar
                   3687:     */
                   3688:     var $_tarname='';
                   3689: 
                   3690:     /**
                   3691:     * @var boolean if true, the Tar file will be gzipped
                   3692:     */
                   3693:     var $_compress=false;
                   3694: 
                   3695:     /**
                   3696:     * @var string Type of compression : 'none', 'gz' or 'bz2'
                   3697:     */
                   3698:     var $_compress_type='none';
                   3699: 
                   3700:     /**
                   3701:     * @var string Explode separator
                   3702:     */
                   3703:     var $_separator=' ';
                   3704: 
                   3705:     /**
                   3706:     * @var file descriptor
                   3707:     */
                   3708:     var $_file=0;
                   3709: 
                   3710:     /**
                   3711:     * @var string Local Tar name of a remote Tar (http:// or ftp://)
                   3712:     */
                   3713:     var $_temp_tarname='';
                   3714: 
                   3715:     /**
                   3716:     * @var string regular expression for ignoring files or directories
                   3717:     */
                   3718:     var $_ignore_regexp='';
                   3719: 
1.1.1.2 ! misho    3720:     /**
        !          3721:      * @var object PEAR_Error object
        !          3722:      */
        !          3723:     var $error_object=null; 
        !          3724: 
1.1       misho    3725:     // {{{ constructor
                   3726:     /**
                   3727:     * Archive_Tar Class constructor. This flavour of the constructor only
                   3728:     * declare a new Archive_Tar object, identifying it by the name of the
                   3729:     * tar file.
                   3730:     * If the compress argument is set the tar will be read or created as a
                   3731:     * gzip or bz2 compressed TAR file.
                   3732:     *
1.1.1.2 ! misho    3733:     * @param string $p_tarname  The name of the tar archive to create
        !          3734:     * @param string $p_compress can be null, 'gz' or 'bz2'. This
        !          3735:     *               parameter indicates if gzip or bz2 compression
        !          3736:     *               is required.  For compatibility reason the
        !          3737:     *               boolean value 'true' means 'gz'.
        !          3738:     *
1.1       misho    3739:     * @access public
                   3740:     */
                   3741:     function Archive_Tar($p_tarname, $p_compress = null)
                   3742:     {
                   3743:         $this->PEAR();
                   3744:         $this->_compress = false;
                   3745:         $this->_compress_type = 'none';
                   3746:         if (($p_compress === null) || ($p_compress == '')) {
                   3747:             if (@file_exists($p_tarname)) {
                   3748:                 if ($fp = @fopen($p_tarname, "rb")) {
                   3749:                     // look for gzip magic cookie
                   3750:                     $data = fread($fp, 2);
                   3751:                     fclose($fp);
                   3752:                     if ($data == "\37\213") {
                   3753:                         $this->_compress = true;
                   3754:                         $this->_compress_type = 'gz';
1.1.1.2 ! misho    3755:                         // No sure it's enought for a magic code ....
1.1       misho    3756:                     } elseif ($data == "BZ") {
                   3757:                         $this->_compress = true;
                   3758:                         $this->_compress_type = 'bz2';
                   3759:                     }
                   3760:                 }
                   3761:             } else {
                   3762:                 // probably a remote file or some file accessible
                   3763:                 // through a stream interface
                   3764:                 if (substr($p_tarname, -2) == 'gz') {
                   3765:                     $this->_compress = true;
                   3766:                     $this->_compress_type = 'gz';
                   3767:                 } elseif ((substr($p_tarname, -3) == 'bz2') ||
                   3768:                           (substr($p_tarname, -2) == 'bz')) {
                   3769:                     $this->_compress = true;
                   3770:                     $this->_compress_type = 'bz2';
                   3771:                 }
                   3772:             }
                   3773:         } else {
                   3774:             if (($p_compress === true) || ($p_compress == 'gz')) {
                   3775:                 $this->_compress = true;
                   3776:                 $this->_compress_type = 'gz';
                   3777:             } else if ($p_compress == 'bz2') {
                   3778:                 $this->_compress = true;
                   3779:                 $this->_compress_type = 'bz2';
                   3780:             } else {
                   3781:                 $this->_error("Unsupported compression type '$p_compress'\n".
                   3782:                     "Supported types are 'gz' and 'bz2'.\n");
                   3783:                 return false;
                   3784:             }
                   3785:         }
                   3786:         $this->_tarname = $p_tarname;
                   3787:         if ($this->_compress) { // assert zlib or bz2 extension support
                   3788:             if ($this->_compress_type == 'gz')
                   3789:                 $extname = 'zlib';
                   3790:             else if ($this->_compress_type == 'bz2')
                   3791:                 $extname = 'bz2';
                   3792: 
                   3793:             if (!extension_loaded($extname)) {
                   3794:                 PEAR::loadExtension($extname);
                   3795:             }
                   3796:             if (!extension_loaded($extname)) {
                   3797:                 $this->_error("The extension '$extname' couldn't be found.\n".
                   3798:                     "Please make sure your version of PHP was built ".
                   3799:                     "with '$extname' support.\n");
                   3800:                 return false;
                   3801:             }
                   3802:         }
                   3803:     }
                   3804:     // }}}
                   3805: 
                   3806:     // {{{ destructor
                   3807:     function _Archive_Tar()
                   3808:     {
                   3809:         $this->_close();
                   3810:         // ----- Look for a local copy to delete
                   3811:         if ($this->_temp_tarname != '')
                   3812:             @unlink($this->_temp_tarname);
                   3813:         $this->_PEAR();
                   3814:     }
                   3815:     // }}}
                   3816: 
                   3817:     // {{{ create()
                   3818:     /**
                   3819:     * This method creates the archive file and add the files / directories
                   3820:     * that are listed in $p_filelist.
                   3821:     * If a file with the same name exist and is writable, it is replaced
                   3822:     * by the new tar.
                   3823:     * The method return false and a PEAR error text.
                   3824:     * The $p_filelist parameter can be an array of string, each string
                   3825:     * representing a filename or a directory name with their path if
                   3826:     * needed. It can also be a single string with names separated by a
                   3827:     * single blank.
                   3828:     * For each directory added in the archive, the files and
                   3829:     * sub-directories are also added.
                   3830:     * See also createModify() method for more details.
                   3831:     *
1.1.1.2 ! misho    3832:     * @param array $p_filelist An array of filenames and directory names, or a
        !          3833:     *              single string with names separated by a single
        !          3834:     *              blank space.
        !          3835:     *
        !          3836:     * @return true on success, false on error.
        !          3837:     * @see    createModify()
1.1       misho    3838:     * @access public
                   3839:     */
                   3840:     function create($p_filelist)
                   3841:     {
                   3842:         return $this->createModify($p_filelist, '', '');
                   3843:     }
                   3844:     // }}}
                   3845: 
                   3846:     // {{{ add()
                   3847:     /**
                   3848:     * This method add the files / directories that are listed in $p_filelist in
                   3849:     * the archive. If the archive does not exist it is created.
                   3850:     * The method return false and a PEAR error text.
                   3851:     * The files and directories listed are only added at the end of the archive,
                   3852:     * even if a file with the same name is already archived.
                   3853:     * See also createModify() method for more details.
                   3854:     *
1.1.1.2 ! misho    3855:     * @param array $p_filelist An array of filenames and directory names, or a
        !          3856:     *              single string with names separated by a single
        !          3857:     *              blank space.
        !          3858:     *
        !          3859:     * @return true on success, false on error.
        !          3860:     * @see    createModify()
1.1       misho    3861:     * @access public
                   3862:     */
                   3863:     function add($p_filelist)
                   3864:     {
                   3865:         return $this->addModify($p_filelist, '', '');
                   3866:     }
                   3867:     // }}}
                   3868: 
                   3869:     // {{{ extract()
1.1.1.2 ! misho    3870:     function extract($p_path='', $p_preserve=false)
1.1       misho    3871:     {
1.1.1.2 ! misho    3872:         return $this->extractModify($p_path, '', $p_preserve);
1.1       misho    3873:     }
                   3874:     // }}}
                   3875: 
                   3876:     // {{{ listContent()
                   3877:     function listContent()
                   3878:     {
                   3879:         $v_list_detail = array();
                   3880: 
                   3881:         if ($this->_openRead()) {
                   3882:             if (!$this->_extractList('', $v_list_detail, "list", '', '')) {
                   3883:                 unset($v_list_detail);
                   3884:                 $v_list_detail = 0;
                   3885:             }
                   3886:             $this->_close();
                   3887:         }
                   3888: 
                   3889:         return $v_list_detail;
                   3890:     }
                   3891:     // }}}
                   3892: 
                   3893:     // {{{ createModify()
                   3894:     /**
                   3895:     * This method creates the archive file and add the files / directories
                   3896:     * that are listed in $p_filelist.
                   3897:     * If the file already exists and is writable, it is replaced by the
                   3898:     * new tar. It is a create and not an add. If the file exists and is
                   3899:     * read-only or is a directory it is not replaced. The method return
                   3900:     * false and a PEAR error text.
                   3901:     * The $p_filelist parameter can be an array of string, each string
                   3902:     * representing a filename or a directory name with their path if
                   3903:     * needed. It can also be a single string with names separated by a
                   3904:     * single blank.
                   3905:     * The path indicated in $p_remove_dir will be removed from the
                   3906:     * memorized path of each file / directory listed when this path
                   3907:     * exists. By default nothing is removed (empty path '')
                   3908:     * The path indicated in $p_add_dir will be added at the beginning of
                   3909:     * the memorized path of each file / directory listed. However it can
                   3910:     * be set to empty ''. The adding of a path is done after the removing
                   3911:     * of path.
                   3912:     * The path add/remove ability enables the user to prepare an archive
                   3913:     * for extraction in a different path than the origin files are.
                   3914:     * See also addModify() method for file adding properties.
                   3915:     *
1.1.1.2 ! misho    3916:     * @param array  $p_filelist   An array of filenames and directory names,
        !          3917:     *                             or a single string with names separated by
        !          3918:     *                             a single blank space.
        !          3919:     * @param string $p_add_dir    A string which contains a path to be added
        !          3920:     *                             to the memorized path of each element in
        !          3921:     *                             the list.
        !          3922:     * @param string $p_remove_dir A string which contains a path to be
        !          3923:     *                             removed from the memorized path of each
        !          3924:     *                             element in the list, when relevant.
        !          3925:     *
        !          3926:     * @return boolean true on success, false on error.
1.1       misho    3927:     * @access public
                   3928:     * @see addModify()
                   3929:     */
                   3930:     function createModify($p_filelist, $p_add_dir, $p_remove_dir='')
                   3931:     {
                   3932:         $v_result = true;
                   3933: 
                   3934:         if (!$this->_openWrite())
                   3935:             return false;
                   3936: 
                   3937:         if ($p_filelist != '') {
                   3938:             if (is_array($p_filelist))
                   3939:                 $v_list = $p_filelist;
                   3940:             elseif (is_string($p_filelist))
                   3941:                 $v_list = explode($this->_separator, $p_filelist);
                   3942:             else {
                   3943:                 $this->_cleanFile();
                   3944:                 $this->_error('Invalid file list');
                   3945:                 return false;
                   3946:             }
                   3947: 
                   3948:             $v_result = $this->_addList($v_list, $p_add_dir, $p_remove_dir);
                   3949:         }
                   3950: 
                   3951:         if ($v_result) {
                   3952:             $this->_writeFooter();
                   3953:             $this->_close();
                   3954:         } else
                   3955:             $this->_cleanFile();
                   3956: 
                   3957:         return $v_result;
                   3958:     }
                   3959:     // }}}
                   3960: 
                   3961:     // {{{ addModify()
                   3962:     /**
                   3963:     * This method add the files / directories listed in $p_filelist at the
                   3964:     * end of the existing archive. If the archive does not yet exists it
                   3965:     * is created.
                   3966:     * The $p_filelist parameter can be an array of string, each string
                   3967:     * representing a filename or a directory name with their path if
                   3968:     * needed. It can also be a single string with names separated by a
                   3969:     * single blank.
                   3970:     * The path indicated in $p_remove_dir will be removed from the
                   3971:     * memorized path of each file / directory listed when this path
                   3972:     * exists. By default nothing is removed (empty path '')
                   3973:     * The path indicated in $p_add_dir will be added at the beginning of
                   3974:     * the memorized path of each file / directory listed. However it can
                   3975:     * be set to empty ''. The adding of a path is done after the removing
                   3976:     * of path.
                   3977:     * The path add/remove ability enables the user to prepare an archive
                   3978:     * for extraction in a different path than the origin files are.
                   3979:     * If a file/dir is already in the archive it will only be added at the
                   3980:     * end of the archive. There is no update of the existing archived
                   3981:     * file/dir. However while extracting the archive, the last file will
                   3982:     * replace the first one. This results in a none optimization of the
                   3983:     * archive size.
                   3984:     * If a file/dir does not exist the file/dir is ignored. However an
                   3985:     * error text is send to PEAR error.
                   3986:     * If a file/dir is not readable the file/dir is ignored. However an
                   3987:     * error text is send to PEAR error.
                   3988:     *
1.1.1.2 ! misho    3989:     * @param array  $p_filelist   An array of filenames and directory
        !          3990:     *                             names, or a single string with names
        !          3991:     *                             separated by a single blank space.
        !          3992:     * @param string $p_add_dir    A string which contains a path to be
        !          3993:     *                             added to the memorized path of each
        !          3994:     *                             element in the list.
        !          3995:     * @param string $p_remove_dir A string which contains a path to be
        !          3996:     *                             removed from the memorized path of
        !          3997:     *                             each element in the list, when
        !          3998:     *                             relevant.
        !          3999:     *
        !          4000:     * @return true on success, false on error.
1.1       misho    4001:     * @access public
                   4002:     */
                   4003:     function addModify($p_filelist, $p_add_dir, $p_remove_dir='')
                   4004:     {
                   4005:         $v_result = true;
                   4006: 
                   4007:         if (!$this->_isArchive())
                   4008:             $v_result = $this->createModify($p_filelist, $p_add_dir,
1.1.1.2 ! misho    4009:                                             $p_remove_dir);
1.1       misho    4010:         else {
                   4011:             if (is_array($p_filelist))
                   4012:                 $v_list = $p_filelist;
                   4013:             elseif (is_string($p_filelist))
                   4014:                 $v_list = explode($this->_separator, $p_filelist);
                   4015:             else {
                   4016:                 $this->_error('Invalid file list');
                   4017:                 return false;
                   4018:             }
                   4019: 
                   4020:             $v_result = $this->_append($v_list, $p_add_dir, $p_remove_dir);
                   4021:         }
                   4022: 
                   4023:         return $v_result;
                   4024:     }
                   4025:     // }}}
                   4026: 
                   4027:     // {{{ addString()
                   4028:     /**
                   4029:     * This method add a single string as a file at the
                   4030:     * end of the existing archive. If the archive does not yet exists it
                   4031:     * is created.
                   4032:     *
1.1.1.2 ! misho    4033:     * @param string $p_filename A string which contains the full
        !          4034:     *                           filename path that will be associated
        !          4035:     *                           with the string.
        !          4036:     * @param string $p_string   The content of the file added in
        !          4037:     *                           the archive.
        !          4038:     * @param int    $p_datetime A custom date/time (unix timestamp)
        !          4039:     *                           for the file (optional).
        !          4040:     *
        !          4041:     * @return true on success, false on error.
1.1       misho    4042:     * @access public
                   4043:     */
1.1.1.2 ! misho    4044:     function addString($p_filename, $p_string, $p_datetime = false)
1.1       misho    4045:     {
                   4046:         $v_result = true;
                   4047: 
                   4048:         if (!$this->_isArchive()) {
                   4049:             if (!$this->_openWrite()) {
                   4050:                 return false;
                   4051:             }
                   4052:             $this->_close();
                   4053:         }
                   4054: 
                   4055:         if (!$this->_openAppend())
                   4056:             return false;
                   4057: 
                   4058:         // Need to check the get back to the temporary file ? ....
1.1.1.2 ! misho    4059:         $v_result = $this->_addString($p_filename, $p_string, $p_datetime);
1.1       misho    4060: 
                   4061:         $this->_writeFooter();
                   4062: 
                   4063:         $this->_close();
                   4064: 
                   4065:         return $v_result;
                   4066:     }
                   4067:     // }}}
                   4068: 
                   4069:     // {{{ extractModify()
                   4070:     /**
                   4071:     * This method extract all the content of the archive in the directory
                   4072:     * indicated by $p_path. When relevant the memorized path of the
                   4073:     * files/dir can be modified by removing the $p_remove_path path at the
                   4074:     * beginning of the file/dir path.
                   4075:     * While extracting a file, if the directory path does not exists it is
                   4076:     * created.
                   4077:     * While extracting a file, if the file already exists it is replaced
                   4078:     * without looking for last modification date.
                   4079:     * While extracting a file, if the file already exists and is write
                   4080:     * protected, the extraction is aborted.
                   4081:     * While extracting a file, if a directory with the same name already
                   4082:     * exists, the extraction is aborted.
                   4083:     * While extracting a directory, if a file with the same name already
                   4084:     * exists, the extraction is aborted.
                   4085:     * While extracting a file/directory if the destination directory exist
                   4086:     * and is write protected, or does not exist but can not be created,
                   4087:     * the extraction is aborted.
                   4088:     * If after extraction an extracted file does not show the correct
                   4089:     * stored file size, the extraction is aborted.
                   4090:     * When the extraction is aborted, a PEAR error text is set and false
                   4091:     * is returned. However the result can be a partial extraction that may
                   4092:     * need to be manually cleaned.
                   4093:     *
1.1.1.2 ! misho    4094:     * @param string  $p_path        The path of the directory where the
        !          4095:     *                               files/dir need to by extracted.
        !          4096:     * @param string  $p_remove_path Part of the memorized path that can be
        !          4097:     *                               removed if present at the beginning of
        !          4098:     *                               the file/dir path.
        !          4099:     * @param boolean $p_preserve    Preserve user/group ownership of files
        !          4100:     *
        !          4101:     * @return boolean true on success, false on error.
1.1       misho    4102:     * @access public
1.1.1.2 ! misho    4103:     * @see    extractList()
1.1       misho    4104:     */
1.1.1.2 ! misho    4105:     function extractModify($p_path, $p_remove_path, $p_preserve=false)
1.1       misho    4106:     {
                   4107:         $v_result = true;
                   4108:         $v_list_detail = array();
                   4109: 
                   4110:         if ($v_result = $this->_openRead()) {
                   4111:             $v_result = $this->_extractList($p_path, $v_list_detail,
1.1.1.2 ! misho    4112:                 "complete", 0, $p_remove_path, $p_preserve);
1.1       misho    4113:             $this->_close();
                   4114:         }
                   4115: 
                   4116:         return $v_result;
                   4117:     }
                   4118:     // }}}
                   4119: 
                   4120:     // {{{ extractInString()
                   4121:     /**
                   4122:     * This method extract from the archive one file identified by $p_filename.
                   4123:     * The return value is a string with the file content, or NULL on error.
1.1.1.2 ! misho    4124:     *
        !          4125:     * @param string $p_filename The path of the file to extract in a string.
        !          4126:     *
        !          4127:     * @return a string with the file content or NULL.
1.1       misho    4128:     * @access public
                   4129:     */
                   4130:     function extractInString($p_filename)
                   4131:     {
                   4132:         if ($this->_openRead()) {
                   4133:             $v_result = $this->_extractInString($p_filename);
                   4134:             $this->_close();
                   4135:         } else {
1.1.1.2 ! misho    4136:             $v_result = null;
1.1       misho    4137:         }
                   4138: 
                   4139:         return $v_result;
                   4140:     }
                   4141:     // }}}
                   4142: 
                   4143:     // {{{ extractList()
                   4144:     /**
                   4145:     * This method extract from the archive only the files indicated in the
                   4146:     * $p_filelist. These files are extracted in the current directory or
                   4147:     * in the directory indicated by the optional $p_path parameter.
                   4148:     * If indicated the $p_remove_path can be used in the same way as it is
                   4149:     * used in extractModify() method.
1.1.1.2 ! misho    4150:     *
        !          4151:     * @param array   $p_filelist    An array of filenames and directory names,
        !          4152:     *                               or a single string with names separated
        !          4153:     *                               by a single blank space.
        !          4154:     * @param string  $p_path        The path of the directory where the
        !          4155:     *                               files/dir need to by extracted.
        !          4156:     * @param string  $p_remove_path Part of the memorized path that can be
        !          4157:     *                               removed if present at the beginning of
        !          4158:     *                               the file/dir path.
        !          4159:     * @param boolean $p_preserve    Preserve user/group ownership of files
        !          4160:     *
        !          4161:     * @return true on success, false on error.
1.1       misho    4162:     * @access public
1.1.1.2 ! misho    4163:     * @see    extractModify()
1.1       misho    4164:     */
1.1.1.2 ! misho    4165:     function extractList($p_filelist, $p_path='', $p_remove_path='', $p_preserve=false)
1.1       misho    4166:     {
                   4167:         $v_result = true;
                   4168:         $v_list_detail = array();
                   4169: 
                   4170:         if (is_array($p_filelist))
                   4171:             $v_list = $p_filelist;
                   4172:         elseif (is_string($p_filelist))
                   4173:             $v_list = explode($this->_separator, $p_filelist);
                   4174:         else {
                   4175:             $this->_error('Invalid string list');
                   4176:             return false;
                   4177:         }
                   4178: 
                   4179:         if ($v_result = $this->_openRead()) {
                   4180:             $v_result = $this->_extractList($p_path, $v_list_detail, "partial",
1.1.1.2 ! misho    4181:                 $v_list, $p_remove_path, $p_preserve);
1.1       misho    4182:             $this->_close();
                   4183:         }
                   4184: 
                   4185:         return $v_result;
                   4186:     }
                   4187:     // }}}
                   4188: 
                   4189:     // {{{ setAttribute()
                   4190:     /**
                   4191:     * This method set specific attributes of the archive. It uses a variable
                   4192:     * list of parameters, in the format attribute code + attribute values :
                   4193:     * $arch->setAttribute(ARCHIVE_TAR_ATT_SEPARATOR, ',');
1.1.1.2 ! misho    4194:     *
        !          4195:     * @param mixed $argv variable list of attributes and values
        !          4196:     *
        !          4197:     * @return true on success, false on error.
1.1       misho    4198:     * @access public
                   4199:     */
                   4200:     function setAttribute()
                   4201:     {
                   4202:         $v_result = true;
                   4203: 
                   4204:         // ----- Get the number of variable list of arguments
                   4205:         if (($v_size = func_num_args()) == 0) {
                   4206:             return true;
                   4207:         }
                   4208: 
                   4209:         // ----- Get the arguments
                   4210:         $v_att_list = &func_get_args();
                   4211: 
                   4212:         // ----- Read the attributes
                   4213:         $i=0;
                   4214:         while ($i<$v_size) {
                   4215: 
                   4216:             // ----- Look for next option
                   4217:             switch ($v_att_list[$i]) {
                   4218:                 // ----- Look for options that request a string value
                   4219:                 case ARCHIVE_TAR_ATT_SEPARATOR :
                   4220:                     // ----- Check the number of parameters
                   4221:                     if (($i+1) >= $v_size) {
                   4222:                         $this->_error('Invalid number of parameters for '
                   4223:                                                              .'attribute ARCHIVE_TAR_ATT_SEPARATOR');
                   4224:                         return false;
                   4225:                     }
                   4226: 
                   4227:                     // ----- Get the value
                   4228:                     $this->_separator = $v_att_list[$i+1];
                   4229:                     $i++;
                   4230:                 break;
                   4231: 
                   4232:                 default :
                   4233:                     $this->_error('Unknow attribute code '.$v_att_list[$i].'');
                   4234:                     return false;
                   4235:             }
                   4236: 
                   4237:             // ----- Next attribute
                   4238:             $i++;
                   4239:         }
                   4240: 
                   4241:         return $v_result;
                   4242:     }
                   4243:     // }}}
                   4244: 
                   4245:     // {{{ setIgnoreRegexp()
                   4246:     /**
                   4247:     * This method sets the regular expression for ignoring files and directories
                   4248:     * at import, for example:
                   4249:     * $arch->setIgnoreRegexp("#CVS|\.svn#");
1.1.1.2 ! misho    4250:     *
        !          4251:     * @param string $regexp regular expression defining which files or directories to ignore
        !          4252:     *
1.1       misho    4253:     * @access public
                   4254:     */
                   4255:     function setIgnoreRegexp($regexp)
                   4256:     {
                   4257:        $this->_ignore_regexp = $regexp;
                   4258:     }
                   4259:     // }}}
                   4260: 
                   4261:     // {{{ setIgnoreList()
                   4262:     /**
                   4263:     * This method sets the regular expression for ignoring all files and directories
                   4264:     * matching the filenames in the array list at import, for example:
                   4265:     * $arch->setIgnoreList(array('CVS', '.svn', 'bin/tool'));
1.1.1.2 ! misho    4266:     *
        !          4267:     * @param array $list a list of file or directory names to ignore
        !          4268:     *
1.1       misho    4269:     * @access public
                   4270:     */
                   4271:     function setIgnoreList($list)
                   4272:     {
                   4273:        $regexp = str_replace(array('#', '.', '^', '$'), array('\#', '\.', '\^', '\$'), $list);
                   4274:        $regexp = '#/'.join('$|/', $list).'#';
                   4275:        $this->setIgnoreRegexp($regexp);
                   4276:     }
                   4277:     // }}}
                   4278: 
                   4279:     // {{{ _error()
                   4280:     function _error($p_message)
                   4281:     {
1.1.1.2 ! misho    4282:         $this->error_object = &$this->raiseError($p_message); 
1.1       misho    4283:     }
                   4284:     // }}}
                   4285: 
                   4286:     // {{{ _warning()
                   4287:     function _warning($p_message)
                   4288:     {
1.1.1.2 ! misho    4289:         $this->error_object = &$this->raiseError($p_message); 
1.1       misho    4290:     }
                   4291:     // }}}
                   4292: 
                   4293:     // {{{ _isArchive()
1.1.1.2 ! misho    4294:     function _isArchive($p_filename=null)
1.1       misho    4295:     {
1.1.1.2 ! misho    4296:         if ($p_filename == null) {
1.1       misho    4297:             $p_filename = $this->_tarname;
                   4298:         }
                   4299:         clearstatcache();
                   4300:         return @is_file($p_filename) && !@is_link($p_filename);
                   4301:     }
                   4302:     // }}}
                   4303: 
                   4304:     // {{{ _openWrite()
                   4305:     function _openWrite()
                   4306:     {
1.1.1.2 ! misho    4307:         if ($this->_compress_type == 'gz' && function_exists('gzopen'))
1.1       misho    4308:             $this->_file = @gzopen($this->_tarname, "wb9");
1.1.1.2 ! misho    4309:         else if ($this->_compress_type == 'bz2' && function_exists('bzopen'))
1.1       misho    4310:             $this->_file = @bzopen($this->_tarname, "w");
                   4311:         else if ($this->_compress_type == 'none')
                   4312:             $this->_file = @fopen($this->_tarname, "wb");
1.1.1.2 ! misho    4313:         else {
1.1       misho    4314:             $this->_error('Unknown or missing compression type ('
                   4315:                                      .$this->_compress_type.')');
1.1.1.2 ! misho    4316:             return false;
        !          4317:         }
1.1       misho    4318: 
                   4319:         if ($this->_file == 0) {
                   4320:             $this->_error('Unable to open in write mode \''
                   4321:                                      .$this->_tarname.'\'');
                   4322:             return false;
                   4323:         }
                   4324: 
                   4325:         return true;
                   4326:     }
                   4327:     // }}}
                   4328: 
                   4329:     // {{{ _openRead()
                   4330:     function _openRead()
                   4331:     {
                   4332:         if (strtolower(substr($this->_tarname, 0, 7)) == 'http://') {
                   4333: 
                   4334:           // ----- Look if a local copy need to be done
                   4335:           if ($this->_temp_tarname == '') {
                   4336:               $this->_temp_tarname = uniqid('tar').'.tmp';
                   4337:               if (!$v_file_from = @fopen($this->_tarname, 'rb')) {
                   4338:                 $this->_error('Unable to open in read mode \''
                   4339:                                              .$this->_tarname.'\'');
                   4340:                 $this->_temp_tarname = '';
                   4341:                 return false;
                   4342:               }
                   4343:               if (!$v_file_to = @fopen($this->_temp_tarname, 'wb')) {
                   4344:                 $this->_error('Unable to open in write mode \''
                   4345:                                              .$this->_temp_tarname.'\'');
                   4346:                 $this->_temp_tarname = '';
                   4347:                 return false;
                   4348:               }
                   4349:               while ($v_data = @fread($v_file_from, 1024))
                   4350:                   @fwrite($v_file_to, $v_data);
                   4351:               @fclose($v_file_from);
                   4352:               @fclose($v_file_to);
                   4353:           }
                   4354: 
                   4355:           // ----- File to open if the local copy
                   4356:           $v_filename = $this->_temp_tarname;
                   4357: 
                   4358:         } else
                   4359:           // ----- File to open if the normal Tar file
                   4360:           $v_filename = $this->_tarname;
                   4361: 
1.1.1.2 ! misho    4362:         if ($this->_compress_type == 'gz' && function_exists('gzopen'))
1.1       misho    4363:             $this->_file = @gzopen($v_filename, "rb");
1.1.1.2 ! misho    4364:         else if ($this->_compress_type == 'bz2' && function_exists('bzopen'))
1.1       misho    4365:             $this->_file = @bzopen($v_filename, "r");
                   4366:         else if ($this->_compress_type == 'none')
                   4367:             $this->_file = @fopen($v_filename, "rb");
1.1.1.2 ! misho    4368:         else {
1.1       misho    4369:             $this->_error('Unknown or missing compression type ('
                   4370:                                      .$this->_compress_type.')');
1.1.1.2 ! misho    4371:             return false;
        !          4372:         }
1.1       misho    4373: 
                   4374:         if ($this->_file == 0) {
                   4375:             $this->_error('Unable to open in read mode \''.$v_filename.'\'');
                   4376:             return false;
                   4377:         }
                   4378: 
                   4379:         return true;
                   4380:     }
                   4381:     // }}}
                   4382: 
                   4383:     // {{{ _openReadWrite()
                   4384:     function _openReadWrite()
                   4385:     {
                   4386:         if ($this->_compress_type == 'gz')
                   4387:             $this->_file = @gzopen($this->_tarname, "r+b");
                   4388:         else if ($this->_compress_type == 'bz2') {
                   4389:             $this->_error('Unable to open bz2 in read/write mode \''
                   4390:                                      .$this->_tarname.'\' (limitation of bz2 extension)');
                   4391:             return false;
                   4392:         } else if ($this->_compress_type == 'none')
                   4393:             $this->_file = @fopen($this->_tarname, "r+b");
1.1.1.2 ! misho    4394:         else {
1.1       misho    4395:             $this->_error('Unknown or missing compression type ('
                   4396:                                      .$this->_compress_type.')');
1.1.1.2 ! misho    4397:             return false;
        !          4398:         }
1.1       misho    4399: 
                   4400:         if ($this->_file == 0) {
                   4401:             $this->_error('Unable to open in read/write mode \''
                   4402:                                      .$this->_tarname.'\'');
                   4403:             return false;
                   4404:         }
                   4405: 
                   4406:         return true;
                   4407:     }
                   4408:     // }}}
                   4409: 
                   4410:     // {{{ _close()
                   4411:     function _close()
                   4412:     {
                   4413:         //if (isset($this->_file)) {
                   4414:         if (is_resource($this->_file)) {
                   4415:             if ($this->_compress_type == 'gz')
                   4416:                 @gzclose($this->_file);
                   4417:             else if ($this->_compress_type == 'bz2')
                   4418:                 @bzclose($this->_file);
                   4419:             else if ($this->_compress_type == 'none')
                   4420:                 @fclose($this->_file);
                   4421:             else
                   4422:                 $this->_error('Unknown or missing compression type ('
                   4423:                                              .$this->_compress_type.')');
                   4424: 
                   4425:             $this->_file = 0;
                   4426:         }
                   4427: 
                   4428:         // ----- Look if a local copy need to be erase
                   4429:         // Note that it might be interesting to keep the url for a time : ToDo
                   4430:         if ($this->_temp_tarname != '') {
                   4431:             @unlink($this->_temp_tarname);
                   4432:             $this->_temp_tarname = '';
                   4433:         }
                   4434: 
                   4435:         return true;
                   4436:     }
                   4437:     // }}}
                   4438: 
                   4439:     // {{{ _cleanFile()
                   4440:     function _cleanFile()
                   4441:     {
                   4442:         $this->_close();
                   4443: 
                   4444:         // ----- Look for a local copy
                   4445:         if ($this->_temp_tarname != '') {
                   4446:             // ----- Remove the local copy but not the remote tarname
                   4447:             @unlink($this->_temp_tarname);
                   4448:             $this->_temp_tarname = '';
                   4449:         } else {
                   4450:             // ----- Remove the local tarname file
                   4451:             @unlink($this->_tarname);
                   4452:         }
                   4453:         $this->_tarname = '';
                   4454: 
                   4455:         return true;
                   4456:     }
                   4457:     // }}}
                   4458: 
                   4459:     // {{{ _writeBlock()
                   4460:     function _writeBlock($p_binary_data, $p_len=null)
                   4461:     {
                   4462:       if (is_resource($this->_file)) {
                   4463:           if ($p_len === null) {
                   4464:               if ($this->_compress_type == 'gz')
                   4465:                   @gzputs($this->_file, $p_binary_data);
                   4466:               else if ($this->_compress_type == 'bz2')
                   4467:                   @bzwrite($this->_file, $p_binary_data);
                   4468:               else if ($this->_compress_type == 'none')
                   4469:                   @fputs($this->_file, $p_binary_data);
                   4470:               else
                   4471:                   $this->_error('Unknown or missing compression type ('
                   4472:                                                .$this->_compress_type.')');
                   4473:           } else {
                   4474:               if ($this->_compress_type == 'gz')
                   4475:                   @gzputs($this->_file, $p_binary_data, $p_len);
                   4476:               else if ($this->_compress_type == 'bz2')
                   4477:                   @bzwrite($this->_file, $p_binary_data, $p_len);
                   4478:               else if ($this->_compress_type == 'none')
                   4479:                   @fputs($this->_file, $p_binary_data, $p_len);
                   4480:               else
                   4481:                   $this->_error('Unknown or missing compression type ('
                   4482:                                                .$this->_compress_type.')');
                   4483: 
                   4484:           }
                   4485:       }
                   4486:       return true;
                   4487:     }
                   4488:     // }}}
                   4489: 
                   4490:     // {{{ _readBlock()
                   4491:     function _readBlock()
                   4492:     {
                   4493:       $v_block = null;
                   4494:       if (is_resource($this->_file)) {
                   4495:           if ($this->_compress_type == 'gz')
                   4496:               $v_block = @gzread($this->_file, 512);
                   4497:           else if ($this->_compress_type == 'bz2')
                   4498:               $v_block = @bzread($this->_file, 512);
                   4499:           else if ($this->_compress_type == 'none')
                   4500:               $v_block = @fread($this->_file, 512);
                   4501:           else
                   4502:               $this->_error('Unknown or missing compression type ('
                   4503:                                        .$this->_compress_type.')');
                   4504:       }
                   4505:       return $v_block;
                   4506:     }
                   4507:     // }}}
                   4508: 
                   4509:     // {{{ _jumpBlock()
                   4510:     function _jumpBlock($p_len=null)
                   4511:     {
                   4512:       if (is_resource($this->_file)) {
                   4513:           if ($p_len === null)
                   4514:               $p_len = 1;
                   4515: 
                   4516:           if ($this->_compress_type == 'gz') {
                   4517:               @gzseek($this->_file, gztell($this->_file)+($p_len*512));
                   4518:           }
                   4519:           else if ($this->_compress_type == 'bz2') {
                   4520:               // ----- Replace missing bztell() and bzseek()
                   4521:               for ($i=0; $i<$p_len; $i++)
                   4522:                   $this->_readBlock();
                   4523:           } else if ($this->_compress_type == 'none')
                   4524:               @fseek($this->_file, $p_len*512, SEEK_CUR);
                   4525:           else
                   4526:               $this->_error('Unknown or missing compression type ('
                   4527:                                        .$this->_compress_type.')');
                   4528: 
                   4529:       }
                   4530:       return true;
                   4531:     }
                   4532:     // }}}
                   4533: 
                   4534:     // {{{ _writeFooter()
                   4535:     function _writeFooter()
                   4536:     {
                   4537:       if (is_resource($this->_file)) {
                   4538:           // ----- Write the last 0 filled block for end of archive
                   4539:           $v_binary_data = pack('a1024', '');
                   4540:           $this->_writeBlock($v_binary_data);
                   4541:       }
                   4542:       return true;
                   4543:     }
                   4544:     // }}}
                   4545: 
                   4546:     // {{{ _addList()
                   4547:     function _addList($p_list, $p_add_dir, $p_remove_dir)
                   4548:     {
                   4549:       $v_result=true;
                   4550:       $v_header = array();
                   4551: 
                   4552:       // ----- Remove potential windows directory separator
                   4553:       $p_add_dir = $this->_translateWinPath($p_add_dir);
                   4554:       $p_remove_dir = $this->_translateWinPath($p_remove_dir, false);
                   4555: 
                   4556:       if (!$this->_file) {
                   4557:           $this->_error('Invalid file descriptor');
                   4558:           return false;
                   4559:       }
                   4560: 
                   4561:       if (sizeof($p_list) == 0)
                   4562:           return true;
                   4563: 
                   4564:       foreach ($p_list as $v_filename) {
                   4565:           if (!$v_result) {
                   4566:               break;
                   4567:           }
                   4568: 
                   4569:         // ----- Skip the current tar name
                   4570:         if ($v_filename == $this->_tarname)
                   4571:             continue;
                   4572: 
                   4573:         if ($v_filename == '')
                   4574:             continue;
                   4575: 
                   4576:                // ----- ignore files and directories matching the ignore regular expression
                   4577:                if ($this->_ignore_regexp && preg_match($this->_ignore_regexp, '/'.$v_filename)) {
                   4578:             $this->_warning("File '$v_filename' ignored");
                   4579:                    continue;
                   4580:                }
                   4581: 
1.1.1.2 ! misho    4582:         if (!file_exists($v_filename) && !is_link($v_filename)) {
1.1       misho    4583:             $this->_warning("File '$v_filename' does not exist");
                   4584:             continue;
                   4585:         }
                   4586: 
                   4587:         // ----- Add the file or directory header
                   4588:         if (!$this->_addFile($v_filename, $v_header, $p_add_dir, $p_remove_dir))
                   4589:             return false;
                   4590: 
                   4591:         if (@is_dir($v_filename) && !@is_link($v_filename)) {
                   4592:             if (!($p_hdir = opendir($v_filename))) {
                   4593:                 $this->_warning("Directory '$v_filename' can not be read");
                   4594:                 continue;
                   4595:             }
                   4596:             while (false !== ($p_hitem = readdir($p_hdir))) {
                   4597:                 if (($p_hitem != '.') && ($p_hitem != '..')) {
                   4598:                     if ($v_filename != ".")
                   4599:                         $p_temp_list[0] = $v_filename.'/'.$p_hitem;
                   4600:                     else
                   4601:                         $p_temp_list[0] = $p_hitem;
                   4602: 
                   4603:                     $v_result = $this->_addList($p_temp_list,
                   4604:                                                                    $p_add_dir,
                   4605:                                                                                                $p_remove_dir);
                   4606:                 }
                   4607:             }
                   4608: 
                   4609:             unset($p_temp_list);
                   4610:             unset($p_hdir);
                   4611:             unset($p_hitem);
                   4612:         }
                   4613:       }
                   4614: 
                   4615:       return $v_result;
                   4616:     }
                   4617:     // }}}
                   4618: 
                   4619:     // {{{ _addFile()
                   4620:     function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir)
                   4621:     {
                   4622:       if (!$this->_file) {
                   4623:           $this->_error('Invalid file descriptor');
                   4624:           return false;
                   4625:       }
                   4626: 
                   4627:       if ($p_filename == '') {
                   4628:           $this->_error('Invalid file name');
                   4629:           return false;
                   4630:       }
                   4631: 
                   4632:       // ----- Calculate the stored filename
                   4633:       $p_filename = $this->_translateWinPath($p_filename, false);;
                   4634:       $v_stored_filename = $p_filename;
                   4635:       if (strcmp($p_filename, $p_remove_dir) == 0) {
                   4636:           return true;
                   4637:       }
                   4638:       if ($p_remove_dir != '') {
                   4639:           if (substr($p_remove_dir, -1) != '/')
                   4640:               $p_remove_dir .= '/';
                   4641: 
                   4642:           if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir)
                   4643:               $v_stored_filename = substr($p_filename, strlen($p_remove_dir));
                   4644:       }
                   4645:       $v_stored_filename = $this->_translateWinPath($v_stored_filename);
                   4646:       if ($p_add_dir != '') {
                   4647:           if (substr($p_add_dir, -1) == '/')
                   4648:               $v_stored_filename = $p_add_dir.$v_stored_filename;
                   4649:           else
                   4650:               $v_stored_filename = $p_add_dir.'/'.$v_stored_filename;
                   4651:       }
                   4652: 
                   4653:       $v_stored_filename = $this->_pathReduction($v_stored_filename);
                   4654: 
                   4655:       if ($this->_isArchive($p_filename)) {
                   4656:           if (($v_file = @fopen($p_filename, "rb")) == 0) {
                   4657:               $this->_warning("Unable to open file '".$p_filename
                   4658:                                          ."' in binary read mode");
                   4659:               return true;
                   4660:           }
                   4661: 
                   4662:           if (!$this->_writeHeader($p_filename, $v_stored_filename))
                   4663:               return false;
                   4664: 
                   4665:           while (($v_buffer = fread($v_file, 512)) != '') {
                   4666:               $v_binary_data = pack("a512", "$v_buffer");
                   4667:               $this->_writeBlock($v_binary_data);
                   4668:           }
                   4669: 
                   4670:           fclose($v_file);
                   4671: 
                   4672:       } else {
                   4673:           // ----- Only header for dir
                   4674:           if (!$this->_writeHeader($p_filename, $v_stored_filename))
                   4675:               return false;
                   4676:       }
                   4677: 
                   4678:       return true;
                   4679:     }
                   4680:     // }}}
                   4681: 
                   4682:     // {{{ _addString()
1.1.1.2 ! misho    4683:     function _addString($p_filename, $p_string, $p_datetime = false)
1.1       misho    4684:     {
                   4685:       if (!$this->_file) {
                   4686:           $this->_error('Invalid file descriptor');
                   4687:           return false;
                   4688:       }
                   4689: 
                   4690:       if ($p_filename == '') {
                   4691:           $this->_error('Invalid file name');
                   4692:           return false;
                   4693:       }
                   4694: 
                   4695:       // ----- Calculate the stored filename
                   4696:       $p_filename = $this->_translateWinPath($p_filename, false);;
1.1.1.2 ! misho    4697:       
        !          4698:       // ----- If datetime is not specified, set current time
        !          4699:       if ($p_datetime === false) {
        !          4700:           $p_datetime = time();
        !          4701:       }
1.1       misho    4702: 
                   4703:       if (!$this->_writeHeaderBlock($p_filename, strlen($p_string),
1.1.1.2 ! misho    4704:                                     $p_datetime, 384, "", 0, 0))
1.1       misho    4705:           return false;
                   4706: 
                   4707:       $i=0;
                   4708:       while (($v_buffer = substr($p_string, (($i++)*512), 512)) != '') {
                   4709:           $v_binary_data = pack("a512", $v_buffer);
                   4710:           $this->_writeBlock($v_binary_data);
                   4711:       }
                   4712: 
                   4713:       return true;
                   4714:     }
                   4715:     // }}}
                   4716: 
                   4717:     // {{{ _writeHeader()
                   4718:     function _writeHeader($p_filename, $p_stored_filename)
                   4719:     {
                   4720:         if ($p_stored_filename == '')
                   4721:             $p_stored_filename = $p_filename;
                   4722:         $v_reduce_filename = $this->_pathReduction($p_stored_filename);
                   4723: 
                   4724:         if (strlen($v_reduce_filename) > 99) {
                   4725:           if (!$this->_writeLongHeader($v_reduce_filename))
                   4726:             return false;
                   4727:         }
                   4728: 
                   4729:         $v_info = lstat($p_filename);
                   4730:         $v_uid = sprintf("%07s", DecOct($v_info[4]));
                   4731:         $v_gid = sprintf("%07s", DecOct($v_info[5]));
                   4732:         $v_perms = sprintf("%07s", DecOct($v_info['mode'] & 000777));
                   4733: 
                   4734:         $v_mtime = sprintf("%011s", DecOct($v_info['mtime']));
                   4735: 
                   4736:         $v_linkname = '';
                   4737: 
                   4738:         if (@is_link($p_filename)) {
                   4739:           $v_typeflag = '2';
                   4740:           $v_linkname = readlink($p_filename);
                   4741:           $v_size = sprintf("%011s", DecOct(0));
                   4742:         } elseif (@is_dir($p_filename)) {
                   4743:           $v_typeflag = "5";
                   4744:           $v_size = sprintf("%011s", DecOct(0));
                   4745:         } else {
                   4746:           $v_typeflag = '0';
                   4747:           clearstatcache();
                   4748:           $v_size = sprintf("%011s", DecOct($v_info['size']));
                   4749:         }
                   4750: 
                   4751:         $v_magic = 'ustar ';
                   4752: 
                   4753:         $v_version = ' ';
                   4754:         
                   4755:         if (function_exists('posix_getpwuid'))
                   4756:         {
                   4757:           $userinfo = posix_getpwuid($v_info[4]);
                   4758:           $groupinfo = posix_getgrgid($v_info[5]);
                   4759:           
                   4760:           $v_uname = $userinfo['name'];
                   4761:           $v_gname = $groupinfo['name'];
                   4762:         }
                   4763:         else
                   4764:         {
                   4765:           $v_uname = '';
                   4766:           $v_gname = '';
                   4767:         }
                   4768: 
                   4769:         $v_devmajor = '';
                   4770: 
                   4771:         $v_devminor = '';
                   4772: 
                   4773:         $v_prefix = '';
                   4774: 
                   4775:         $v_binary_data_first = pack("a100a8a8a8a12a12",
                   4776:                                            $v_reduce_filename, $v_perms, $v_uid,
                   4777:                                                                        $v_gid, $v_size, $v_mtime);
                   4778:         $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12",
                   4779:                                           $v_typeflag, $v_linkname, $v_magic,
                   4780:                                                                   $v_version, $v_uname, $v_gname,
                   4781:                                                                   $v_devmajor, $v_devminor, $v_prefix, '');
                   4782: 
                   4783:         // ----- Calculate the checksum
                   4784:         $v_checksum = 0;
                   4785:         // ..... First part of the header
                   4786:         for ($i=0; $i<148; $i++)
                   4787:             $v_checksum += ord(substr($v_binary_data_first,$i,1));
                   4788:         // ..... Ignore the checksum value and replace it by ' ' (space)
                   4789:         for ($i=148; $i<156; $i++)
                   4790:             $v_checksum += ord(' ');
                   4791:         // ..... Last part of the header
                   4792:         for ($i=156, $j=0; $i<512; $i++, $j++)
                   4793:             $v_checksum += ord(substr($v_binary_data_last,$j,1));
                   4794: 
                   4795:         // ----- Write the first 148 bytes of the header in the archive
                   4796:         $this->_writeBlock($v_binary_data_first, 148);
                   4797: 
                   4798:         // ----- Write the calculated checksum
                   4799:         $v_checksum = sprintf("%06s ", DecOct($v_checksum));
                   4800:         $v_binary_data = pack("a8", $v_checksum);
                   4801:         $this->_writeBlock($v_binary_data, 8);
                   4802: 
                   4803:         // ----- Write the last 356 bytes of the header in the archive
                   4804:         $this->_writeBlock($v_binary_data_last, 356);
                   4805: 
                   4806:         return true;
                   4807:     }
                   4808:     // }}}
                   4809: 
                   4810:     // {{{ _writeHeaderBlock()
                   4811:     function _writeHeaderBlock($p_filename, $p_size, $p_mtime=0, $p_perms=0,
                   4812:                                   $p_type='', $p_uid=0, $p_gid=0)
                   4813:     {
                   4814:         $p_filename = $this->_pathReduction($p_filename);
                   4815: 
                   4816:         if (strlen($p_filename) > 99) {
                   4817:           if (!$this->_writeLongHeader($p_filename))
                   4818:             return false;
                   4819:         }
                   4820: 
                   4821:         if ($p_type == "5") {
                   4822:           $v_size = sprintf("%011s", DecOct(0));
                   4823:         } else {
                   4824:           $v_size = sprintf("%011s", DecOct($p_size));
                   4825:         }
                   4826: 
                   4827:         $v_uid = sprintf("%07s", DecOct($p_uid));
                   4828:         $v_gid = sprintf("%07s", DecOct($p_gid));
                   4829:         $v_perms = sprintf("%07s", DecOct($p_perms & 000777));
                   4830: 
                   4831:         $v_mtime = sprintf("%11s", DecOct($p_mtime));
                   4832: 
                   4833:         $v_linkname = '';
                   4834: 
                   4835:         $v_magic = 'ustar ';
                   4836: 
                   4837:         $v_version = ' ';
                   4838: 
                   4839:         if (function_exists('posix_getpwuid'))
                   4840:         {
                   4841:           $userinfo = posix_getpwuid($p_uid);
                   4842:           $groupinfo = posix_getgrgid($p_gid);
                   4843:           
                   4844:           $v_uname = $userinfo['name'];
                   4845:           $v_gname = $groupinfo['name'];
                   4846:         }
                   4847:         else
                   4848:         {
                   4849:           $v_uname = '';
                   4850:           $v_gname = '';
                   4851:         }
                   4852:         
                   4853:         $v_devmajor = '';
                   4854: 
                   4855:         $v_devminor = '';
                   4856: 
                   4857:         $v_prefix = '';
                   4858: 
                   4859:         $v_binary_data_first = pack("a100a8a8a8a12A12",
                   4860:                                            $p_filename, $v_perms, $v_uid, $v_gid,
                   4861:                                                                        $v_size, $v_mtime);
                   4862:         $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12",
                   4863:                                           $p_type, $v_linkname, $v_magic,
                   4864:                                                                   $v_version, $v_uname, $v_gname,
                   4865:                                                                   $v_devmajor, $v_devminor, $v_prefix, '');
                   4866: 
                   4867:         // ----- Calculate the checksum
                   4868:         $v_checksum = 0;
                   4869:         // ..... First part of the header
                   4870:         for ($i=0; $i<148; $i++)
                   4871:             $v_checksum += ord(substr($v_binary_data_first,$i,1));
                   4872:         // ..... Ignore the checksum value and replace it by ' ' (space)
                   4873:         for ($i=148; $i<156; $i++)
                   4874:             $v_checksum += ord(' ');
                   4875:         // ..... Last part of the header
                   4876:         for ($i=156, $j=0; $i<512; $i++, $j++)
                   4877:             $v_checksum += ord(substr($v_binary_data_last,$j,1));
                   4878: 
                   4879:         // ----- Write the first 148 bytes of the header in the archive
                   4880:         $this->_writeBlock($v_binary_data_first, 148);
                   4881: 
                   4882:         // ----- Write the calculated checksum
                   4883:         $v_checksum = sprintf("%06s ", DecOct($v_checksum));
                   4884:         $v_binary_data = pack("a8", $v_checksum);
                   4885:         $this->_writeBlock($v_binary_data, 8);
                   4886: 
                   4887:         // ----- Write the last 356 bytes of the header in the archive
                   4888:         $this->_writeBlock($v_binary_data_last, 356);
                   4889: 
                   4890:         return true;
                   4891:     }
                   4892:     // }}}
                   4893: 
                   4894:     // {{{ _writeLongHeader()
                   4895:     function _writeLongHeader($p_filename)
                   4896:     {
                   4897:         $v_size = sprintf("%11s ", DecOct(strlen($p_filename)));
                   4898: 
                   4899:         $v_typeflag = 'L';
                   4900: 
                   4901:         $v_linkname = '';
                   4902: 
                   4903:         $v_magic = '';
                   4904: 
                   4905:         $v_version = '';
                   4906: 
                   4907:         $v_uname = '';
                   4908: 
                   4909:         $v_gname = '';
                   4910: 
                   4911:         $v_devmajor = '';
                   4912: 
                   4913:         $v_devminor = '';
                   4914: 
                   4915:         $v_prefix = '';
                   4916: 
                   4917:         $v_binary_data_first = pack("a100a8a8a8a12a12",
                   4918:                                            '././@LongLink', 0, 0, 0, $v_size, 0);
                   4919:         $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12",
                   4920:                                           $v_typeflag, $v_linkname, $v_magic,
                   4921:                                                                   $v_version, $v_uname, $v_gname,
                   4922:                                                                   $v_devmajor, $v_devminor, $v_prefix, '');
                   4923: 
                   4924:         // ----- Calculate the checksum
                   4925:         $v_checksum = 0;
                   4926:         // ..... First part of the header
                   4927:         for ($i=0; $i<148; $i++)
                   4928:             $v_checksum += ord(substr($v_binary_data_first,$i,1));
                   4929:         // ..... Ignore the checksum value and replace it by ' ' (space)
                   4930:         for ($i=148; $i<156; $i++)
                   4931:             $v_checksum += ord(' ');
                   4932:         // ..... Last part of the header
                   4933:         for ($i=156, $j=0; $i<512; $i++, $j++)
                   4934:             $v_checksum += ord(substr($v_binary_data_last,$j,1));
                   4935: 
                   4936:         // ----- Write the first 148 bytes of the header in the archive
                   4937:         $this->_writeBlock($v_binary_data_first, 148);
                   4938: 
                   4939:         // ----- Write the calculated checksum
                   4940:         $v_checksum = sprintf("%06s ", DecOct($v_checksum));
                   4941:         $v_binary_data = pack("a8", $v_checksum);
                   4942:         $this->_writeBlock($v_binary_data, 8);
                   4943: 
                   4944:         // ----- Write the last 356 bytes of the header in the archive
                   4945:         $this->_writeBlock($v_binary_data_last, 356);
                   4946: 
                   4947:         // ----- Write the filename as content of the block
                   4948:         $i=0;
                   4949:         while (($v_buffer = substr($p_filename, (($i++)*512), 512)) != '') {
                   4950:             $v_binary_data = pack("a512", "$v_buffer");
                   4951:             $this->_writeBlock($v_binary_data);
                   4952:         }
                   4953: 
                   4954:         return true;
                   4955:     }
                   4956:     // }}}
                   4957: 
                   4958:     // {{{ _readHeader()
                   4959:     function _readHeader($v_binary_data, &$v_header)
                   4960:     {
                   4961:         if (strlen($v_binary_data)==0) {
                   4962:             $v_header['filename'] = '';
                   4963:             return true;
                   4964:         }
                   4965: 
                   4966:         if (strlen($v_binary_data) != 512) {
                   4967:             $v_header['filename'] = '';
                   4968:             $this->_error('Invalid block size : '.strlen($v_binary_data));
                   4969:             return false;
                   4970:         }
                   4971: 
                   4972:         if (!is_array($v_header)) {
                   4973:             $v_header = array();
                   4974:         }
                   4975:         // ----- Calculate the checksum
                   4976:         $v_checksum = 0;
                   4977:         // ..... First part of the header
                   4978:         for ($i=0; $i<148; $i++)
                   4979:             $v_checksum+=ord(substr($v_binary_data,$i,1));
                   4980:         // ..... Ignore the checksum value and replace it by ' ' (space)
                   4981:         for ($i=148; $i<156; $i++)
                   4982:             $v_checksum += ord(' ');
                   4983:         // ..... Last part of the header
                   4984:         for ($i=156; $i<512; $i++)
                   4985:            $v_checksum+=ord(substr($v_binary_data,$i,1));
                   4986: 
1.1.1.2 ! misho    4987:         if (version_compare(PHP_VERSION,"5.5.0-dev")<0) {
        !          4988:             $fmt = "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" .
        !          4989:                    "a8checksum/a1typeflag/a100link/a6magic/a2version/" .
        !          4990:                    "a32uname/a32gname/a8devmajor/a8devminor/a131prefix";
        !          4991:         } else {
        !          4992:             $fmt = "Z100filename/Z8mode/Z8uid/Z8gid/Z12size/Z12mtime/" .
        !          4993:                    "Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" .
        !          4994:                    "Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix";
        !          4995:         }
        !          4996:         $v_data = unpack($fmt, $v_binary_data);
        !          4997: 
        !          4998:         if (strlen($v_data["prefix"]) > 0) {
        !          4999:             $v_data["filename"] = "$v_data[prefix]/$v_data[filename]";
        !          5000:         }
1.1       misho    5001: 
                   5002:         // ----- Extract the checksum
                   5003:         $v_header['checksum'] = OctDec(trim($v_data['checksum']));
                   5004:         if ($v_header['checksum'] != $v_checksum) {
                   5005:             $v_header['filename'] = '';
                   5006: 
                   5007:             // ----- Look for last block (empty block)
                   5008:             if (($v_checksum == 256) && ($v_header['checksum'] == 0))
                   5009:                 return true;
                   5010: 
                   5011:             $this->_error('Invalid checksum for file "'.$v_data['filename']
                   5012:                                      .'" : '.$v_checksum.' calculated, '
                   5013:                                                  .$v_header['checksum'].' expected');
                   5014:             return false;
                   5015:         }
                   5016: 
                   5017:         // ----- Extract the properties
                   5018:         $v_header['filename'] = $v_data['filename'];
                   5019:         if ($this->_maliciousFilename($v_header['filename'])) {
                   5020:             $this->_error('Malicious .tar detected, file "' . $v_header['filename'] .
                   5021:                 '" will not install in desired directory tree');
                   5022:             return false;
                   5023:         }
                   5024:         $v_header['mode'] = OctDec(trim($v_data['mode']));
                   5025:         $v_header['uid'] = OctDec(trim($v_data['uid']));
                   5026:         $v_header['gid'] = OctDec(trim($v_data['gid']));
                   5027:         $v_header['size'] = OctDec(trim($v_data['size']));
                   5028:         $v_header['mtime'] = OctDec(trim($v_data['mtime']));
                   5029:         if (($v_header['typeflag'] = $v_data['typeflag']) == "5") {
                   5030:           $v_header['size'] = 0;
                   5031:         }
                   5032:         $v_header['link'] = trim($v_data['link']);
                   5033:         /* ----- All these fields are removed form the header because
                   5034:                they do not carry interesting info
                   5035:         $v_header[magic] = trim($v_data[magic]);
                   5036:         $v_header[version] = trim($v_data[version]);
                   5037:         $v_header[uname] = trim($v_data[uname]);
                   5038:         $v_header[gname] = trim($v_data[gname]);
                   5039:         $v_header[devmajor] = trim($v_data[devmajor]);
                   5040:         $v_header[devminor] = trim($v_data[devminor]);
                   5041:         */
                   5042: 
                   5043:         return true;
                   5044:     }
                   5045:     // }}}
                   5046: 
                   5047:     // {{{ _maliciousFilename()
                   5048:     /**
                   5049:      * Detect and report a malicious file name
                   5050:      *
                   5051:      * @param string $file
1.1.1.2 ! misho    5052:      *
1.1       misho    5053:      * @return bool
                   5054:      * @access private
                   5055:      */
                   5056:     function _maliciousFilename($file)
                   5057:     {
                   5058:         if (strpos($file, '/../') !== false) {
                   5059:             return true;
                   5060:         }
                   5061:         if (strpos($file, '../') === 0) {
                   5062:             return true;
                   5063:         }
                   5064:         return false;
                   5065:     }
                   5066:     // }}}
                   5067: 
                   5068:     // {{{ _readLongHeader()
                   5069:     function _readLongHeader(&$v_header)
                   5070:     {
                   5071:       $v_filename = '';
                   5072:       $n = floor($v_header['size']/512);
                   5073:       for ($i=0; $i<$n; $i++) {
                   5074:         $v_content = $this->_readBlock();
                   5075:         $v_filename .= $v_content;
                   5076:       }
                   5077:       if (($v_header['size'] % 512) != 0) {
                   5078:         $v_content = $this->_readBlock();
                   5079:         $v_filename .= trim($v_content);
                   5080:       }
                   5081: 
                   5082:       // ----- Read the next header
                   5083:       $v_binary_data = $this->_readBlock();
                   5084: 
                   5085:       if (!$this->_readHeader($v_binary_data, $v_header))
                   5086:         return false;
                   5087: 
                   5088:       $v_filename = trim($v_filename);
                   5089:       $v_header['filename'] = $v_filename;
                   5090:         if ($this->_maliciousFilename($v_filename)) {
                   5091:             $this->_error('Malicious .tar detected, file "' . $v_filename .
                   5092:                 '" will not install in desired directory tree');
                   5093:             return false;
                   5094:       }
                   5095: 
                   5096:       return true;
                   5097:     }
                   5098:     // }}}
                   5099: 
                   5100:     // {{{ _extractInString()
                   5101:     /**
                   5102:     * This method extract from the archive one file identified by $p_filename.
1.1.1.2 ! misho    5103:     * The return value is a string with the file content, or null on error.
        !          5104:     *
        !          5105:     * @param string $p_filename The path of the file to extract in a string.
        !          5106:     *
        !          5107:     * @return a string with the file content or null.
1.1       misho    5108:     * @access private
                   5109:     */
                   5110:     function _extractInString($p_filename)
                   5111:     {
                   5112:         $v_result_str = "";
                   5113: 
                   5114:         While (strlen($v_binary_data = $this->_readBlock()) != 0)
                   5115:         {
                   5116:           if (!$this->_readHeader($v_binary_data, $v_header))
1.1.1.2 ! misho    5117:             return null;
1.1       misho    5118: 
                   5119:           if ($v_header['filename'] == '')
                   5120:             continue;
                   5121: 
                   5122:           // ----- Look for long filename
                   5123:           if ($v_header['typeflag'] == 'L') {
                   5124:             if (!$this->_readLongHeader($v_header))
1.1.1.2 ! misho    5125:               return null;
1.1       misho    5126:           }
                   5127: 
                   5128:           if ($v_header['filename'] == $p_filename) {
                   5129:               if ($v_header['typeflag'] == "5") {
                   5130:                   $this->_error('Unable to extract in string a directory '
                   5131:                                                .'entry {'.$v_header['filename'].'}');
1.1.1.2 ! misho    5132:                   return null;
1.1       misho    5133:               } else {
                   5134:                   $n = floor($v_header['size']/512);
                   5135:                   for ($i=0; $i<$n; $i++) {
                   5136:                       $v_result_str .= $this->_readBlock();
                   5137:                   }
                   5138:                   if (($v_header['size'] % 512) != 0) {
                   5139:                       $v_content = $this->_readBlock();
                   5140:                       $v_result_str .= substr($v_content, 0,
                   5141:                                                                  ($v_header['size'] % 512));
                   5142:                   }
                   5143:                   return $v_result_str;
                   5144:               }
                   5145:           } else {
                   5146:               $this->_jumpBlock(ceil(($v_header['size']/512)));
                   5147:           }
                   5148:         }
                   5149: 
1.1.1.2 ! misho    5150:         return null;
1.1       misho    5151:     }
                   5152:     // }}}
                   5153: 
                   5154:     // {{{ _extractList()
                   5155:     function _extractList($p_path, &$p_list_detail, $p_mode,
1.1.1.2 ! misho    5156:                           $p_file_list, $p_remove_path, $p_preserve=false)
1.1       misho    5157:     {
                   5158:     $v_result=true;
                   5159:     $v_nb = 0;
                   5160:     $v_extract_all = true;
                   5161:     $v_listing = false;
                   5162: 
                   5163:     $p_path = $this->_translateWinPath($p_path, false);
                   5164:     if ($p_path == '' || (substr($p_path, 0, 1) != '/'
                   5165:            && substr($p_path, 0, 3) != "../" && !strpos($p_path, ':'))) {
                   5166:       $p_path = "./".$p_path;
                   5167:     }
                   5168:     $p_remove_path = $this->_translateWinPath($p_remove_path);
                   5169: 
                   5170:     // ----- Look for path to remove format (should end by /)
                   5171:     if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/'))
                   5172:       $p_remove_path .= '/';
                   5173:     $p_remove_path_size = strlen($p_remove_path);
                   5174: 
                   5175:     switch ($p_mode) {
                   5176:       case "complete" :
1.1.1.2 ! misho    5177:         $v_extract_all = true;
        !          5178:         $v_listing = false;
1.1       misho    5179:       break;
                   5180:       case "partial" :
1.1.1.2 ! misho    5181:           $v_extract_all = false;
        !          5182:           $v_listing = false;
1.1       misho    5183:       break;
                   5184:       case "list" :
1.1.1.2 ! misho    5185:           $v_extract_all = false;
        !          5186:           $v_listing = true;
1.1       misho    5187:       break;
                   5188:       default :
                   5189:         $this->_error('Invalid extract mode ('.$p_mode.')');
                   5190:         return false;
                   5191:     }
                   5192: 
                   5193:     clearstatcache();
                   5194: 
                   5195:     while (strlen($v_binary_data = $this->_readBlock()) != 0)
                   5196:     {
                   5197:       $v_extract_file = FALSE;
                   5198:       $v_extraction_stopped = 0;
                   5199: 
                   5200:       if (!$this->_readHeader($v_binary_data, $v_header))
                   5201:         return false;
                   5202: 
                   5203:       if ($v_header['filename'] == '') {
                   5204:         continue;
                   5205:       }
                   5206: 
                   5207:       // ----- Look for long filename
                   5208:       if ($v_header['typeflag'] == 'L') {
                   5209:         if (!$this->_readLongHeader($v_header))
                   5210:           return false;
                   5211:       }
                   5212: 
                   5213:       if ((!$v_extract_all) && (is_array($p_file_list))) {
                   5214:         // ----- By default no unzip if the file is not found
                   5215:         $v_extract_file = false;
                   5216: 
                   5217:         for ($i=0; $i<sizeof($p_file_list); $i++) {
                   5218:           // ----- Look if it is a directory
                   5219:           if (substr($p_file_list[$i], -1) == '/') {
                   5220:             // ----- Look if the directory is in the filename path
                   5221:             if ((strlen($v_header['filename']) > strlen($p_file_list[$i]))
                   5222:                            && (substr($v_header['filename'], 0, strlen($p_file_list[$i]))
                   5223:                                    == $p_file_list[$i])) {
1.1.1.2 ! misho    5224:               $v_extract_file = true;
1.1       misho    5225:               break;
                   5226:             }
                   5227:           }
                   5228: 
                   5229:           // ----- It is a file, so compare the file names
                   5230:           elseif ($p_file_list[$i] == $v_header['filename']) {
1.1.1.2 ! misho    5231:             $v_extract_file = true;
1.1       misho    5232:             break;
                   5233:           }
                   5234:         }
                   5235:       } else {
1.1.1.2 ! misho    5236:         $v_extract_file = true;
1.1       misho    5237:       }
                   5238: 
                   5239:       // ----- Look if this file need to be extracted
                   5240:       if (($v_extract_file) && (!$v_listing))
                   5241:       {
                   5242:         if (($p_remove_path != '')
1.1.1.2 ! misho    5243:             && (substr($v_header['filename'].'/', 0, $p_remove_path_size)
        !          5244:                            == $p_remove_path)) {
1.1       misho    5245:           $v_header['filename'] = substr($v_header['filename'],
                   5246:                                                 $p_remove_path_size);
1.1.1.2 ! misho    5247:           if( $v_header['filename'] == '' ){
        !          5248:             continue;
        !          5249:           }
        !          5250:         }
1.1       misho    5251:         if (($p_path != './') && ($p_path != '/')) {
                   5252:           while (substr($p_path, -1) == '/')
                   5253:             $p_path = substr($p_path, 0, strlen($p_path)-1);
                   5254: 
                   5255:           if (substr($v_header['filename'], 0, 1) == '/')
                   5256:               $v_header['filename'] = $p_path.$v_header['filename'];
                   5257:           else
                   5258:             $v_header['filename'] = $p_path.'/'.$v_header['filename'];
                   5259:         }
                   5260:         if (file_exists($v_header['filename'])) {
                   5261:           if (   (@is_dir($v_header['filename']))
                   5262:                      && ($v_header['typeflag'] == '')) {
                   5263:             $this->_error('File '.$v_header['filename']
                   5264:                                      .' already exists as a directory');
                   5265:             return false;
                   5266:           }
                   5267:           if (   ($this->_isArchive($v_header['filename']))
                   5268:                      && ($v_header['typeflag'] == "5")) {
                   5269:             $this->_error('Directory '.$v_header['filename']
                   5270:                                      .' already exists as a file');
                   5271:             return false;
                   5272:           }
                   5273:           if (!is_writeable($v_header['filename'])) {
                   5274:             $this->_error('File '.$v_header['filename']
                   5275:                                      .' already exists and is write protected');
                   5276:             return false;
                   5277:           }
                   5278:           if (filemtime($v_header['filename']) > $v_header['mtime']) {
                   5279:             // To be completed : An error or silent no replace ?
                   5280:           }
                   5281:         }
                   5282: 
                   5283:         // ----- Check the directory availability and create it if necessary
                   5284:         elseif (($v_result
                   5285:                         = $this->_dirCheck(($v_header['typeflag'] == "5"
                   5286:                                                    ?$v_header['filename']
                   5287:                                                                        :dirname($v_header['filename'])))) != 1) {
                   5288:             $this->_error('Unable to create path for '.$v_header['filename']);
                   5289:             return false;
                   5290:         }
                   5291: 
                   5292:         if ($v_extract_file) {
                   5293:           if ($v_header['typeflag'] == "5") {
                   5294:             if (!@file_exists($v_header['filename'])) {
                   5295:                 if (!@mkdir($v_header['filename'], 0777)) {
                   5296:                     $this->_error('Unable to create directory {'
                   5297:                                                      .$v_header['filename'].'}');
                   5298:                     return false;
                   5299:                 }
                   5300:             }
                   5301:           } elseif ($v_header['typeflag'] == "2") {
                   5302:               if (@file_exists($v_header['filename'])) {
                   5303:                   @unlink($v_header['filename']);
                   5304:               }
                   5305:               if (!@symlink($v_header['link'], $v_header['filename'])) {
                   5306:                   $this->_error('Unable to extract symbolic link {'
                   5307:                                 .$v_header['filename'].'}');
                   5308:                   return false;
                   5309:               }
                   5310:           } else {
                   5311:               if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) {
                   5312:                   $this->_error('Error while opening {'.$v_header['filename']
                   5313:                                                .'} in write binary mode');
                   5314:                   return false;
                   5315:               } else {
                   5316:                   $n = floor($v_header['size']/512);
                   5317:                   for ($i=0; $i<$n; $i++) {
                   5318:                       $v_content = $this->_readBlock();
                   5319:                       fwrite($v_dest_file, $v_content, 512);
                   5320:                   }
                   5321:             if (($v_header['size'] % 512) != 0) {
                   5322:               $v_content = $this->_readBlock();
                   5323:               fwrite($v_dest_file, $v_content, ($v_header['size'] % 512));
                   5324:             }
                   5325: 
                   5326:             @fclose($v_dest_file);
1.1.1.2 ! misho    5327:             
        !          5328:             if ($p_preserve) {
        !          5329:                 @chown($v_header['filename'], $v_header['uid']);
        !          5330:                 @chgrp($v_header['filename'], $v_header['gid']);
        !          5331:             }
1.1       misho    5332: 
                   5333:             // ----- Change the file mode, mtime
                   5334:             @touch($v_header['filename'], $v_header['mtime']);
                   5335:             if ($v_header['mode'] & 0111) {
                   5336:                 // make file executable, obey umask
                   5337:                 $mode = fileperms($v_header['filename']) | (~umask() & 0111);
                   5338:                 @chmod($v_header['filename'], $mode);
                   5339:             }
                   5340:           }
                   5341: 
                   5342:           // ----- Check the file size
                   5343:           clearstatcache();
1.1.1.2 ! misho    5344:           if (!is_file($v_header['filename'])) {
1.1       misho    5345:               $this->_error('Extracted file '.$v_header['filename']
1.1.1.2 ! misho    5346:                             .'does not exist. Archive may be corrupted.');
        !          5347:               return false;
        !          5348:           }
        !          5349:           
        !          5350:           $filesize = filesize($v_header['filename']);
        !          5351:           if ($filesize != $v_header['size']) {
        !          5352:               $this->_error('Extracted file '.$v_header['filename']
        !          5353:                             .' does not have the correct file size \''
        !          5354:                             .$filesize
        !          5355:                             .'\' ('.$v_header['size']
        !          5356:                             .' expected). Archive may be corrupted.');
1.1       misho    5357:               return false;
                   5358:           }
                   5359:           }
                   5360:         } else {
                   5361:           $this->_jumpBlock(ceil(($v_header['size']/512)));
                   5362:         }
                   5363:       } else {
                   5364:           $this->_jumpBlock(ceil(($v_header['size']/512)));
                   5365:       }
                   5366: 
                   5367:       /* TBC : Seems to be unused ...
                   5368:       if ($this->_compress)
                   5369:         $v_end_of_file = @gzeof($this->_file);
                   5370:       else
                   5371:         $v_end_of_file = @feof($this->_file);
                   5372:         */
                   5373: 
                   5374:       if ($v_listing || $v_extract_file || $v_extraction_stopped) {
                   5375:         // ----- Log extracted files
                   5376:         if (($v_file_dir = dirname($v_header['filename']))
                   5377:                    == $v_header['filename'])
                   5378:           $v_file_dir = '';
                   5379:         if ((substr($v_header['filename'], 0, 1) == '/') && ($v_file_dir == ''))
                   5380:           $v_file_dir = '/';
                   5381: 
                   5382:         $p_list_detail[$v_nb++] = $v_header;
                   5383:         if (is_array($p_file_list) && (count($p_list_detail) == count($p_file_list))) {
                   5384:             return true;
                   5385:         }
                   5386:       }
                   5387:     }
                   5388: 
                   5389:         return true;
                   5390:     }
                   5391:     // }}}
                   5392: 
                   5393:     // {{{ _openAppend()
                   5394:     function _openAppend()
                   5395:     {
                   5396:         if (filesize($this->_tarname) == 0)
                   5397:           return $this->_openWrite();
                   5398: 
                   5399:         if ($this->_compress) {
                   5400:             $this->_close();
                   5401: 
                   5402:             if (!@rename($this->_tarname, $this->_tarname.".tmp")) {
                   5403:                 $this->_error('Error while renaming \''.$this->_tarname
                   5404:                                              .'\' to temporary file \''.$this->_tarname
                   5405:                                                          .'.tmp\'');
                   5406:                 return false;
                   5407:             }
                   5408: 
                   5409:             if ($this->_compress_type == 'gz')
                   5410:                 $v_temp_tar = @gzopen($this->_tarname.".tmp", "rb");
                   5411:             elseif ($this->_compress_type == 'bz2')
                   5412:                 $v_temp_tar = @bzopen($this->_tarname.".tmp", "r");
                   5413: 
                   5414:             if ($v_temp_tar == 0) {
                   5415:                 $this->_error('Unable to open file \''.$this->_tarname
                   5416:                                              .'.tmp\' in binary read mode');
                   5417:                 @rename($this->_tarname.".tmp", $this->_tarname);
                   5418:                 return false;
                   5419:             }
                   5420: 
                   5421:             if (!$this->_openWrite()) {
                   5422:                 @rename($this->_tarname.".tmp", $this->_tarname);
                   5423:                 return false;
                   5424:             }
                   5425: 
                   5426:             if ($this->_compress_type == 'gz') {
1.1.1.2 ! misho    5427:                 $end_blocks = 0;
        !          5428:                 
1.1       misho    5429:                 while (!@gzeof($v_temp_tar)) {
                   5430:                     $v_buffer = @gzread($v_temp_tar, 512);
1.1.1.2 ! misho    5431:                     if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
        !          5432:                         $end_blocks++;
1.1       misho    5433:                         // do not copy end blocks, we will re-make them
                   5434:                         // after appending
                   5435:                         continue;
1.1.1.2 ! misho    5436:                     } elseif ($end_blocks > 0) {
        !          5437:                         for ($i = 0; $i < $end_blocks; $i++) {
        !          5438:                             $this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
        !          5439:                         }
        !          5440:                         $end_blocks = 0;
1.1       misho    5441:                     }
                   5442:                     $v_binary_data = pack("a512", $v_buffer);
                   5443:                     $this->_writeBlock($v_binary_data);
                   5444:                 }
                   5445: 
                   5446:                 @gzclose($v_temp_tar);
                   5447:             }
                   5448:             elseif ($this->_compress_type == 'bz2') {
1.1.1.2 ! misho    5449:                 $end_blocks = 0;
        !          5450:                 
1.1       misho    5451:                 while (strlen($v_buffer = @bzread($v_temp_tar, 512)) > 0) {
1.1.1.2 ! misho    5452:                     if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
        !          5453:                         $end_blocks++;
        !          5454:                         // do not copy end blocks, we will re-make them
        !          5455:                         // after appending
1.1       misho    5456:                         continue;
1.1.1.2 ! misho    5457:                     } elseif ($end_blocks > 0) {
        !          5458:                         for ($i = 0; $i < $end_blocks; $i++) {
        !          5459:                             $this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
        !          5460:                         }
        !          5461:                         $end_blocks = 0;
1.1       misho    5462:                     }
                   5463:                     $v_binary_data = pack("a512", $v_buffer);
                   5464:                     $this->_writeBlock($v_binary_data);
                   5465:                 }
                   5466: 
                   5467:                 @bzclose($v_temp_tar);
                   5468:             }
                   5469: 
                   5470:             if (!@unlink($this->_tarname.".tmp")) {
                   5471:                 $this->_error('Error while deleting temporary file \''
                   5472:                                              .$this->_tarname.'.tmp\'');
                   5473:             }
                   5474: 
                   5475:         } else {
                   5476:             // ----- For not compressed tar, just add files before the last
                   5477:                        //       one or two 512 bytes block
                   5478:             if (!$this->_openReadWrite())
                   5479:                return false;
                   5480: 
                   5481:             clearstatcache();
                   5482:             $v_size = filesize($this->_tarname);
                   5483: 
                   5484:             // We might have zero, one or two end blocks.
                   5485:             // The standard is two, but we should try to handle
                   5486:             // other cases.
                   5487:             fseek($this->_file, $v_size - 1024);
                   5488:             if (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) {
                   5489:                 fseek($this->_file, $v_size - 1024);
                   5490:             }
                   5491:             elseif (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) {
                   5492:                 fseek($this->_file, $v_size - 512);
                   5493:             }
                   5494:         }
                   5495: 
                   5496:         return true;
                   5497:     }
                   5498:     // }}}
                   5499: 
                   5500:     // {{{ _append()
                   5501:     function _append($p_filelist, $p_add_dir='', $p_remove_dir='')
                   5502:     {
                   5503:         if (!$this->_openAppend())
                   5504:             return false;
                   5505: 
                   5506:         if ($this->_addList($p_filelist, $p_add_dir, $p_remove_dir))
                   5507:            $this->_writeFooter();
                   5508: 
                   5509:         $this->_close();
                   5510: 
                   5511:         return true;
                   5512:     }
                   5513:     // }}}
                   5514: 
                   5515:     // {{{ _dirCheck()
                   5516: 
                   5517:     /**
                   5518:      * Check if a directory exists and create it (including parent
                   5519:      * dirs) if not.
                   5520:      *
                   5521:      * @param string $p_dir directory to check
                   5522:      *
1.1.1.2 ! misho    5523:      * @return bool true if the directory exists or was created
1.1       misho    5524:      */
                   5525:     function _dirCheck($p_dir)
                   5526:     {
                   5527:         clearstatcache();
                   5528:         if ((@is_dir($p_dir)) || ($p_dir == ''))
                   5529:             return true;
                   5530: 
                   5531:         $p_parent_dir = dirname($p_dir);
                   5532: 
                   5533:         if (($p_parent_dir != $p_dir) &&
                   5534:             ($p_parent_dir != '') &&
                   5535:             (!$this->_dirCheck($p_parent_dir)))
                   5536:              return false;
                   5537: 
                   5538:         if (!@mkdir($p_dir, 0777)) {
                   5539:             $this->_error("Unable to create directory '$p_dir'");
                   5540:             return false;
                   5541:         }
                   5542: 
                   5543:         return true;
                   5544:     }
                   5545: 
                   5546:     // }}}
                   5547: 
                   5548:     // {{{ _pathReduction()
                   5549: 
                   5550:     /**
                   5551:      * Compress path by changing for example "/dir/foo/../bar" to "/dir/bar",
                   5552:      * rand emove double slashes.
                   5553:      *
                   5554:      * @param string $p_dir path to reduce
                   5555:      *
                   5556:      * @return string reduced path
                   5557:      *
                   5558:      * @access private
                   5559:      *
                   5560:      */
                   5561:     function _pathReduction($p_dir)
                   5562:     {
                   5563:         $v_result = '';
                   5564: 
                   5565:         // ----- Look for not empty path
                   5566:         if ($p_dir != '') {
                   5567:             // ----- Explode path by directory names
                   5568:             $v_list = explode('/', $p_dir);
                   5569: 
                   5570:             // ----- Study directories from last to first
                   5571:             for ($i=sizeof($v_list)-1; $i>=0; $i--) {
                   5572:                 // ----- Look for current path
                   5573:                 if ($v_list[$i] == ".") {
                   5574:                     // ----- Ignore this directory
                   5575:                     // Should be the first $i=0, but no check is done
                   5576:                 }
                   5577:                 else if ($v_list[$i] == "..") {
                   5578:                     // ----- Ignore it and ignore the $i-1
                   5579:                     $i--;
                   5580:                 }
                   5581:                 else if (   ($v_list[$i] == '')
                   5582:                                         && ($i!=(sizeof($v_list)-1))
                   5583:                                                 && ($i!=0)) {
                   5584:                     // ----- Ignore only the double '//' in path,
                   5585:                     // but not the first and last /
                   5586:                 } else {
                   5587:                     $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?'/'
                   5588:                                                    .$v_result:'');
                   5589:                 }
                   5590:             }
                   5591:         }
1.1.1.2 ! misho    5592:         
        !          5593:         if (defined('OS_WINDOWS') && OS_WINDOWS) {
        !          5594:             $v_result = strtr($v_result, '\\', '/');
        !          5595:         }
        !          5596:         
1.1       misho    5597:         return $v_result;
                   5598:     }
                   5599: 
                   5600:     // }}}
                   5601: 
                   5602:     // {{{ _translateWinPath()
                   5603:     function _translateWinPath($p_path, $p_remove_disk_letter=true)
                   5604:     {
                   5605:       if (defined('OS_WINDOWS') && OS_WINDOWS) {
                   5606:           // ----- Look for potential disk letter
                   5607:           if (   ($p_remove_disk_letter)
                   5608:                      && (($v_position = strpos($p_path, ':')) != false)) {
                   5609:               $p_path = substr($p_path, $v_position+1);
                   5610:           }
                   5611:           // ----- Change potential windows directory separator
                   5612:           if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) {
                   5613:               $p_path = strtr($p_path, '\\', '/');
                   5614:           }
                   5615:       }
                   5616:       return $p_path;
                   5617:     }
                   5618:     // }}}
                   5619: 
                   5620: }
                   5621: ?>
1.1.1.2 ! misho    5622: Archive_Tar-1.3.11/docs/Archive_Tar.txt0000644000175000017500000004367312105433221016652 0ustar  druiddruidDocumentation for class Archive_Tar
1.1       misho    5623: ===================================
                   5624: Last update : 2001-08-15
                   5625: 
                   5626: 
                   5627: 
                   5628: Overview :
                   5629: ----------
                   5630: 
                   5631:   The Archive_Tar class helps in creating and managing GNU TAR format
                   5632:   files compressed by GNU ZIP or not. 
                   5633:   The class offers basic functions like creating an archive, adding
                   5634:   files in the archive, extracting files from the archive and listing
                   5635:   the archive content. 
                   5636:   It also provide advanced functions that allow the adding and
                   5637:   extraction of files with path manipulation. 
                   5638: 
                   5639: 
                   5640: Sample :
                   5641: --------
                   5642: 
                   5643:   // ----- Creating the object (uncompressed archive)
                   5644:   $tar_object = new Archive_Tar("tarname.tar");
                   5645:   $tar_object->setErrorHandling(PEAR_ERROR_PRINT);
                   5646: 
                   5647:   // ----- Creating the archive
                   5648:   $v_list[0]="file.txt";
                   5649:   $v_list[1]="data/";
                   5650:   $v_list[2]="file.log";
                   5651:   $tar_object->create($v_list);
                   5652: 
                   5653:   // ----- Adding files
                   5654:   $v_list[0]="dev/file.txt";
                   5655:   $v_list[1]="dev/data/";
                   5656:   $v_list[2]="log/file.log";
                   5657:   $tar_object->add($v_list);
                   5658: 
                   5659:   // ----- Adding more files
                   5660:   $tar_object->add("release/newfile.log release/readme.txt");
                   5661: 
                   5662:   // ----- Listing the content
                   5663:   if (($v_list  =  $tar_object->listContent()) != 0)
                   5664:     for ($i=0; $i<sizeof($v_list); $i++)
                   5665:     {
                   5666:       echo "Filename :'".$v_list[$i][filename]."'<br>";
                   5667:       echo " .size :'".$v_list[$i][size]."'<br>";
                   5668:       echo " .mtime :'".$v_list[$i][mtime]."' (".date("l dS of F Y h:i:s A", $v_list[$i][mtime]).")<br>";
                   5669:       echo " .mode :'".$v_list[$i][mode]."'<br>";
                   5670:       echo " .uid :'".$v_list[$i][uid]."'<br>";
                   5671:       echo " .gid :'".$v_list[$i][gid]."'<br>";
                   5672:       echo " .typeflag :'".$v_list[$i][typeflag]."'<br>";
                   5673:     }
                   5674: 
                   5675:   // ----- Extracting the archive in directory "install"
                   5676:   $tar_object->extract("install");
                   5677: 
                   5678: 
                   5679: Public arguments :
                   5680: ------------------
                   5681: 
                   5682: None
                   5683: 
                   5684: 
                   5685: Public Methods :
                   5686: ----------------
                   5687: 
                   5688: Method : Archive_Tar($p_tarname, $compress = null)
                   5689: Description :
                   5690:   Archive_Tar Class constructor. This flavour of the constructor only
                   5691:   declare a new Archive_Tar object, identifying it by the name of the
                   5692:   tar file.
                   5693:   If the compress argument is set the tar will be read or created as a
                   5694:   gzip or bz2 compressed TAR file. 
                   5695: Arguments :
                   5696:   $p_tarname : A valid filename for the tar archive file.
                   5697:   $p_compress : can be null, 'gz' or 'bz2'. For
                   5698:                 compatibility reason it can also be true. This
                   5699:                 parameter indicates if gzip or bz2 compression
                   5700:                 is required. 
                   5701: Return value :
                   5702:   The Archive_Tar object.
                   5703: Sample :
                   5704:   $tar_object = new Archive_Tar("tarname.tar");
                   5705:   $tar_object_compressed = new Archive_Tar("tarname.tgz", true);
                   5706: How it works :
                   5707:   Initialize the object.
                   5708: 
                   5709: Method : create($p_filelist)
                   5710: Description :
                   5711:   This method creates the archive file and add the files / directories
                   5712:   that are listed in $p_filelist. 
                   5713:   If the file already exists and is writable, it is replaced by the
                   5714:   new tar. It is a create and not an add. If the file exists and is
                   5715:   read-only or is a directory it is not replaced. The method return
                   5716:   false and a PEAR error text. 
                   5717:   The $p_filelist parameter can be an array of string, each string
                   5718:   representing a filename or a directory name with their path if
                   5719:   needed. It can also be a single string with names separated by a
                   5720:   single blank. 
                   5721:   See also createModify() method for more details.
                   5722: Arguments :
                   5723:   $p_filelist : An array of filenames and directory names, or a single
                   5724:   string with names separated by a single blank space. 
                   5725: Return value :
                   5726:   true on success, false on error.
                   5727: Sample 1 :
                   5728:   $tar_object = new Archive_Tar("tarname.tar");
                   5729:   $tar_object->setErrorHandling(PEAR_ERROR_PRINT);  // Optional error handling
                   5730:   $v_list[0]="file.txt";
                   5731:   $v_list[1]="data/"; (Optional '/' at the end)
                   5732:   $v_list[2]="file.log";
                   5733:   $tar_object->create($v_list);
                   5734: Sample 2 :
                   5735:   $tar_object = new Archive_Tar("tarname.tar");
                   5736:   $tar_object->setErrorHandling(PEAR_ERROR_PRINT);  // Optional error handling
                   5737:   $tar_object->create("file.txt data/ file.log");
                   5738: How it works :
                   5739:   Just calling the createModify() method with the right parameters.
                   5740: 
                   5741: Method : createModify($p_filelist, $p_add_dir, $p_remove_dir = "")
                   5742: Description :
                   5743:   This method creates the archive file and add the files / directories
                   5744:   that are listed in $p_filelist. 
                   5745:   If the file already exists and is writable, it is replaced by the
                   5746:   new tar. It is a create and not an add. If the file exists and is
                   5747:   read-only or is a directory it is not replaced. The method return
                   5748:   false and a PEAR error text. 
                   5749:   The $p_filelist parameter can be an array of string, each string
                   5750:   representing a filename or a directory name with their path if
                   5751:   needed. It can also be a single string with names separated by a
                   5752:   single blank. 
                   5753:   The path indicated in $p_remove_dir will be removed from the
                   5754:   memorized path of each file / directory listed when this path
                   5755:   exists. By default nothing is removed (empty path "") 
                   5756:   The path indicated in $p_add_dir will be added at the beginning of
                   5757:   the memorized path of each file / directory listed. However it can
                   5758:   be set to empty "". The adding of a path is done after the removing
                   5759:   of path. 
                   5760:   The path add/remove ability enables the user to prepare an archive
                   5761:   for extraction in a different path than the origin files are. 
                   5762:   See also addModify() method for file adding properties.
                   5763: Arguments :
                   5764:   $p_filelist : An array of filenames and directory names, or a single
                   5765:                 string with names separated by a single blank space.
                   5766:   $p_add_dir : A string which contains a path to be added to the
                   5767:                memorized path of each element in the list. 
                   5768:   $p_remove_dir : A string which contains a path to be removed from
                   5769:                   the memorized path of each element in the list, when
                   5770:                  relevant.
                   5771: Return value :
                   5772:   true on success, false on error.
                   5773: Sample 1 :
                   5774:   $tar_object = new Archive_Tar("tarname.tar");
                   5775:   $tar_object->setErrorHandling(PEAR_ERROR_PRINT);  // Optional error handling
                   5776:   $v_list[0]="file.txt";
                   5777:   $v_list[1]="data/"; (Optional '/' at the end)
                   5778:   $v_list[2]="file.log";
                   5779:   $tar_object->createModify($v_list, "install");
                   5780:   // files are stored in the archive as :
                   5781:   //   install/file.txt
                   5782:   //   install/data
                   5783:   //   install/data/file1.txt
                   5784:   //   install/data/... all the files and sub-dirs of data/
                   5785:   //   install/file.log
                   5786: Sample 2 :
                   5787:   $tar_object = new Archive_Tar("tarname.tar");
                   5788:   $tar_object->setErrorHandling(PEAR_ERROR_PRINT);  // Optional error handling
                   5789:   $v_list[0]="dev/file.txt";
                   5790:   $v_list[1]="dev/data/"; (Optional '/' at the end)
                   5791:   $v_list[2]="log/file.log";
                   5792:   $tar_object->createModify($v_list, "install", "dev");
                   5793:   // files are stored in the archive as :
                   5794:   //   install/file.txt
                   5795:   //   install/data
                   5796:   //   install/data/file1.txt
                   5797:   //   install/data/... all the files and sub-dirs of data/
                   5798:   //   install/log/file.log
                   5799: How it works :
                   5800:   Open the file in write mode (erasing the existing one if one),
                   5801:   call the _addList() method for adding the files in an empty archive,
                   5802:   add the tar footer (512 bytes block), close the tar file.
                   5803: 
                   5804: 
                   5805: Method : addModify($p_filelist, $p_add_dir, $p_remove_dir="")
                   5806: Description :
                   5807:   This method add the files / directories listed in $p_filelist at the
                   5808:   end of the existing archive. If the archive does not yet exists it
                   5809:   is created.
                   5810:   The $p_filelist parameter can be an array of string, each string
                   5811:   representing a filename or a directory name with their path if
                   5812:   needed. It can also be a single string with names separated by a
                   5813:   single blank. 
                   5814:   The path indicated in $p_remove_dir will be removed from the
                   5815:   memorized path of each file / directory listed when this path
                   5816:   exists. By default nothing is removed (empty path "") 
                   5817:   The path indicated in $p_add_dir will be added at the beginning of
                   5818:   the memorized path of each file / directory listed. However it can
                   5819:   be set to empty "". The adding of a path is done after the removing
                   5820:   of path. 
                   5821:   The path add/remove ability enables the user to prepare an archive
                   5822:   for extraction in a different path than the origin files are. 
                   5823:   If a file/dir is already in the archive it will only be added at the
                   5824:   end of the archive. There is no update of the existing archived
                   5825:   file/dir. However while extracting the archive, the last file will
                   5826:   replace the first one. This results in a none optimization of the
                   5827:   archive size. 
                   5828:   If a file/dir does not exist the file/dir is ignored. However an
                   5829:   error text is send to PEAR error. 
                   5830:   If a file/dir is not readable the file/dir is ignored. However an
                   5831:   error text is send to PEAR error. 
                   5832:   If the resulting filename/dirname (after the add/remove option or
                   5833:   not) string is greater than 99 char, the file/dir is
                   5834:   ignored. However an error text is send to PEAR error. 
                   5835: Arguments :
                   5836:   $p_filelist : An array of filenames and directory names, or a single
                   5837:                 string with names separated by a single blank space. 
                   5838:   $p_add_dir : A string which contains a path to be added to the
                   5839:                memorized path of each element in the list. 
                   5840:   $p_remove_dir : A string which contains a path to be removed from
                   5841:                   the memorized path of each element in the list, when
                   5842:                  relevant.
                   5843: Return value :
                   5844:   true on success, false on error.
                   5845: Sample 1 :
                   5846:   $tar_object = new Archive_Tar("tarname.tar");
                   5847:   [...]
                   5848:   $v_list[0]="dev/file.txt";
                   5849:   $v_list[1]="dev/data/"; (Optional '/' at the end)
                   5850:   $v_list[2]="log/file.log";
                   5851:   $tar_object->addModify($v_list, "install");
                   5852:   // files are stored in the archive as :
                   5853:   //   install/file.txt
                   5854:   //   install/data
                   5855:   //   install/data/file1.txt
                   5856:   //   install/data/... all the files and sub-dirs of data/
                   5857:   //   install/file.log
                   5858: Sample 2 :
                   5859:   $tar_object = new Archive_Tar("tarname.tar");
                   5860:   [...]
                   5861:   $v_list[0]="dev/file.txt";
                   5862:   $v_list[1]="dev/data/"; (Optional '/' at the end)
                   5863:   $v_list[2]="log/file.log";
                   5864:   $tar_object->addModify($v_list, "install", "dev");
                   5865:   // files are stored in the archive as :
                   5866:   //   install/file.txt
                   5867:   //   install/data
                   5868:   //   install/data/file1.txt
                   5869:   //   install/data/... all the files and sub-dirs of data/
                   5870:   //   install/log/file.log
                   5871: How it works :
                   5872:   If the archive does not exists it create it and add the files.
                   5873:   If the archive does exists and is not compressed, it open it, jump
                   5874:   before the last empty 512 bytes block (tar footer) and add the files
                   5875:   at this point.
                   5876:   If the archive does exists and is compressed, a temporary copy file
                   5877:   is created. This temporary file is then 'gzip' read block by block
                   5878:   until the last empty block. The new files are then added in the
                   5879:   compressed file.
                   5880:   The adding of files is done by going through the file/dir list,
                   5881:   adding files per files, in a recursive way through the
                   5882:   directory. Each time a path need to be added/removed it is done
                   5883:   before writing the file header in the archive.
                   5884: 
                   5885: Method : add($p_filelist)
                   5886: Description :
                   5887:   This method add the files / directories listed in $p_filelist at the
                   5888:   end of the existing archive. If the archive does not yet exists it
                   5889:   is created. 
                   5890:   The $p_filelist parameter can be an array of string, each string
                   5891:   representing a filename or a directory name with their path if
                   5892:   needed. It can also be a single string with names separated by a
                   5893:   single blank. 
                   5894:   See addModify() method for details and limitations.
                   5895: Arguments :
                   5896:   $p_filelist : An array of filenames and directory names, or a single
                   5897:   string with names separated by a single blank space. 
                   5898: Return value :
                   5899:   true on success, false on error.
                   5900: Sample 1 :
                   5901:   $tar_object = new Archive_Tar("tarname.tar");
                   5902:   [...]
                   5903:   $v_list[0]="dev/file.txt";
                   5904:   $v_list[1]="dev/data/"; (Optional '/' at the end)
                   5905:   $v_list[2]="log/file.log";
                   5906:   $tar_object->add($v_list);
                   5907: Sample 2 :
                   5908:   $tar_object = new Archive_Tar("tarname.tgz", true);
                   5909:   [...]
                   5910:   $v_list[0]="dev/file.txt";
                   5911:   $v_list[1]="dev/data/"; (Optional '/' at the end)
                   5912:   $v_list[2]="log/file.log";
                   5913:   $tar_object->add($v_list);
                   5914: How it works :
                   5915:   Simply call the addModify() method with the right parameters.
                   5916: 
                   5917: Method : addString($p_filename, $p_string)
                   5918: Description :
                   5919:   This method add a single string as a file at the
                   5920:   end of the existing archive. If the archive does not yet exists it
                   5921:   is created.
                   5922: Arguments :
                   5923:   $p_filename : A string which contains the full filename path
                   5924:                 that will be associated with the string.
                   5925:   $p_string :   The content of the file added in the archive.
                   5926: Return value :
                   5927:   true on success, false on error.
                   5928: Sample 1 :
                   5929:   $v_archive = & new Archive_Tar($p_filename);
                   5930:   $v_archive->setErrorHandling(PEAR_ERROR_PRINT);
                   5931:   $v_result = $v_archive->addString('data/test.txt', 'This is the text of the string');
                   5932: 
                   5933: 
                   5934: Method : extract($p_path = "")
                   5935: Description :
                   5936:   This method extract all the content of the archive in the directory
                   5937:   indicated by $p_path.If $p_path is optional, if not set the archive
                   5938:   is extracted in the current directory. 
                   5939:   While extracting a file, if the directory path does not exists it is
                   5940:   created. 
                   5941:   See extractModify() for details and limitations.
                   5942: Arguments :
                   5943:   $p_path : Optional path where the files/dir need to by extracted.
                   5944: Return value :
                   5945:   true on success, false on error.
                   5946: Sample :
                   5947:   $tar_object = new Archive_Tar("tarname.tar");
                   5948:   $tar_object->extract();
                   5949: How it works :
                   5950:   Simply call the extractModify() method with appropriate parameters.
                   5951: 
                   5952: Method : extractModify($p_path, $p_remove_path)
                   5953: Description :
                   5954:   This method extract all the content of the archive in the directory
                   5955:   indicated by $p_path. When relevant the memorized path of the
                   5956:   files/dir can be modified by removing the $p_remove_path path at the
                   5957:   beginning of the file/dir path. 
                   5958:   While extracting a file, if the directory path does not exists it is
                   5959:   created. 
                   5960:   While extracting a file, if the file already exists it is replaced
                   5961:   without looking for last modification date. 
                   5962:   While extracting a file, if the file already exists and is write
                   5963:   protected, the extraction is aborted. 
                   5964:   While extracting a file, if a directory with the same name already
                   5965:   exists, the extraction is aborted. 
                   5966:   While extracting a directory, if a file with the same name already
                   5967:   exists, the extraction is aborted. 
                   5968:   While extracting a file/directory if the destination directory exist
                   5969:   and is write protected, or does not exist but can not be created,
                   5970:   the extraction is aborted. 
                   5971:   If after extraction an extracted file does not show the correct
                   5972:   stored file size, the extraction is aborted. 
                   5973:   When the extraction is aborted, a PEAR error text is set and false
                   5974:   is returned. However the result can be a partial extraction that may
                   5975:   need to be manually cleaned. 
                   5976: Arguments :
                   5977:   $p_path : The path of the directory where the files/dir need to by
                   5978:             extracted. 
                   5979:   $p_remove_path : Part of the memorized path that can be removed if
                   5980:                    present at the beginning of the file/dir path. 
                   5981: Return value :
                   5982:   true on success, false on error.
                   5983: Sample :
                   5984:   // Imagine tarname.tar with files :
                   5985:   //   dev/data/file.txt
                   5986:   //   dev/data/log.txt
                   5987:   //   readme.txt
                   5988:   $tar_object = new Archive_Tar("tarname.tar");
                   5989:   $tar_object->extractModify("install", "dev");
                   5990:   // Files will be extracted there :
                   5991:   //   install/data/file.txt
                   5992:   //   install/data/log.txt
                   5993:   //   install/readme.txt
                   5994: How it works :
                   5995:   Open the archive and call a more generic function that can extract
                   5996:   only a part of the archive or all the archive. 
                   5997:   See extractList() method for more details.
                   5998: 
                   5999: Method : extractInString($p_filename)
                   6000: Description :
                   6001:   This method extract from the archive one file identified by $p_filename.
                   6002:   The return value is a string with the file content, or NULL on error. 
                   6003: Arguments :
                   6004:   $p_filename : The path of the file to extract in a string. 
                   6005: Return value :
                   6006:   a string with the file content or NULL.
                   6007: Sample :
                   6008:   // Imagine tarname.tar with files :
                   6009:   //   dev/data/file.txt
                   6010:   //   dev/data/log.txt
                   6011:   //   dev/readme.txt
                   6012:   $v_archive = & new Archive_Tar('tarname.tar');
                   6013:   $v_archive->setErrorHandling(PEAR_ERROR_PRINT);
                   6014:   $v_string = $v_archive->extractInString('dev/readme.txt');
                   6015:   echo $v_string;
                   6016: 
                   6017: Method : listContent()
                   6018: Description :
                   6019:   This method returns an array of arrays that describe each
                   6020:   file/directory present in the archive. 
                   6021:   The array is not sorted, so it show the position of the file in the
                   6022:   archive. 
                   6023:   The file informations are :
                   6024:     $file[filename] : Name and path of the file/dir.
                   6025:     $file[mode] : File permissions (result of fileperms())
                   6026:     $file[uid] : user id
                   6027:     $file[gid] : group id
                   6028:     $file[size] : filesize
                   6029:     $file[mtime] : Last modification time (result of filemtime())
                   6030:     $file[typeflag] : "" for file, "5" for directory
                   6031: Arguments :
                   6032: Return value :
                   6033:   An array of arrays or 0 on error.
                   6034: Sample :
                   6035:   $tar_object = new Archive_Tar("tarname.tar");
                   6036:   if (($v_list  =  $tar_object->listContent()) != 0)
                   6037:     for ($i=0; $i<sizeof($v_list); $i++)
                   6038:     {
                   6039:       echo "Filename :'".$v_list[$i][filename]."'<br>";
                   6040:       echo " .size :'".$v_list[$i][size]."'<br>";
                   6041:       echo " .mtime :'".$v_list[$i][mtime]."' (".
                   6042:            date("l dS of F Y h:i:s A", $v_list[$i][mtime]).")<br>";
                   6043:       echo " .mode :'".$v_list[$i][mode]."'<br>";
                   6044:       echo " .uid :'".$v_list[$i][uid]."'<br>";
                   6045:       echo " .gid :'".$v_list[$i][gid]."'<br>";
                   6046:       echo " .typeflag :'".$v_list[$i][typeflag]."'<br>";
                   6047:     }
                   6048: How it works :
                   6049:   Call the same function as an extract however with a flag to only go
                   6050:   through the archive without extracting the files. 
                   6051: 
                   6052: Method : extractList($p_filelist, $p_path = "", $p_remove_path = "")
                   6053: Description :
                   6054:   This method extract from the archive only the files indicated in the
                   6055:   $p_filelist. These files are extracted in the current directory or
                   6056:   in the directory indicated by the optional $p_path parameter. 
                   6057:   If indicated the $p_remove_path can be used in the same way as it is
                   6058:   used in extractModify() method. 
                   6059: Arguments :
                   6060:   $p_filelist : An array of filenames and directory names, or a single
                   6061:                 string with names separated by a single blank space. 
                   6062:   $p_path : The path of the directory where the files/dir need to by
                   6063:             extracted. 
                   6064:   $p_remove_path : Part of the memorized path that can be removed if
                   6065:                    present at the beginning of the file/dir path. 
                   6066: Return value :
                   6067:   true on success, false on error.
                   6068: Sample :
                   6069:   // Imagine tarname.tar with files :
                   6070:   //   dev/data/file.txt
                   6071:   //   dev/data/log.txt
                   6072:   //   readme.txt
                   6073:   $tar_object = new Archive_Tar("tarname.tar");
                   6074:   $tar_object->extractList("dev/data/file.txt readme.txt", "install",
                   6075:                            "dev");
                   6076:   // Files will be extracted there :
                   6077:   //   install/data/file.txt
                   6078:   //   install/readme.txt
                   6079: How it works :
                   6080:   Go through the archive and extract only the files present in the
                   6081:   list. 
                   6082: 
                   6083: <?php
                   6084: /* vim: set expandtab tabstop=4 shiftwidth=4: */
                   6085: /**
                   6086:  * PHP Version 5
                   6087:  *
                   6088:  * Copyright (c) 1997-2004 The PHP Group
                   6089:  *
                   6090:  * This source file is subject to version 3.0 of the PHP license,
                   6091:  * that is bundled with this package in the file LICENSE, and is
                   6092:  * available through the world-wide-web at the following url:
                   6093:  * http://www.php.net/license/3_0.txt.
                   6094:  * If you did not receive a copy of the PHP license and are unable to
                   6095:  * obtain it through the world-wide-web, please send a note to
                   6096:  * license@php.net so we can mail you a copy immediately.
                   6097:  *
                   6098:  * @category Console
                   6099:  * @package  Console_Getopt
                   6100:  * @author   Andrei Zmievski <andrei@php.net>
                   6101:  * @license  http://www.php.net/license/3_0.txt PHP 3.0
                   6102:  * @version  CVS: $Id: Getopt.php 306067 2010-12-08 00:13:31Z dufuz $
                   6103:  * @link     http://pear.php.net/package/Console_Getopt
                   6104:  */
                   6105: 
                   6106: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   6107: 
                   6108: /**
                   6109:  * Command-line options parsing class.
                   6110:  *
                   6111:  * @category Console
                   6112:  * @package  Console_Getopt
                   6113:  * @author   Andrei Zmievski <andrei@php.net>
                   6114:  * @license  http://www.php.net/license/3_0.txt PHP 3.0
                   6115:  * @link     http://pear.php.net/package/Console_Getopt
                   6116:  */
                   6117: class Console_Getopt
                   6118: {
                   6119: 
                   6120:     /**
                   6121:      * Parses the command-line options.
                   6122:      *
                   6123:      * The first parameter to this function should be the list of command-line
                   6124:      * arguments without the leading reference to the running program.
                   6125:      *
                   6126:      * The second parameter is a string of allowed short options. Each of the
                   6127:      * option letters can be followed by a colon ':' to specify that the option
                   6128:      * requires an argument, or a double colon '::' to specify that the option
                   6129:      * takes an optional argument.
                   6130:      *
                   6131:      * The third argument is an optional array of allowed long options. The
                   6132:      * leading '--' should not be included in the option name. Options that
                   6133:      * require an argument should be followed by '=', and options that take an
                   6134:      * option argument should be followed by '=='.
                   6135:      *
                   6136:      * The return value is an array of two elements: the list of parsed
                   6137:      * options and the list of non-option command-line arguments. Each entry in
                   6138:      * the list of parsed options is a pair of elements - the first one
                   6139:      * specifies the option, and the second one specifies the option argument,
                   6140:      * if there was one.
                   6141:      *
                   6142:      * Long and short options can be mixed.
                   6143:      *
                   6144:      * Most of the semantics of this function are based on GNU getopt_long().
                   6145:      *
                   6146:      * @param array  $args          an array of command-line arguments
                   6147:      * @param string $short_options specifies the list of allowed short options
                   6148:      * @param array  $long_options  specifies the list of allowed long options
                   6149:      * @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option
                   6150:      *
                   6151:      * @return array two-element array containing the list of parsed options and
                   6152:      * the non-option arguments
                   6153:      * @access public
                   6154:      */
                   6155:     function getopt2($args, $short_options, $long_options = null, $skip_unknown = false)
                   6156:     {
                   6157:         return Console_Getopt::doGetopt(2, $args, $short_options, $long_options, $skip_unknown);
                   6158:     }
                   6159: 
                   6160:     /**
                   6161:      * This function expects $args to start with the script name (POSIX-style).
                   6162:      * Preserved for backwards compatibility.
                   6163:      *
                   6164:      * @param array  $args          an array of command-line arguments
                   6165:      * @param string $short_options specifies the list of allowed short options
                   6166:      * @param array  $long_options  specifies the list of allowed long options
                   6167:      *
                   6168:      * @see getopt2()
                   6169:      * @return array two-element array containing the list of parsed options and
                   6170:      * the non-option arguments
                   6171:      */
                   6172:     function getopt($args, $short_options, $long_options = null, $skip_unknown = false)
                   6173:     {
                   6174:         return Console_Getopt::doGetopt(1, $args, $short_options, $long_options, $skip_unknown);
                   6175:     }
                   6176: 
                   6177:     /**
                   6178:      * The actual implementation of the argument parsing code.
                   6179:      *
                   6180:      * @param int    $version       Version to use
                   6181:      * @param array  $args          an array of command-line arguments
                   6182:      * @param string $short_options specifies the list of allowed short options
                   6183:      * @param array  $long_options  specifies the list of allowed long options
                   6184:      * @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option
                   6185:      *
                   6186:      * @return array
                   6187:      */
                   6188:     function doGetopt($version, $args, $short_options, $long_options = null, $skip_unknown = false)
                   6189:     {
                   6190:         // in case you pass directly readPHPArgv() as the first arg
                   6191:         if (PEAR::isError($args)) {
                   6192:             return $args;
                   6193:         }
                   6194: 
                   6195:         if (empty($args)) {
                   6196:             return array(array(), array());
                   6197:         }
                   6198: 
                   6199:         $non_opts = $opts = array();
                   6200: 
                   6201:         settype($args, 'array');
                   6202: 
                   6203:         if ($long_options) {
                   6204:             sort($long_options);
                   6205:         }
                   6206: 
                   6207:         /*
                   6208:          * Preserve backwards compatibility with callers that relied on
                   6209:          * erroneous POSIX fix.
                   6210:          */
                   6211:         if ($version < 2) {
                   6212:             if (isset($args[0]{0}) && $args[0]{0} != '-') {
                   6213:                 array_shift($args);
                   6214:             }
                   6215:         }
                   6216: 
                   6217:         reset($args);
                   6218:         while (list($i, $arg) = each($args)) {
                   6219:             /* The special element '--' means explicit end of
                   6220:                options. Treat the rest of the arguments as non-options
                   6221:                and end the loop. */
                   6222:             if ($arg == '--') {
                   6223:                 $non_opts = array_merge($non_opts, array_slice($args, $i + 1));
                   6224:                 break;
                   6225:             }
                   6226: 
                   6227:             if ($arg{0} != '-' || (strlen($arg) > 1 && $arg{1} == '-' && !$long_options)) {
                   6228:                 $non_opts = array_merge($non_opts, array_slice($args, $i));
                   6229:                 break;
                   6230:             } elseif (strlen($arg) > 1 && $arg{1} == '-') {
                   6231:                 $error = Console_Getopt::_parseLongOption(substr($arg, 2),
                   6232:                                                           $long_options,
                   6233:                                                           $opts,
                   6234:                                                           $args,
                   6235:                                                           $skip_unknown);
                   6236:                 if (PEAR::isError($error)) {
                   6237:                     return $error;
                   6238:                 }
                   6239:             } elseif ($arg == '-') {
                   6240:                 // - is stdin
                   6241:                 $non_opts = array_merge($non_opts, array_slice($args, $i));
                   6242:                 break;
                   6243:             } else {
                   6244:                 $error = Console_Getopt::_parseShortOption(substr($arg, 1),
                   6245:                                                            $short_options,
                   6246:                                                            $opts,
                   6247:                                                            $args,
                   6248:                                                            $skip_unknown);
                   6249:                 if (PEAR::isError($error)) {
                   6250:                     return $error;
                   6251:                 }
                   6252:             }
                   6253:         }
                   6254: 
                   6255:         return array($opts, $non_opts);
                   6256:     }
                   6257: 
                   6258:     /**
                   6259:      * Parse short option
                   6260:      *
                   6261:      * @param string     $arg           Argument
                   6262:      * @param string[]   $short_options Available short options
                   6263:      * @param string[][] &$opts
                   6264:      * @param string[]   &$args
                   6265:      * @param boolean    $skip_unknown suppresses Console_Getopt: unrecognized option
                   6266:      *
                   6267:      * @access private
                   6268:      * @return void
                   6269:      */
                   6270:     function _parseShortOption($arg, $short_options, &$opts, &$args, $skip_unknown)
                   6271:     {
                   6272:         for ($i = 0; $i < strlen($arg); $i++) {
                   6273:             $opt     = $arg{$i};
                   6274:             $opt_arg = null;
                   6275: 
                   6276:             /* Try to find the short option in the specifier string. */
                   6277:             if (($spec = strstr($short_options, $opt)) === false || $arg{$i} == ':') {
                   6278:                 if ($skip_unknown === true) {
                   6279:                     break;
                   6280:                 }
                   6281: 
                   6282:                 $msg = "Console_Getopt: unrecognized option -- $opt";
                   6283:                 return PEAR::raiseError($msg);
                   6284:             }
                   6285: 
                   6286:             if (strlen($spec) > 1 && $spec{1} == ':') {
                   6287:                 if (strlen($spec) > 2 && $spec{2} == ':') {
                   6288:                     if ($i + 1 < strlen($arg)) {
                   6289:                         /* Option takes an optional argument. Use the remainder of
                   6290:                            the arg string if there is anything left. */
                   6291:                         $opts[] = array($opt, substr($arg, $i + 1));
                   6292:                         break;
                   6293:                     }
                   6294:                 } else {
                   6295:                     /* Option requires an argument. Use the remainder of the arg
                   6296:                        string if there is anything left. */
                   6297:                     if ($i + 1 < strlen($arg)) {
                   6298:                         $opts[] = array($opt,  substr($arg, $i + 1));
                   6299:                         break;
                   6300:                     } else if (list(, $opt_arg) = each($args)) {
                   6301:                         /* Else use the next argument. */;
                   6302:                         if (Console_Getopt::_isShortOpt($opt_arg)
                   6303:                             || Console_Getopt::_isLongOpt($opt_arg)) {
                   6304:                             $msg = "option requires an argument --$opt";
                   6305:                             return PEAR::raiseError("Console_Getopt:" . $msg);
                   6306:                         }
                   6307:                     } else {
                   6308:                         $msg = "option requires an argument --$opt";
                   6309:                         return PEAR::raiseError("Console_Getopt:" . $msg);
                   6310:                     }
                   6311:                 }
                   6312:             }
                   6313: 
                   6314:             $opts[] = array($opt, $opt_arg);
                   6315:         }
                   6316:     }
                   6317: 
                   6318:     /**
                   6319:      * Checks if an argument is a short option
                   6320:      *
                   6321:      * @param string $arg Argument to check
                   6322:      *
                   6323:      * @access private
                   6324:      * @return bool
                   6325:      */
                   6326:     function _isShortOpt($arg)
                   6327:     {
                   6328:         return strlen($arg) == 2 && $arg[0] == '-'
                   6329:                && preg_match('/[a-zA-Z]/', $arg[1]);
                   6330:     }
                   6331: 
                   6332:     /**
                   6333:      * Checks if an argument is a long option
                   6334:      *
                   6335:      * @param string $arg Argument to check
                   6336:      *
                   6337:      * @access private
                   6338:      * @return bool
                   6339:      */
                   6340:     function _isLongOpt($arg)
                   6341:     {
                   6342:         return strlen($arg) > 2 && $arg[0] == '-' && $arg[1] == '-' &&
                   6343:                preg_match('/[a-zA-Z]+$/', substr($arg, 2));
                   6344:     }
                   6345: 
                   6346:     /**
                   6347:      * Parse long option
                   6348:      *
                   6349:      * @param string     $arg          Argument
                   6350:      * @param string[]   $long_options Available long options
                   6351:      * @param string[][] &$opts
                   6352:      * @param string[]   &$args
                   6353:      *
                   6354:      * @access private
                   6355:      * @return void|PEAR_Error
                   6356:      */
                   6357:     function _parseLongOption($arg, $long_options, &$opts, &$args, $skip_unknown)
                   6358:     {
                   6359:         @list($opt, $opt_arg) = explode('=', $arg, 2);
                   6360: 
                   6361:         $opt_len = strlen($opt);
                   6362: 
                   6363:         for ($i = 0; $i < count($long_options); $i++) {
                   6364:             $long_opt  = $long_options[$i];
                   6365:             $opt_start = substr($long_opt, 0, $opt_len);
                   6366: 
                   6367:             $long_opt_name = str_replace('=', '', $long_opt);
                   6368: 
                   6369:             /* Option doesn't match. Go on to the next one. */
                   6370:             if ($long_opt_name != $opt) {
                   6371:                 continue;
                   6372:             }
                   6373: 
                   6374:             $opt_rest = substr($long_opt, $opt_len);
                   6375: 
                   6376:             /* Check that the options uniquely matches one of the allowed
                   6377:                options. */
                   6378:             if ($i + 1 < count($long_options)) {
                   6379:                 $next_option_rest = substr($long_options[$i + 1], $opt_len);
                   6380:             } else {
                   6381:                 $next_option_rest = '';
                   6382:             }
                   6383: 
                   6384:             if ($opt_rest != '' && $opt{0} != '=' &&
                   6385:                 $i + 1 < count($long_options) &&
                   6386:                 $opt == substr($long_options[$i+1], 0, $opt_len) &&
                   6387:                 $next_option_rest != '' &&
                   6388:                 $next_option_rest{0} != '=') {
                   6389: 
                   6390:                 $msg = "Console_Getopt: option --$opt is ambiguous";
                   6391:                 return PEAR::raiseError($msg);
                   6392:             }
                   6393: 
                   6394:             if (substr($long_opt, -1) == '=') {
                   6395:                 if (substr($long_opt, -2) != '==') {
                   6396:                     /* Long option requires an argument.
                   6397:                        Take the next argument if one wasn't specified. */;
                   6398:                     if (!strlen($opt_arg) && !(list(, $opt_arg) = each($args))) {
                   6399:                         $msg = "Console_Getopt: option requires an argument --$opt";
                   6400:                         return PEAR::raiseError($msg);
                   6401:                     }
                   6402: 
                   6403:                     if (Console_Getopt::_isShortOpt($opt_arg)
                   6404:                         || Console_Getopt::_isLongOpt($opt_arg)) {
                   6405:                         $msg = "Console_Getopt: option requires an argument --$opt";
                   6406:                         return PEAR::raiseError($msg);
                   6407:                     }
                   6408:                 }
                   6409:             } else if ($opt_arg) {
                   6410:                 $msg = "Console_Getopt: option --$opt doesn't allow an argument";
                   6411:                 return PEAR::raiseError($msg);
                   6412:             }
                   6413: 
                   6414:             $opts[] = array('--' . $opt, $opt_arg);
                   6415:             return;
                   6416:         }
                   6417: 
                   6418:         if ($skip_unknown === true) {
                   6419:             return;
                   6420:         }
                   6421: 
                   6422:         return PEAR::raiseError("Console_Getopt: unrecognized option --$opt");
                   6423:     }
                   6424: 
                   6425:     /**
                   6426:      * Safely read the $argv PHP array across different PHP configurations.
                   6427:      * Will take care on register_globals and register_argc_argv ini directives
                   6428:      *
                   6429:      * @access public
                   6430:      * @return mixed the $argv PHP array or PEAR error if not registered
                   6431:      */
                   6432:     function readPHPArgv()
                   6433:     {
                   6434:         global $argv;
                   6435:         if (!is_array($argv)) {
                   6436:             if (!@is_array($_SERVER['argv'])) {
                   6437:                 if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) {
                   6438:                     $msg = "Could not read cmd args (register_argc_argv=Off?)";
                   6439:                     return PEAR::raiseError("Console_Getopt: " . $msg);
                   6440:                 }
                   6441:                 return $GLOBALS['HTTP_SERVER_VARS']['argv'];
                   6442:             }
                   6443:             return $_SERVER['argv'];
                   6444:         }
                   6445:         return $argv;
                   6446:     }
                   6447: 
1.1.1.2 ! misho    6448: }package.xml0000644000076500000240000001212011535261415012145 0ustar  helgistaff<?xml version="1.0" encoding="UTF-8"?>
1.1       misho    6449: <package packagerversion="1.9.2" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
                   6450:  <name>Console_Getopt</name>
                   6451:  <channel>pear.php.net</channel>
                   6452:  <summary>Command-line option parser</summary>
                   6453:  <description>This is a PHP implementation of &quot;getopt&quot; supporting both
                   6454: short and long options.</description>
                   6455:  <lead>
                   6456:   <name>Andrei Zmievski</name>
                   6457:   <user>andrei</user>
                   6458:   <email>andrei@php.net</email>
                   6459:   <active>yes</active>
                   6460:  </lead>
                   6461:  <developer>
                   6462:   <name>Stig Bakken</name>
                   6463:   <user>ssb</user>
                   6464:   <email>stig@php.net</email>
                   6465:   <active>no</active>
                   6466:  </developer>
                   6467:  <helper>
                   6468:   <name>Greg Beaver</name>
                   6469:   <user>cellog</user>
                   6470:   <email>cellog@php.net</email>
                   6471:   <active>yes</active>
                   6472:  </helper>
1.1.1.2 ! misho    6473:  <date>2011-03-07</date>
        !          6474:  <time>22:58:21</time>
1.1       misho    6475:  <version>
1.1.1.2 ! misho    6476:   <release>1.3.1</release>
1.1       misho    6477:   <api>1.3.0</api>
                   6478:  </version>
                   6479:  <stability>
                   6480:   <release>stable</release>
                   6481:   <api>stable</api>
                   6482:  </stability>
                   6483:  <license uri="http://www.php.net/license">PHP License</license>
                   6484:  <notes>
1.1.1.2 ! misho    6485: * Change the minimum PEAR installer dep to be lower
1.1       misho    6486:  </notes>
                   6487:  <contents>
                   6488:   <dir name="/">
                   6489:    <file md5sum="ed666da6b1c5d01c3ecbf1f588a70a60" name="Console/Getopt.php" role="php" />
                   6490:   </dir>
                   6491:  </contents>
                   6492:  <compatible>
                   6493:   <name>PEAR</name>
                   6494:   <channel>pear.php.net</channel>
                   6495:   <min>1.4.0</min>
                   6496:   <max>1.10.0</max>
                   6497:  </compatible>
                   6498:  <dependencies>
                   6499:   <required>
                   6500:    <php>
                   6501:     <min>4.3.0</min>
                   6502:    </php>
                   6503:    <pearinstaller>
1.1.1.2 ! misho    6504:     <min>1.8.0</min>
1.1       misho    6505:    </pearinstaller>
                   6506:   </required>
                   6507:  </dependencies>
                   6508:  <phprelease />
                   6509:  <changelog>
                   6510:   <release>
1.1.1.2 ! misho    6511:    <date>2010-12-11</date>
        !          6512:    <time>20:20:13</time>
        !          6513:    <version>
        !          6514:     <release>1.3.0</release>
        !          6515:     <api>1.3.0</api>
        !          6516:    </version>
        !          6517:    <stability>
        !          6518:     <release>stable</release>
        !          6519:     <api>stable</api>
        !          6520:    </stability>
        !          6521:    <license uri="http://www.php.net/license">PHP License</license>
        !          6522:    <notes>
        !          6523: * Implement Request #13140: [PATCH] to skip unknown parameters. [patch by rquadling, improved on by dufuz]
        !          6524:    </notes>
        !          6525:   </release>
        !          6526:   <release>
1.1       misho    6527:    <date>2007-06-12</date>
                   6528:    <version>
                   6529:     <release>1.2.3</release>
                   6530:     <api>1.2.1</api>
                   6531:    </version>
                   6532:    <stability>
                   6533:     <release>stable</release>
                   6534:     <api>stable</api>
                   6535:    </stability>
                   6536:    <license uri="http://www.php.net/license">PHP License</license>
                   6537:    <notes>
                   6538: * fix Bug #11068: No way to read plain &quot;-&quot; option [cardoe]
                   6539:    </notes>
                   6540:   </release>
                   6541:   <release>
                   6542:    <version>
                   6543:     <release>1.2.2</release>
                   6544:     <api>1.2.1</api>
                   6545:    </version>
                   6546:    <stability>
                   6547:     <release>stable</release>
                   6548:     <api>stable</api>
                   6549:    </stability>
                   6550:    <date>2007-02-17</date>
                   6551:    <license uri="http://www.php.net/license">PHP License</license>
                   6552:    <notes>
                   6553: * fix Bug #4475: An ambiguous error occurred when specifying similar longoption name.
                   6554: * fix Bug #10055: Not failing properly on short options missing required values
                   6555:    </notes>
                   6556:   </release>
                   6557:   <release>
                   6558:    <version>
                   6559:     <release>1.2.1</release>
                   6560:     <api>1.2.1</api>
                   6561:    </version>
                   6562:    <stability>
                   6563:     <release>stable</release>
                   6564:     <api>stable</api>
                   6565:    </stability>
                   6566:    <date>2006-12-08</date>
                   6567:    <license uri="http://www.php.net/license">PHP License</license>
                   6568:    <notes>
                   6569: Fixed bugs #4448 (Long parameter values truncated with longoption parameter) and #7444 (Trailing spaces after php closing tag)
                   6570:    </notes>
                   6571:   </release>
                   6572:   <release>
                   6573:    <version>
                   6574:     <release>1.2</release>
                   6575:     <api>1.2</api>
                   6576:    </version>
                   6577:    <stability>
                   6578:     <release>stable</release>
                   6579:     <api>stable</api>
                   6580:    </stability>
                   6581:    <date>2003-12-11</date>
                   6582:    <license uri="http://www.php.net/license">PHP License</license>
                   6583:    <notes>
                   6584: Fix to preserve BC with 1.0 and allow correct behaviour for new users
                   6585:    </notes>
                   6586:   </release>
                   6587:   <release>
                   6588:    <version>
                   6589:     <release>1.0</release>
                   6590:     <api>1.0</api>
                   6591:    </version>
                   6592:    <stability>
                   6593:     <release>stable</release>
                   6594:     <api>stable</api>
                   6595:    </stability>
                   6596:    <date>2002-09-13</date>
                   6597:    <license uri="http://www.php.net/license">PHP License</license>
                   6598:    <notes>
                   6599: Stable release
                   6600:    </notes>
                   6601:   </release>
                   6602:   <release>
                   6603:    <version>
                   6604:     <release>0.11</release>
                   6605:     <api>0.11</api>
                   6606:    </version>
                   6607:    <stability>
                   6608:     <release>beta</release>
                   6609:     <api>beta</api>
                   6610:    </stability>
                   6611:    <date>2002-05-26</date>
                   6612:    <license uri="http://www.php.net/license">PHP License</license>
                   6613:    <notes>
                   6614: POSIX getopt compatibility fix: treat first element of args
                   6615:         array as command name
                   6616:    </notes>
                   6617:   </release>
                   6618:   <release>
                   6619:    <version>
                   6620:     <release>0.10</release>
                   6621:     <api>0.10</api>
                   6622:    </version>
                   6623:    <stability>
                   6624:     <release>beta</release>
                   6625:     <api>beta</api>
                   6626:    </stability>
                   6627:    <date>2002-05-12</date>
                   6628:    <license uri="http://www.php.net/license">PHP License</license>
                   6629:    <notes>
                   6630: Packaging fix
                   6631:    </notes>
                   6632:   </release>
                   6633:   <release>
                   6634:    <version>
                   6635:     <release>0.9</release>
                   6636:     <api>0.9</api>
                   6637:    </version>
                   6638:    <stability>
                   6639:     <release>beta</release>
                   6640:     <api>beta</api>
                   6641:    </stability>
                   6642:    <date>2002-05-12</date>
                   6643:    <license uri="http://www.php.net/license">PHP License</license>
                   6644:    <notes>
                   6645: Initial release
                   6646:    </notes>
                   6647:   </release>
                   6648:  </changelog>
                   6649: </package>
1.1.1.2 ! misho    6650: Console_Getopt-1.3.1/Console/Getopt.php0000644000076500000240000003223511535261415017000 0ustar  helgistaff<?php
1.1       misho    6651: /* vim: set expandtab tabstop=4 shiftwidth=4: */
                   6652: /**
                   6653:  * PHP Version 5
                   6654:  *
                   6655:  * Copyright (c) 1997-2004 The PHP Group
                   6656:  *
                   6657:  * This source file is subject to version 3.0 of the PHP license,
                   6658:  * that is bundled with this package in the file LICENSE, and is
                   6659:  * available through the world-wide-web at the following url:
                   6660:  * http://www.php.net/license/3_0.txt.
                   6661:  * If you did not receive a copy of the PHP license and are unable to
                   6662:  * obtain it through the world-wide-web, please send a note to
                   6663:  * license@php.net so we can mail you a copy immediately.
                   6664:  *
                   6665:  * @category Console
                   6666:  * @package  Console_Getopt
                   6667:  * @author   Andrei Zmievski <andrei@php.net>
                   6668:  * @license  http://www.php.net/license/3_0.txt PHP 3.0
                   6669:  * @version  CVS: $Id: Getopt.php 306067 2010-12-08 00:13:31Z dufuz $
                   6670:  * @link     http://pear.php.net/package/Console_Getopt
                   6671:  */
                   6672: 
                   6673: require_once 'PEAR.php';
                   6674: 
                   6675: /**
                   6676:  * Command-line options parsing class.
                   6677:  *
                   6678:  * @category Console
                   6679:  * @package  Console_Getopt
                   6680:  * @author   Andrei Zmievski <andrei@php.net>
                   6681:  * @license  http://www.php.net/license/3_0.txt PHP 3.0
                   6682:  * @link     http://pear.php.net/package/Console_Getopt
                   6683:  */
                   6684: class Console_Getopt
                   6685: {
                   6686: 
                   6687:     /**
                   6688:      * Parses the command-line options.
                   6689:      *
                   6690:      * The first parameter to this function should be the list of command-line
                   6691:      * arguments without the leading reference to the running program.
                   6692:      *
                   6693:      * The second parameter is a string of allowed short options. Each of the
                   6694:      * option letters can be followed by a colon ':' to specify that the option
                   6695:      * requires an argument, or a double colon '::' to specify that the option
                   6696:      * takes an optional argument.
                   6697:      *
                   6698:      * The third argument is an optional array of allowed long options. The
                   6699:      * leading '--' should not be included in the option name. Options that
                   6700:      * require an argument should be followed by '=', and options that take an
                   6701:      * option argument should be followed by '=='.
                   6702:      *
                   6703:      * The return value is an array of two elements: the list of parsed
                   6704:      * options and the list of non-option command-line arguments. Each entry in
                   6705:      * the list of parsed options is a pair of elements - the first one
                   6706:      * specifies the option, and the second one specifies the option argument,
                   6707:      * if there was one.
                   6708:      *
                   6709:      * Long and short options can be mixed.
                   6710:      *
                   6711:      * Most of the semantics of this function are based on GNU getopt_long().
                   6712:      *
                   6713:      * @param array  $args          an array of command-line arguments
                   6714:      * @param string $short_options specifies the list of allowed short options
                   6715:      * @param array  $long_options  specifies the list of allowed long options
                   6716:      * @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option
                   6717:      *
                   6718:      * @return array two-element array containing the list of parsed options and
                   6719:      * the non-option arguments
                   6720:      * @access public
                   6721:      */
                   6722:     function getopt2($args, $short_options, $long_options = null, $skip_unknown = false)
                   6723:     {
                   6724:         return Console_Getopt::doGetopt(2, $args, $short_options, $long_options, $skip_unknown);
                   6725:     }
                   6726: 
                   6727:     /**
                   6728:      * This function expects $args to start with the script name (POSIX-style).
                   6729:      * Preserved for backwards compatibility.
                   6730:      *
                   6731:      * @param array  $args          an array of command-line arguments
                   6732:      * @param string $short_options specifies the list of allowed short options
                   6733:      * @param array  $long_options  specifies the list of allowed long options
                   6734:      *
                   6735:      * @see getopt2()
                   6736:      * @return array two-element array containing the list of parsed options and
                   6737:      * the non-option arguments
                   6738:      */
                   6739:     function getopt($args, $short_options, $long_options = null, $skip_unknown = false)
                   6740:     {
                   6741:         return Console_Getopt::doGetopt(1, $args, $short_options, $long_options, $skip_unknown);
                   6742:     }
                   6743: 
                   6744:     /**
                   6745:      * The actual implementation of the argument parsing code.
                   6746:      *
                   6747:      * @param int    $version       Version to use
                   6748:      * @param array  $args          an array of command-line arguments
                   6749:      * @param string $short_options specifies the list of allowed short options
                   6750:      * @param array  $long_options  specifies the list of allowed long options
                   6751:      * @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option
                   6752:      *
                   6753:      * @return array
                   6754:      */
                   6755:     function doGetopt($version, $args, $short_options, $long_options = null, $skip_unknown = false)
                   6756:     {
                   6757:         // in case you pass directly readPHPArgv() as the first arg
                   6758:         if (PEAR::isError($args)) {
                   6759:             return $args;
                   6760:         }
                   6761: 
                   6762:         if (empty($args)) {
                   6763:             return array(array(), array());
                   6764:         }
                   6765: 
                   6766:         $non_opts = $opts = array();
                   6767: 
                   6768:         settype($args, 'array');
                   6769: 
                   6770:         if ($long_options) {
                   6771:             sort($long_options);
                   6772:         }
                   6773: 
                   6774:         /*
                   6775:          * Preserve backwards compatibility with callers that relied on
                   6776:          * erroneous POSIX fix.
                   6777:          */
                   6778:         if ($version < 2) {
                   6779:             if (isset($args[0]{0}) && $args[0]{0} != '-') {
                   6780:                 array_shift($args);
                   6781:             }
                   6782:         }
                   6783: 
                   6784:         reset($args);
                   6785:         while (list($i, $arg) = each($args)) {
                   6786:             /* The special element '--' means explicit end of
                   6787:                options. Treat the rest of the arguments as non-options
                   6788:                and end the loop. */
                   6789:             if ($arg == '--') {
                   6790:                 $non_opts = array_merge($non_opts, array_slice($args, $i + 1));
                   6791:                 break;
                   6792:             }
                   6793: 
                   6794:             if ($arg{0} != '-' || (strlen($arg) > 1 && $arg{1} == '-' && !$long_options)) {
                   6795:                 $non_opts = array_merge($non_opts, array_slice($args, $i));
                   6796:                 break;
                   6797:             } elseif (strlen($arg) > 1 && $arg{1} == '-') {
                   6798:                 $error = Console_Getopt::_parseLongOption(substr($arg, 2),
                   6799:                                                           $long_options,
                   6800:                                                           $opts,
                   6801:                                                           $args,
                   6802:                                                           $skip_unknown);
                   6803:                 if (PEAR::isError($error)) {
                   6804:                     return $error;
                   6805:                 }
                   6806:             } elseif ($arg == '-') {
                   6807:                 // - is stdin
                   6808:                 $non_opts = array_merge($non_opts, array_slice($args, $i));
                   6809:                 break;
                   6810:             } else {
                   6811:                 $error = Console_Getopt::_parseShortOption(substr($arg, 1),
                   6812:                                                            $short_options,
                   6813:                                                            $opts,
                   6814:                                                            $args,
                   6815:                                                            $skip_unknown);
                   6816:                 if (PEAR::isError($error)) {
                   6817:                     return $error;
                   6818:                 }
                   6819:             }
                   6820:         }
                   6821: 
                   6822:         return array($opts, $non_opts);
                   6823:     }
                   6824: 
                   6825:     /**
                   6826:      * Parse short option
                   6827:      *
                   6828:      * @param string     $arg           Argument
                   6829:      * @param string[]   $short_options Available short options
                   6830:      * @param string[][] &$opts
                   6831:      * @param string[]   &$args
                   6832:      * @param boolean    $skip_unknown suppresses Console_Getopt: unrecognized option
                   6833:      *
                   6834:      * @access private
                   6835:      * @return void
                   6836:      */
                   6837:     function _parseShortOption($arg, $short_options, &$opts, &$args, $skip_unknown)
                   6838:     {
                   6839:         for ($i = 0; $i < strlen($arg); $i++) {
                   6840:             $opt     = $arg{$i};
                   6841:             $opt_arg = null;
                   6842: 
                   6843:             /* Try to find the short option in the specifier string. */
                   6844:             if (($spec = strstr($short_options, $opt)) === false || $arg{$i} == ':') {
                   6845:                 if ($skip_unknown === true) {
                   6846:                     break;
                   6847:                 }
                   6848: 
                   6849:                 $msg = "Console_Getopt: unrecognized option -- $opt";
                   6850:                 return PEAR::raiseError($msg);
                   6851:             }
                   6852: 
                   6853:             if (strlen($spec) > 1 && $spec{1} == ':') {
                   6854:                 if (strlen($spec) > 2 && $spec{2} == ':') {
                   6855:                     if ($i + 1 < strlen($arg)) {
                   6856:                         /* Option takes an optional argument. Use the remainder of
                   6857:                            the arg string if there is anything left. */
                   6858:                         $opts[] = array($opt, substr($arg, $i + 1));
                   6859:                         break;
                   6860:                     }
                   6861:                 } else {
                   6862:                     /* Option requires an argument. Use the remainder of the arg
                   6863:                        string if there is anything left. */
                   6864:                     if ($i + 1 < strlen($arg)) {
                   6865:                         $opts[] = array($opt,  substr($arg, $i + 1));
                   6866:                         break;
                   6867:                     } else if (list(, $opt_arg) = each($args)) {
                   6868:                         /* Else use the next argument. */;
                   6869:                         if (Console_Getopt::_isShortOpt($opt_arg)
                   6870:                             || Console_Getopt::_isLongOpt($opt_arg)) {
                   6871:                             $msg = "option requires an argument --$opt";
                   6872:                             return PEAR::raiseError("Console_Getopt:" . $msg);
                   6873:                         }
                   6874:                     } else {
                   6875:                         $msg = "option requires an argument --$opt";
                   6876:                         return PEAR::raiseError("Console_Getopt:" . $msg);
                   6877:                     }
                   6878:                 }
                   6879:             }
                   6880: 
                   6881:             $opts[] = array($opt, $opt_arg);
                   6882:         }
                   6883:     }
                   6884: 
                   6885:     /**
                   6886:      * Checks if an argument is a short option
                   6887:      *
                   6888:      * @param string $arg Argument to check
                   6889:      *
                   6890:      * @access private
                   6891:      * @return bool
                   6892:      */
                   6893:     function _isShortOpt($arg)
                   6894:     {
                   6895:         return strlen($arg) == 2 && $arg[0] == '-'
                   6896:                && preg_match('/[a-zA-Z]/', $arg[1]);
                   6897:     }
                   6898: 
                   6899:     /**
                   6900:      * Checks if an argument is a long option
                   6901:      *
                   6902:      * @param string $arg Argument to check
                   6903:      *
                   6904:      * @access private
                   6905:      * @return bool
                   6906:      */
                   6907:     function _isLongOpt($arg)
                   6908:     {
                   6909:         return strlen($arg) > 2 && $arg[0] == '-' && $arg[1] == '-' &&
                   6910:                preg_match('/[a-zA-Z]+$/', substr($arg, 2));
                   6911:     }
                   6912: 
                   6913:     /**
                   6914:      * Parse long option
                   6915:      *
                   6916:      * @param string     $arg          Argument
                   6917:      * @param string[]   $long_options Available long options
                   6918:      * @param string[][] &$opts
                   6919:      * @param string[]   &$args
                   6920:      *
                   6921:      * @access private
                   6922:      * @return void|PEAR_Error
                   6923:      */
                   6924:     function _parseLongOption($arg, $long_options, &$opts, &$args, $skip_unknown)
                   6925:     {
                   6926:         @list($opt, $opt_arg) = explode('=', $arg, 2);
                   6927: 
                   6928:         $opt_len = strlen($opt);
                   6929: 
                   6930:         for ($i = 0; $i < count($long_options); $i++) {
                   6931:             $long_opt  = $long_options[$i];
                   6932:             $opt_start = substr($long_opt, 0, $opt_len);
                   6933: 
                   6934:             $long_opt_name = str_replace('=', '', $long_opt);
                   6935: 
                   6936:             /* Option doesn't match. Go on to the next one. */
                   6937:             if ($long_opt_name != $opt) {
                   6938:                 continue;
                   6939:             }
                   6940: 
                   6941:             $opt_rest = substr($long_opt, $opt_len);
                   6942: 
                   6943:             /* Check that the options uniquely matches one of the allowed
                   6944:                options. */
                   6945:             if ($i + 1 < count($long_options)) {
                   6946:                 $next_option_rest = substr($long_options[$i + 1], $opt_len);
                   6947:             } else {
                   6948:                 $next_option_rest = '';
                   6949:             }
                   6950: 
                   6951:             if ($opt_rest != '' && $opt{0} != '=' &&
                   6952:                 $i + 1 < count($long_options) &&
                   6953:                 $opt == substr($long_options[$i+1], 0, $opt_len) &&
                   6954:                 $next_option_rest != '' &&
                   6955:                 $next_option_rest{0} != '=') {
                   6956: 
                   6957:                 $msg = "Console_Getopt: option --$opt is ambiguous";
                   6958:                 return PEAR::raiseError($msg);
                   6959:             }
                   6960: 
                   6961:             if (substr($long_opt, -1) == '=') {
                   6962:                 if (substr($long_opt, -2) != '==') {
                   6963:                     /* Long option requires an argument.
                   6964:                        Take the next argument if one wasn't specified. */;
                   6965:                     if (!strlen($opt_arg) && !(list(, $opt_arg) = each($args))) {
                   6966:                         $msg = "Console_Getopt: option requires an argument --$opt";
                   6967:                         return PEAR::raiseError($msg);
                   6968:                     }
                   6969: 
                   6970:                     if (Console_Getopt::_isShortOpt($opt_arg)
                   6971:                         || Console_Getopt::_isLongOpt($opt_arg)) {
                   6972:                         $msg = "Console_Getopt: option requires an argument --$opt";
                   6973:                         return PEAR::raiseError($msg);
                   6974:                     }
                   6975:                 }
                   6976:             } else if ($opt_arg) {
                   6977:                 $msg = "Console_Getopt: option --$opt doesn't allow an argument";
                   6978:                 return PEAR::raiseError($msg);
                   6979:             }
                   6980: 
                   6981:             $opts[] = array('--' . $opt, $opt_arg);
                   6982:             return;
                   6983:         }
                   6984: 
                   6985:         if ($skip_unknown === true) {
                   6986:             return;
                   6987:         }
                   6988: 
                   6989:         return PEAR::raiseError("Console_Getopt: unrecognized option --$opt");
                   6990:     }
                   6991: 
                   6992:     /**
                   6993:      * Safely read the $argv PHP array across different PHP configurations.
                   6994:      * Will take care on register_globals and register_argc_argv ini directives
                   6995:      *
                   6996:      * @access public
                   6997:      * @return mixed the $argv PHP array or PEAR error if not registered
                   6998:      */
                   6999:     function readPHPArgv()
                   7000:     {
                   7001:         global $argv;
                   7002:         if (!is_array($argv)) {
                   7003:             if (!@is_array($_SERVER['argv'])) {
                   7004:                 if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) {
                   7005:                     $msg = "Could not read cmd args (register_argc_argv=Off?)";
                   7006:                     return PEAR::raiseError("Console_Getopt: " . $msg);
                   7007:                 }
                   7008:                 return $GLOBALS['HTTP_SERVER_VARS']['argv'];
                   7009:             }
                   7010:             return $_SERVER['argv'];
                   7011:         }
                   7012:         return $argv;
                   7013:     }
                   7014: 
                   7015: }<?php
                   7016: while (@ob_end_flush());
1.1.1.2 ! misho    7017: /* $Id$ */
1.1       misho    7018: 
                   7019: error_reporting(1803);
                   7020: 
                   7021: if (ini_get('date.timezone') === '' && function_exists('date_default_timezone_set')) {
                   7022:     date_default_timezone_set('UTC');
                   7023: }
                   7024: 
                   7025: $pear_dir = dirname(__FILE__);
                   7026: ini_set('include_path', '');
                   7027: if (function_exists('mb_internal_encoding')) {
                   7028:     mb_internal_encoding('ASCII');
                   7029: }
                   7030: set_time_limit(0);
                   7031: include_once 'phar://install-pear-nozlib.phar/PEAR.php';
                   7032: include_once 'phar://install-pear-nozlib.phar/PEAR/Installer.php';
                   7033: include_once 'phar://install-pear-nozlib.phar/PEAR/Registry.php';
                   7034: include_once 'phar://install-pear-nozlib.phar/PEAR/PackageFile.php';
                   7035: include_once 'phar://install-pear-nozlib.phar/PEAR/Downloader/Package.php';
                   7036: include_once 'phar://install-pear-nozlib.phar/PEAR/Frontend.php';
                   7037: $a = true;
                   7038: if (!PEAR::loadExtension('xml')) {
                   7039:     $a = false;
                   7040:     echo "[PEAR] xml extension is required\n";
                   7041: }
                   7042: if (!PEAR::loadExtension('pcre')) {
                   7043:     $a = false;
                   7044:     echo "[PEAR] pcre extension is required\n";
                   7045: }
                   7046: if (!$a) {
                   7047:     return -1;
                   7048: }
                   7049: 
                   7050: $force = false;
1.1.1.2 ! misho    7051: $install_files = array('Archive_Tar' => 'phar://install-pear-nozlib.phar/Archive_Tar-1.3.11.tar',
        !          7052: 'Console_Getopt' => 'phar://install-pear-nozlib.phar/Console_Getopt-1.3.1.tar',
        !          7053: 'PEAR' => 'phar://install-pear-nozlib.phar/PEAR-1.9.4.tar',
1.1       misho    7054: 'Structures_Graph' => 'phar://install-pear-nozlib.phar/Structures_Graph-1.0.4.tar',
                   7055: 'XML_Util' => 'phar://install-pear-nozlib.phar/XML_Util-1.2.1.tar',
                   7056: );
                   7057: array_shift($argv);
                   7058: $debug = false;
                   7059: for ($i = 0; $i < sizeof($argv); $i++) {
                   7060:     $arg = $argv[$i];
                   7061:     $bn = basename($arg);
                   7062:     if (preg_match('/package-(.*)\.xml$/', $bn, $matches) ||
                   7063:         preg_match('/([A-Za-z0-9_:]+)-.*\.(tar|tgz)$/', $bn, $matches)) {
                   7064:         $install_files[$matches[1]] = $arg;
1.1.1.2 ! misho    7065:     } elseif ($arg == '-a' || $arg == '--cache') {
1.1       misho    7066:         $cache_dir = $argv[$i+1];
                   7067:         $i++;
                   7068:     } elseif ($arg == '--force') {
                   7069:         $force = true;
                   7070:     } elseif ($arg == '-dp') {
                   7071:         $prefix = $argv[$i+1];
                   7072:         $i++;
                   7073:     } elseif ($arg == '-ds') {
                   7074:         $suffix = $argv[$i+1];
                   7075:         $i++;
1.1.1.2 ! misho    7076:     } elseif ($arg == '-d' || $arg == '--dir') {
1.1       misho    7077:         $with_dir = $argv[$i+1];
                   7078:         $i++;
1.1.1.2 ! misho    7079:     } elseif ($arg == '-b' || $arg == '--bin') {
1.1       misho    7080:         $bin_dir = $argv[$i+1];
                   7081:         $i++;
1.1.1.2 ! misho    7082:     } elseif ($arg == '-c' || $arg == '--config') {
1.1       misho    7083:         $cfg_dir = $argv[$i+1];
                   7084:         $i++;
1.1.1.2 ! misho    7085:     } elseif ($arg == '-w' || $arg == '--www') {
1.1       misho    7086:         $www_dir = $argv[$i+1];
                   7087:         $i++;
1.1.1.2 ! misho    7088:     } elseif ($arg == '-p' || $arg == '--php') {
1.1       misho    7089:         $php_bin = $argv[$i+1];
                   7090:         $i++;
1.1.1.2 ! misho    7091:     } elseif ($arg == '-o' || $arg == '--download') {
1.1       misho    7092:         $download_dir = $argv[$i+1];
                   7093:         $i++;
1.1.1.2 ! misho    7094:     } elseif ($arg == '-m' || $arg == '--metadata') {
        !          7095:         $metadata_dir = $argv[$i+1];
        !          7096:         $i++;
        !          7097:     } elseif ($arg == '-t' || $arg == '--temp') {
1.1       misho    7098:         $temp_dir = $argv[$i+1];
                   7099:         $i++;
1.1.1.2 ! misho    7100:     } elseif ($arg == '-A' || $arg == '--data') {
        !          7101:         $data_dir = $argv[$i+1];
        !          7102:         $i++;
        !          7103:     } elseif ($arg == '-D' || $arg == '--doc') {
        !          7104:         $doc_dir = $argv[$i+1];
        !          7105:         $i++;
        !          7106:     } elseif ($arg == '-T' || $arg == '--test') {
        !          7107:         $test_dir = $argv[$i+1];
        !          7108:         $i++;
1.1       misho    7109:     } elseif ($arg == '--debug') {
                   7110:         $debug = 1;
                   7111:     } elseif ($arg == '--extremedebug') {
                   7112:         $debug = 2;
                   7113:     }
                   7114: }
                   7115: 
                   7116: $config = PEAR_Config::singleton();
                   7117: 
                   7118: if (PEAR::isError($config)) {
                   7119:     $locs = PEAR_Config::getDefaultConfigFiles();
                   7120:     die("ERROR: One of $locs[user] or $locs[system] is corrupt, please remove them and try again");
                   7121: }
                   7122: 
                   7123: // make sure we use only default values
                   7124: $config_layers = $config->getLayers();
                   7125: foreach ($config_layers as $layer) {
                   7126:     if ($layer == 'default') continue;
                   7127:     $config->removeLayer($layer);
                   7128: }
                   7129: $keys = $config->getKeys();
                   7130: if ($debug) {
                   7131:     $config->set('verbose', 5, 'default');
                   7132: } else {
                   7133:     $config->set('verbose', 0, 'default');
                   7134: }
                   7135: // PEAR executables
                   7136: if (!empty($bin_dir)) {
                   7137:     $config->set('bin_dir', $bin_dir, 'default');
                   7138: }
                   7139: 
                   7140: // Cache files
                   7141: if (!empty($cache_dir)) {
                   7142:     $config->set('cache_dir', $cache_dir, 'default');
                   7143: }
                   7144: 
                   7145: // Config files
                   7146: if (!empty($cfg_dir)) {
                   7147:     $config->set('cfg_dir', $cfg_dir, 'default');
                   7148: }
                   7149: 
                   7150: // Web files
                   7151: if (!empty($www_dir)) {
                   7152:     $config->set('www_dir', $www_dir, 'default');
                   7153: }
                   7154: 
                   7155: // Downloaded files
                   7156: if (!empty($download_dir)) {
                   7157:     $config->set('download_dir', $download_dir, 'default');
                   7158: }
                   7159: 
                   7160: // Temporary files
                   7161: if (!empty($temp_dir)) {
                   7162:     $config->set('temp_dir', $temp_dir, 'default');
                   7163: }
                   7164: 
1.1.1.2 ! misho    7165: // Documentation files
        !          7166: if (!empty($doc_dir)) {
        !          7167:     $config->set('doc_dir', $doc_dir, 'default');
        !          7168: }
        !          7169: 
        !          7170: // Data files
        !          7171: if (!empty($data_dir)) {
        !          7172:     $config->set('data_dir', $data_dir, 'default');
        !          7173: }
        !          7174: 
        !          7175: // Unit tests
        !          7176: if (!empty($test_dir)) {
        !          7177:     $config->set('test_dir', $test_dir, 'default');
        !          7178: }
        !          7179: 
1.1       misho    7180: // User supplied a dir prefix
                   7181: if (!empty($with_dir)) {
                   7182:     $ds = DIRECTORY_SEPARATOR;
                   7183:     $config->set('php_dir', $with_dir, 'default');
1.1.1.2 ! misho    7184:     // Metadata
        !          7185:     if (!empty($metadata_dir)) {
        !          7186:         $config->set('metadata_dir', $metadata_dir, 'default');
        !          7187:     }
        !          7188:     if (empty($doc_dir)) {
        !          7189:         $config->set('doc_dir', $with_dir . $ds . 'doc', 'default');
        !          7190:     }
        !          7191:     if (empty($data_dir)) {
        !          7192:         $config->set('data_dir', $with_dir . $ds . 'data', 'default');
        !          7193:     }
        !          7194:     if (empty($test_dir)) {
        !          7195:         $config->set('test_dir', $with_dir . $ds . 'test', 'default');
        !          7196:     }
1.1       misho    7197:     if (empty($www_dir)) {
                   7198:         $config->set('www_dir', $with_dir . $ds . 'htdocs', 'default');
                   7199:     }
                   7200:     if (empty($cfg_dir)) {
                   7201:         $config->set('cfg_dir', $with_dir . $ds . 'cfg', 'default');
                   7202:     }
                   7203:     if (!is_writable($config->get('cache_dir'))) {
                   7204:         include_once 'phar://install-pear-nozlib.phar/System.php';
                   7205:         $cdir = System::mktemp(array('-d', 'pear'));
                   7206:         if (PEAR::isError($cdir)) {
                   7207:             $ui->outputData("[PEAR] cannot make new temporary directory: " . $cdir);
                   7208:             die(1);
                   7209:         }
                   7210:         $oldcachedir = $config->get('cache_dir');
                   7211:         $config->set('cache_dir', $cdir);
                   7212:     }
                   7213: }
                   7214: 
                   7215: // PHP executable
                   7216: if (!empty($php_bin)) {
                   7217:     $config->set('php_bin', $php_bin);
                   7218: }
                   7219: 
                   7220: // PHP prefix
                   7221: if (isset($prefix)) {
                   7222:     if ($prefix != 'a') {
                   7223:         if ($prefix[0] == 'a') {
                   7224:             $prefix = substr($prefix, 1);
                   7225:         }
                   7226:         $config->set('php_prefix', $prefix, 'system');
                   7227:     }
                   7228: }
                   7229: 
                   7230: // PHP suffix
                   7231: if (isset($suffix)) {
                   7232:     if ($suffix != 'a') {
                   7233:         if ($suffix[0] == 'a') {
                   7234:             $suffix = substr($suffix, 1);
                   7235:         }
                   7236:         $config->set('php_suffix', $suffix, 'system');
                   7237:     }
                   7238: }
                   7239: 
                   7240: /* Print PEAR Conf (useful for debuging do NOT REMOVE) */
                   7241: if ($debug) {
                   7242:     sort($keys);
                   7243:     foreach ($keys as $key) {
                   7244:         echo $key . '    ' .
                   7245:             $config->getPrompt($key) . ": " . $config->get($key, null, 'default') . "\n";
                   7246:     }
                   7247:     if ($debug == 2) { // extreme debugging
                   7248:         exit;
                   7249:     }
                   7250: }
                   7251: // end print
                   7252: 
                   7253: $php_dir = $config->get('php_dir');
                   7254: $options = array();
                   7255: $options['upgrade'] = true;
                   7256: $install_root = getenv('INSTALL_ROOT');
                   7257: if (!empty($install_root)) {
                   7258:     $options['packagingroot'] = $install_root;
1.1.1.2 ! misho    7259:     $reg = &new PEAR_Registry($options['packagingroot'], false, false, $metadata_dir);
1.1       misho    7260: } else {
                   7261:     $reg = $config->getRegistry('default');
                   7262: }
                   7263: 
                   7264: $ui = PEAR_Frontend::singleton('PEAR_Frontend_CLI');
                   7265: if (PEAR::isError($ui)) {
                   7266:     die($ui->getMessage());
                   7267: }
                   7268: $installer = new PEAR_Installer($ui);
                   7269: $pkg = new PEAR_PackageFile($config, $debug);
                   7270: 
                   7271: foreach ($install_files as $package => $instfile) {
                   7272:     $info = $pkg->fromAnyFile($instfile, PEAR_VALIDATE_INSTALLING);
                   7273:     if (PEAR::isError($info)) {
                   7274:         if (is_array($info->getUserInfo())) {
                   7275:             foreach ($info->getUserInfo() as $err) {
                   7276:                 $ui->outputData(sprintf("[PEAR] %s: %s", $package, $err['message']));
                   7277:             }
                   7278:         }
                   7279:         $ui->outputData(sprintf("[PEAR] %s: %s", $package, $info->getMessage()));
                   7280:         continue;
                   7281:     }
                   7282:     $new_ver = $info->getVersion();
                   7283:     $downloaderpackage = new PEAR_Downloader_Package($installer);
                   7284:     $err = $downloaderpackage->initialize($instfile);
                   7285:     if (PEAR::isError($err)) {
                   7286:         $ui->outputData(sprintf("[PEAR] %s: %s", $package, $err->getMessage()));
                   7287:         continue;
                   7288:     }
                   7289:     if ($reg->packageExists($package)) {
                   7290:         $old_ver = $reg->packageInfo($package, 'version');
                   7291:         if (version_compare($new_ver, $old_ver, 'gt')) {
                   7292:             $installer->setOptions($options);
                   7293:             $dp = array($downloaderpackage);
                   7294:             $installer->setDownloadedPackages($dp);
                   7295:             $err = $installer->install($downloaderpackage, $options);
                   7296:             if (PEAR::isError($err)) {
                   7297:                 $ui->outputData(sprintf("[PEAR] %s: %s", $package, $err->getMessage()));
                   7298:                 continue;
                   7299:             }
                   7300:             $ui->outputData(sprintf("[PEAR] %-15s- upgraded:  %s", $package, $new_ver));
                   7301:         } else {
                   7302:             if ($force) {
                   7303:                 $options['force'] = true;
                   7304:                 $installer->setOptions($options);
                   7305:                 $dp = array($downloaderpackage);
                   7306:                 $installer->setDownloadedPackages($dp);
                   7307:                 $err = $installer->install($downloaderpackage, $options);
                   7308:                 if (PEAR::isError($err)) {
                   7309:                     $ui->outputData(sprintf("[PEAR] %s: %s", $package, $err->getMessage()));
                   7310:                     continue;
                   7311:                 }
                   7312:                 $ui->outputData(sprintf("[PEAR] %-15s- installed: %s", $package, $new_ver));
                   7313:             } else {
                   7314:                 $ui->outputData(sprintf("[PEAR] %-15s- already installed: %s", $package, $old_ver));
                   7315:             }
                   7316:         }
                   7317:     } else {
                   7318:         $options['nodeps'] = true;
                   7319:         $installer->setOptions($options);
                   7320:         $dp = array($downloaderpackage);
                   7321:         $installer->setDownloadedPackages($dp);
                   7322:         $err = $installer->install($downloaderpackage, $options);
                   7323:         if (PEAR::isError($err)) {
                   7324:             $ui->outputData(sprintf("[PEAR] %s: %s", $package, $err->getMessage()));
                   7325:             continue;
                   7326:         }
                   7327:         $ui->outputData(sprintf("[PEAR] %-15s- installed: %s", $package, $new_ver));
                   7328:     }
                   7329:     if ($package == 'PEAR') {
                   7330:         if (is_file($ufile = $config->getConfFile('user'))) {
                   7331:             $ui->outputData('Warning! a PEAR user config file already exists from ' .
                   7332:                             'a previous PEAR installation at ' .
                   7333:                             "'$ufile'. You may probably want to remove it.");
                   7334:         }
                   7335:         $config->set('verbose', 1, 'default');
                   7336:         if (isset($oldcachedir)) {
                   7337:             $config->set('cache_dir', $oldcachedir);
                   7338:         }
                   7339:         $data = array();
                   7340:         foreach ($config->getKeys() as $key) {
                   7341:             $data[$key] = $config->get($key);
                   7342:         }
                   7343:         $cnf_file = $config->getConfFile('system');
                   7344:         if (!empty($install_root)) {
                   7345:             $cnf_file = $install_root . DIRECTORY_SEPARATOR . $cnf_file;
                   7346:         }
                   7347:         $config->writeConfigFile($cnf_file, 'system', $data);
                   7348:         $ui->outputData('Wrote PEAR system config file at: ' . $cnf_file);
                   7349:         $ui->outputData('You may want to add: ' . $config->get('php_dir') . ' to your php.ini include_path');
                   7350:     }
                   7351: }
                   7352: ?>
                   7353: <?php
                   7354: /**
                   7355:  * The OS_Guess class
                   7356:  *
                   7357:  * PHP versions 4 and 5
                   7358:  *
                   7359:  * @category   pear
                   7360:  * @package    PEAR
                   7361:  * @author     Stig Bakken <ssb@php.net>
                   7362:  * @author     Gregory Beaver <cellog@php.net>
                   7363:  * @copyright  1997-2009 The Authors
                   7364:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    7365:  * @version    CVS: $Id: Guess.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    7366:  * @link       http://pear.php.net/package/PEAR
                   7367:  * @since      File available since PEAR 0.1
                   7368:  */
                   7369: 
                   7370: // {{{ uname examples
                   7371: 
                   7372: // php_uname() without args returns the same as 'uname -a', or a PHP-custom
                   7373: // string for Windows.
                   7374: // PHP versions prior to 4.3 return the uname of the host where PHP was built,
                   7375: // as of 4.3 it returns the uname of the host running the PHP code.
                   7376: //
                   7377: // PC RedHat Linux 7.1:
                   7378: // Linux host.example.com 2.4.2-2 #1 Sun Apr 8 20:41:30 EDT 2001 i686 unknown
                   7379: //
                   7380: // PC Debian Potato:
                   7381: // Linux host 2.4.17 #2 SMP Tue Feb 12 15:10:04 CET 2002 i686 unknown
                   7382: //
                   7383: // PC FreeBSD 3.3:
                   7384: // FreeBSD host.example.com 3.3-STABLE FreeBSD 3.3-STABLE #0: Mon Feb 21 00:42:31 CET 2000     root@example.com:/usr/src/sys/compile/CONFIG  i386
                   7385: //
                   7386: // PC FreeBSD 4.3:
                   7387: // FreeBSD host.example.com 4.3-RELEASE FreeBSD 4.3-RELEASE #1: Mon Jun 25 11:19:43 EDT 2001     root@example.com:/usr/src/sys/compile/CONFIG  i386
                   7388: //
                   7389: // PC FreeBSD 4.5:
                   7390: // FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb  6 23:59:23 CET 2002     root@example.com:/usr/src/sys/compile/CONFIG  i386
                   7391: //
                   7392: // PC FreeBSD 4.5 w/uname from GNU shellutils:
                   7393: // FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb  i386 unknown
                   7394: //
                   7395: // HP 9000/712 HP-UX 10:
                   7396: // HP-UX iq B.10.10 A 9000/712 2008429113 two-user license
                   7397: //
                   7398: // HP 9000/712 HP-UX 10 w/uname from GNU shellutils:
                   7399: // HP-UX host B.10.10 A 9000/712 unknown
                   7400: //
                   7401: // IBM RS6000/550 AIX 4.3:
                   7402: // AIX host 3 4 000003531C00
                   7403: //
                   7404: // AIX 4.3 w/uname from GNU shellutils:
                   7405: // AIX host 3 4 000003531C00 unknown
                   7406: //
                   7407: // SGI Onyx IRIX 6.5 w/uname from GNU shellutils:
                   7408: // IRIX64 host 6.5 01091820 IP19 mips
                   7409: //
                   7410: // SGI Onyx IRIX 6.5:
                   7411: // IRIX64 host 6.5 01091820 IP19
                   7412: //
                   7413: // SparcStation 20 Solaris 8 w/uname from GNU shellutils:
                   7414: // SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc
                   7415: //
                   7416: // SparcStation 20 Solaris 8:
                   7417: // SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc SUNW,SPARCstation-20
                   7418: //
                   7419: // Mac OS X (Darwin)
                   7420: // Darwin home-eden.local 7.5.0 Darwin Kernel Version 7.5.0: Thu Aug  5 19:26:16 PDT 2004; root:xnu/xnu-517.7.21.obj~3/RELEASE_PPC  Power Macintosh
                   7421: //
                   7422: // Mac OS X early versions
                   7423: //
                   7424: 
                   7425: // }}}
                   7426: 
                   7427: /* TODO:
                   7428:  * - define endianness, to allow matchSignature("bigend") etc.
                   7429:  */
                   7430: 
                   7431: /**
                   7432:  * Retrieves information about the current operating system
                   7433:  *
                   7434:  * This class uses php_uname() to grok information about the current OS
                   7435:  *
                   7436:  * @category   pear
                   7437:  * @package    PEAR
                   7438:  * @author     Stig Bakken <ssb@php.net>
                   7439:  * @author     Gregory Beaver <cellog@php.net>
                   7440:  * @copyright  1997-2009 The Authors
                   7441:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    7442:  * @version    Release: 1.9.4
1.1       misho    7443:  * @link       http://pear.php.net/package/PEAR
                   7444:  * @since      Class available since Release 0.1
                   7445:  */
                   7446: class OS_Guess
                   7447: {
                   7448:     var $sysname;
                   7449:     var $nodename;
                   7450:     var $cpu;
                   7451:     var $release;
                   7452:     var $extra;
                   7453: 
                   7454:     function OS_Guess($uname = null)
                   7455:     {
                   7456:         list($this->sysname,
                   7457:              $this->release,
                   7458:              $this->cpu,
                   7459:              $this->extra,
                   7460:              $this->nodename) = $this->parseSignature($uname);
                   7461:     }
                   7462: 
                   7463:     function parseSignature($uname = null)
                   7464:     {
                   7465:         static $sysmap = array(
                   7466:             'HP-UX' => 'hpux',
                   7467:             'IRIX64' => 'irix',
                   7468:         );
                   7469:         static $cpumap = array(
                   7470:             'i586' => 'i386',
                   7471:             'i686' => 'i386',
                   7472:             'ppc' => 'powerpc',
                   7473:         );
                   7474:         if ($uname === null) {
                   7475:             $uname = php_uname();
                   7476:         }
                   7477:         $parts = preg_split('/\s+/', trim($uname));
                   7478:         $n = count($parts);
                   7479: 
                   7480:         $release  = $machine = $cpu = '';
                   7481:         $sysname  = $parts[0];
                   7482:         $nodename = $parts[1];
                   7483:         $cpu      = $parts[$n-1];
                   7484:         $extra = '';
                   7485:         if ($cpu == 'unknown') {
                   7486:             $cpu = $parts[$n - 2];
                   7487:         }
                   7488: 
                   7489:         switch ($sysname) {
                   7490:             case 'AIX' :
                   7491:                 $release = "$parts[3].$parts[2]";
                   7492:                 break;
                   7493:             case 'Windows' :
                   7494:                 switch ($parts[1]) {
                   7495:                     case '95/98':
                   7496:                         $release = '9x';
                   7497:                         break;
                   7498:                     default:
                   7499:                         $release = $parts[1];
                   7500:                         break;
                   7501:                 }
                   7502:                 $cpu = 'i386';
                   7503:                 break;
                   7504:             case 'Linux' :
                   7505:                 $extra = $this->_detectGlibcVersion();
                   7506:                 // use only the first two digits from the kernel version
                   7507:                 $release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]);
                   7508:                 break;
                   7509:             case 'Mac' :
                   7510:                 $sysname = 'darwin';
                   7511:                 $nodename = $parts[2];
                   7512:                 $release = $parts[3];
                   7513:                 if ($cpu == 'Macintosh') {
                   7514:                     if ($parts[$n - 2] == 'Power') {
                   7515:                         $cpu = 'powerpc';
                   7516:                     }
                   7517:                 }
                   7518:                 break;
                   7519:             case 'Darwin' :
                   7520:                 if ($cpu == 'Macintosh') {
                   7521:                     if ($parts[$n - 2] == 'Power') {
                   7522:                         $cpu = 'powerpc';
                   7523:                     }
                   7524:                 }
                   7525:                 $release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]);
                   7526:                 break;
                   7527:             default:
                   7528:                 $release = preg_replace('/-.*/', '', $parts[2]);
                   7529:                 break;
                   7530:         }
                   7531: 
                   7532:         if (isset($sysmap[$sysname])) {
                   7533:             $sysname = $sysmap[$sysname];
                   7534:         } else {
                   7535:             $sysname = strtolower($sysname);
                   7536:         }
                   7537:         if (isset($cpumap[$cpu])) {
                   7538:             $cpu = $cpumap[$cpu];
                   7539:         }
                   7540:         return array($sysname, $release, $cpu, $extra, $nodename);
                   7541:     }
                   7542: 
                   7543:     function _detectGlibcVersion()
                   7544:     {
                   7545:         static $glibc = false;
                   7546:         if ($glibc !== false) {
                   7547:             return $glibc; // no need to run this multiple times
                   7548:         }
                   7549:         $major = $minor = 0;
                   7550:         include_once 'phar://install-pear-nozlib.phar/' . "System.php";
                   7551:         // Use glibc's <features.h> header file to
                   7552:         // get major and minor version number:
                   7553:         if (@file_exists('/usr/include/features.h') &&
                   7554:               @is_readable('/usr/include/features.h')) {
                   7555:             if (!@file_exists('/usr/bin/cpp') || !@is_executable('/usr/bin/cpp')) {
                   7556:                 $features_file = fopen('/usr/include/features.h', 'rb');
                   7557:                 while (!feof($features_file)) {
                   7558:                     $line = fgets($features_file, 8192);
                   7559:                     if (!$line || (strpos($line, '#define') === false)) {
                   7560:                         continue;
                   7561:                     }
                   7562:                     if (strpos($line, '__GLIBC__')) {
                   7563:                         // major version number #define __GLIBC__ version
                   7564:                         $line = preg_split('/\s+/', $line);
                   7565:                         $glibc_major = trim($line[2]);
                   7566:                         if (isset($glibc_minor)) {
                   7567:                             break;
                   7568:                         }
                   7569:                         continue;
                   7570:                     }
                   7571: 
                   7572:                     if (strpos($line, '__GLIBC_MINOR__'))  {
                   7573:                         // got the minor version number
                   7574:                         // #define __GLIBC_MINOR__ version
                   7575:                         $line = preg_split('/\s+/', $line);
                   7576:                         $glibc_minor = trim($line[2]);
                   7577:                         if (isset($glibc_major)) {
                   7578:                             break;
                   7579:                         }
                   7580:                         continue;
                   7581:                     }
                   7582:                 }
                   7583:                 fclose($features_file);
                   7584:                 if (!isset($glibc_major) || !isset($glibc_minor)) {
                   7585:                     return $glibc = '';
                   7586:                 }
                   7587:                 return $glibc = 'glibc' . trim($glibc_major) . "." . trim($glibc_minor) ;
                   7588:             } // no cpp
                   7589: 
                   7590:             $tmpfile = System::mktemp("glibctest");
                   7591:             $fp = fopen($tmpfile, "w");
                   7592:             fwrite($fp, "#include <features.h>\n__GLIBC__ __GLIBC_MINOR__\n");
                   7593:             fclose($fp);
                   7594:             $cpp = popen("/usr/bin/cpp $tmpfile", "r");
                   7595:             while ($line = fgets($cpp, 1024)) {
                   7596:                 if ($line{0} == '#' || trim($line) == '') {
                   7597:                     continue;
                   7598:                 }
                   7599: 
                   7600:                 if (list($major, $minor) = explode(' ', trim($line))) {
                   7601:                     break;
                   7602:                 }
                   7603:             }
                   7604:             pclose($cpp);
                   7605:             unlink($tmpfile);
                   7606:         } // features.h
                   7607: 
                   7608:         if (!($major && $minor) && @is_link('/lib/libc.so.6')) {
                   7609:             // Let's try reading the libc.so.6 symlink
                   7610:             if (preg_match('/^libc-(.*)\.so$/', basename(readlink('/lib/libc.so.6')), $matches)) {
                   7611:                 list($major, $minor) = explode('.', $matches[1]);
                   7612:             }
                   7613:         }
                   7614: 
                   7615:         if (!($major && $minor)) {
                   7616:             return $glibc = '';
                   7617:         }
                   7618: 
                   7619:         return $glibc = "glibc{$major}.{$minor}";
                   7620:     }
                   7621: 
                   7622:     function getSignature()
                   7623:     {
                   7624:         if (empty($this->extra)) {
                   7625:             return "{$this->sysname}-{$this->release}-{$this->cpu}";
                   7626:         }
                   7627:         return "{$this->sysname}-{$this->release}-{$this->cpu}-{$this->extra}";
                   7628:     }
                   7629: 
                   7630:     function getSysname()
                   7631:     {
                   7632:         return $this->sysname;
                   7633:     }
                   7634: 
                   7635:     function getNodename()
                   7636:     {
                   7637:         return $this->nodename;
                   7638:     }
                   7639: 
                   7640:     function getCpu()
                   7641:     {
                   7642:         return $this->cpu;
                   7643:     }
                   7644: 
                   7645:     function getRelease()
                   7646:     {
                   7647:         return $this->release;
                   7648:     }
                   7649: 
                   7650:     function getExtra()
                   7651:     {
                   7652:         return $this->extra;
                   7653:     }
                   7654: 
                   7655:     function matchSignature($match)
                   7656:     {
                   7657:         $fragments = is_array($match) ? $match : explode('-', $match);
                   7658:         $n = count($fragments);
                   7659:         $matches = 0;
                   7660:         if ($n > 0) {
                   7661:             $matches += $this->_matchFragment($fragments[0], $this->sysname);
                   7662:         }
                   7663:         if ($n > 1) {
                   7664:             $matches += $this->_matchFragment($fragments[1], $this->release);
                   7665:         }
                   7666:         if ($n > 2) {
                   7667:             $matches += $this->_matchFragment($fragments[2], $this->cpu);
                   7668:         }
                   7669:         if ($n > 3) {
                   7670:             $matches += $this->_matchFragment($fragments[3], $this->extra);
                   7671:         }
                   7672:         return ($matches == $n);
                   7673:     }
                   7674: 
                   7675:     function _matchFragment($fragment, $value)
                   7676:     {
                   7677:         if (strcspn($fragment, '*?') < strlen($fragment)) {
                   7678:             $reg = '/^' . str_replace(array('*', '?', '/'), array('.*', '.', '\\/'), $fragment) . '\\z/';
                   7679:             return preg_match($reg, $value);
                   7680:         }
                   7681:         return ($fragment == '*' || !strcasecmp($fragment, $value));
                   7682:     }
                   7683: 
                   7684: }
                   7685: /*
                   7686:  * Local Variables:
                   7687:  * indent-tabs-mode: nil
                   7688:  * c-basic-offset: 4
                   7689:  * End:
1.1.1.2 ! misho    7690:  */package2.xml0000644000076500000240000013062211605156614012241 0ustar  helgistaff<?xml version="1.0" encoding="UTF-8"?>
1.1       misho    7691: <package packagerversion="1.9.4" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
                   7692:  <name>PEAR</name>
                   7693:  <channel>pear.php.net</channel>
                   7694:  <summary>PEAR Base System</summary>
                   7695:  <description>The PEAR package contains:
                   7696:  * the PEAR installer, for creating, distributing
                   7697:    and installing packages
                   7698:  * the PEAR_Exception PHP5 error handling mechanism
                   7699:  * the PEAR_ErrorStack advanced error handling mechanism
                   7700:  * the PEAR_Error error handling mechanism
                   7701:  * the OS_Guess class for retrieving info about the OS
                   7702:    where PHP is running on
                   7703:  * the System class for quick handling of common operations
                   7704:    with files and directories
                   7705:  * the PEAR base class
                   7706:   Features in a nutshell:
                   7707:   * full support for channels
                   7708:   * pre-download dependency validation
                   7709:   * new package.xml 2.0 format allows tremendous flexibility while maintaining BC
                   7710:   * support for optional dependency groups and limited support for sub-packaging
                   7711:   * robust dependency support
                   7712:   * full dependency validation on uninstall
                   7713:   * remote install for hosts with only ftp access - no more problems with
                   7714:     restricted host installation
                   7715:   * full support for mirroring
                   7716:   * support for bundling several packages into a single tarball
                   7717:   * support for static dependencies on a url-based package
                   7718:   * support for custom file roles and installation tasks</description>
                   7719:  <lead>
                   7720:   <name>Greg Beaver</name>
                   7721:   <user>cellog</user>
                   7722:   <email>cellog@php.net</email>
                   7723:   <active>no</active>
                   7724:  </lead>
                   7725:  <lead>
                   7726:   <name>Pierre-Alain Joye</name>
                   7727:   <user>pajoye</user>
                   7728:   <email>pierre@php.net</email>
                   7729:   <active>no</active>
                   7730:  </lead>
                   7731:  <lead>
                   7732:   <name>Stig Bakken</name>
                   7733:   <user>ssb</user>
                   7734:   <email>stig@php.net</email>
                   7735:   <active>no</active>
                   7736:  </lead>
                   7737:  <lead>
                   7738:   <name>Tomas V.V.Cox</name>
                   7739:   <user>cox</user>
                   7740:   <email>cox@idecnet.com</email>
                   7741:   <active>no</active>
                   7742:  </lead>
                   7743:  <lead>
                   7744:   <name>Helgi Thormar</name>
                   7745:   <user>dufuz</user>
                   7746:   <email>dufuz@php.net</email>
                   7747:   <active>yes</active>
                   7748:  </lead>
                   7749:  <developer>
                   7750:   <name>Tias Guns</name>
                   7751:   <user>tias</user>
                   7752:   <email>tias@php.net</email>
                   7753:   <active>yes</active>
                   7754:  </developer>
                   7755:  <helper>
                   7756:   <name>Tim Jackson</name>
                   7757:   <user>timj</user>
                   7758:   <email>timj@php.net</email>
                   7759:   <active>no</active>
                   7760:  </helper>
                   7761:  <helper>
                   7762:   <name>Bertrand Gugger</name>
                   7763:   <user>toggg</user>
                   7764:   <email>toggg@php.net</email>
                   7765:   <active>no</active>
                   7766:  </helper>
                   7767:  <helper>
                   7768:   <name>Martin Jansen</name>
                   7769:   <user>mj</user>
                   7770:   <email>mj@php.net</email>
                   7771:   <active>no</active>
                   7772:  </helper>
                   7773:  <date>2011-07-06</date>
1.1.1.2 ! misho    7774:  <time>22:11:24</time>
1.1       misho    7775:  <version>
                   7776:   <release>1.9.4</release>
                   7777:   <api>1.9.4</api>
                   7778:  </version>
                   7779:  <stability>
                   7780:   <release>stable</release>
                   7781:   <api>stable</api>
                   7782:  </stability>
                   7783:  <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   7784:  <notes>
                   7785: Bug Fixes:
                   7786: * Bug #17350: &quot;pear install --force&quot; doesn&apos;t uninstall files from previous pkg versions [dufuz]
                   7787: * Bug #18362: A whitespace TEMP_DIR path breaks install/upgrade functionality [dufuz]
                   7788: * Bug #18440: bad tmp folder path on install : Unable to create path for C:/Program/tmp [dufuz]
                   7789: * Bug #18581: &quot;config-get -c&quot; not returning channel&apos;s configuration when using alias [dufuz]
                   7790: * Bug #18639: regression: installing xdebug fails most likely due to another fix [dufuz]
                   7791: 
                   7792: Features
                   7793: * All System (the class) functions can now take in spaced paths as long as they are surrounded in quotes.
                   7794:   Prior to this it was possible to do that by passing all values in as an array (by product of #18362, #18440) [dufuz]
                   7795:  </notes>
                   7796:  <contents>
                   7797:   <dir name="/">
                   7798:    <file md5sum="a74724b2a02b50afb0e71f78b7661a4c" name="OS/Guess.php" role="php">
                   7799:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7800:    </file>
                   7801:    <file md5sum="d453b69059dceb53e5a61b9881fe2336" name="PEAR/ChannelFile/Parser.php" role="php">
                   7802:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7803:    </file>
                   7804:    <file md5sum="8fd87e64002e11fd86eb2f3fbfee6599" name="PEAR/Command/Auth.xml" role="php" />
                   7805:    <file md5sum="314f2756d74b4cc529e77be45847b3ac" name="PEAR/Command/Auth.php" role="php">
                   7806:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7807:    </file>
                   7808:    <file md5sum="73602fd7f051eaf8d37452d0e3063bdb" name="PEAR/Command/Build.xml" role="php" />
                   7809:    <file md5sum="aa7961eff628901fd6a08074715d18ac" name="PEAR/Command/Build.php" role="php">
                   7810:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7811:    </file>
                   7812:    <file md5sum="6d5aab4d4308c3005b5f584c7783a031" name="PEAR/Command/Channels.xml" role="php" />
                   7813:    <file md5sum="d61f91d95657304c3e7facf3f4a3ab7b" name="PEAR/Command/Channels.php" role="php">
                   7814:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7815:    </file>
                   7816:    <file md5sum="1214f0f5edb4d7531e54b32e75c3b162" name="PEAR/Command/Common.php" role="php">
                   7817:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7818:    </file>
                   7819:    <file md5sum="91f189cb9423b5e87ee0abc5ea1a2be3" name="PEAR/Command/Config.xml" role="php" />
                   7820:    <file md5sum="2cca5bfb4005291d3a234b9cc00e4091" name="PEAR/Command/Config.php" role="php">
                   7821:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7822:    </file>
                   7823:    <file md5sum="2db0386b865d3f9a29f9126728722ece" name="PEAR/Command/Install.xml" role="php" />
                   7824:    <file md5sum="32d3ee477937685cffec094424390c18" name="PEAR/Command/Install.php" role="php">
                   7825:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7826:    </file>
                   7827:    <file md5sum="5cb62a04c0a268f4edd64a49a3895c92" name="PEAR/Command/Mirror.xml" role="php" />
                   7828:    <file md5sum="bc0b8df989565f87f1693ac7a2ce0e4b" name="PEAR/Command/Mirror.php" role="php">
                   7829:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7830:    </file>
                   7831:    <file md5sum="9367dcd7e4dbdde423f9c4c7d3f3a919" name="PEAR/Command/Package.xml" role="php" />
                   7832:    <file md5sum="68f45817fe926173b45018e1b1dec108" name="PEAR/Command/Package.php" role="php">
                   7833:     <tasks:replace from="@DATA-DIR@" to="data_dir" type="pear-config" />
                   7834:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7835:    </file>
                   7836:    <file md5sum="28dc842ea725d8787b9f9c3dbca5aa22" name="PEAR/Command/Pickle.xml" role="php" />
                   7837:    <file md5sum="583e8d10daab8e16b2e2a9fc3498b1ac" name="PEAR/Command/Pickle.php" role="php">
                   7838:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7839:    </file>
                   7840:    <file md5sum="49b046cfc14747f0365e02e9c3f0e6dc" name="PEAR/Command/Registry.xml" role="php" />
                   7841:    <file md5sum="59629a5d63b0d5e54f49de509a1a6cf9" name="PEAR/Command/Registry.php" role="php">
                   7842:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7843:    </file>
                   7844:    <file md5sum="29c02e823879b4e3e291f6b36fb339f1" name="PEAR/Command/Remote.xml" role="php" />
                   7845:    <file md5sum="36c02597c5db0b5148aef6e49d3b2604" name="PEAR/Command/Remote.php" role="php">
                   7846:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7847:    </file>
                   7848:    <file md5sum="a50c32015005e0761cc3b04679b29ed0" name="PEAR/Command/Test.xml" role="php" />
                   7849:    <file md5sum="8794af46ada0364362db0e131607e6d1" name="PEAR/Command/Test.php" role="php">
                   7850:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7851:    </file>
                   7852:    <file md5sum="2a4bfddd597fcb1d63b2a06ea4544b91" name="PEAR/Downloader/Package.php" role="php">
                   7853:     <tasks:replace from="@PEAR-VER@" to="version" type="package-info" />
                   7854:    </file>
                   7855:    <file md5sum="8c8ebc9143aeff5fd5803c63e1cd0070" name="PEAR/Frontend/CLI.php" role="php">
                   7856:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7857:    </file>
                   7858:    <file md5sum="6a0785b8e9678b7283d56eba9aaea390" name="PEAR/Installer/Role/Common.php" role="php">
                   7859:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7860:    </file>
                   7861:    <file md5sum="d8c62e6275e3aaa7784290912406092c" name="PEAR/Installer/Role/Cfg.xml" role="php" />
                   7862:    <file md5sum="faee4c4408cf77aa73c608b54ed3a587" name="PEAR/Installer/Role/Cfg.php" role="php">
                   7863:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7864:    </file>
                   7865:    <file md5sum="89a4a2a286e842d45a98974f40a0565c" name="PEAR/Installer/Role/Data.xml" role="php" />
                   7866:    <file md5sum="6273b7a0c754f7ec61a9ad0e7476ab35" name="PEAR/Installer/Role/Data.php" role="php">
                   7867:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7868:    </file>
                   7869:    <file md5sum="b1ce0fe105251c3b75209d6518ee69ac" name="PEAR/Installer/Role/Doc.xml" role="php" />
                   7870:    <file md5sum="f965a64b0fc06036ed4299ab51521874" name="PEAR/Installer/Role/Doc.php" role="php">
                   7871:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7872:    </file>
                   7873:    <file md5sum="af71c0ad42d16a323afe24a4f884ef15" name="PEAR/Installer/Role/Ext.xml" role="php" />
                   7874:    <file md5sum="8222eb9dc206801ebd0495720e94490f" name="PEAR/Installer/Role/Ext.php" role="php">
                   7875:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7876:    </file>
                   7877:    <file md5sum="ef88f0321d3e481c2130c95122cf76d8" name="PEAR/Installer/Role/Php.xml" role="php" />
                   7878:    <file md5sum="5bb9fe55b02ec58880243234bd847e57" name="PEAR/Installer/Role/Php.php" role="php">
                   7879:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7880:    </file>
                   7881:    <file md5sum="746461dc3b48af6d24094cb0211608f2" name="PEAR/Installer/Role/Script.xml" role="php" />
                   7882:    <file md5sum="769a902fe324b627357860b1b922aa1c" name="PEAR/Installer/Role/Script.php" role="php">
                   7883:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7884:    </file>
                   7885:    <file md5sum="e147d63f168ea156fc2be38caaa63804" name="PEAR/Installer/Role/Src.xml" role="php" />
                   7886:    <file md5sum="8f38f7e74a60e90a7e1363b6f509b426" name="PEAR/Installer/Role/Src.php" role="php">
                   7887:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7888:    </file>
                   7889:    <file md5sum="a24b596ec987aa5688fc19e8ed4e97ea" name="PEAR/Installer/Role/Test.xml" role="php" />
                   7890:    <file md5sum="b12694a189904c77db170d89f8aa9b61" name="PEAR/Installer/Role/Test.php" role="php">
                   7891:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7892:    </file>
                   7893:    <file md5sum="7641e71c5785bb33a4261ebe25ed0fd7" name="PEAR/Installer/Role/Www.xml" role="php" />
                   7894:    <file md5sum="0a3b8808e8c7f26a7f2e3c115fd09fdc" name="PEAR/Installer/Role/Www.php" role="php">
                   7895:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7896:    </file>
                   7897:    <file md5sum="bd136be2697af553a4ba35f7eaca7f68" name="PEAR/Installer/Role.php" role="php">
                   7898:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7899:    </file>
                   7900:    <file md5sum="7db4fa3f069fc2ed490464b1efe6d801" name="PEAR/PackageFile/Generator/v1.php" role="php">
                   7901:     <tasks:replace from="@PEAR-VER@" to="version" type="package-info" />
                   7902:    </file>
                   7903:    <file md5sum="8294267046359e521dc226ebbbed8d37" name="PEAR/PackageFile/Generator/v2.php" role="php">
                   7904:     <tasks:replace from="@PEAR-VER@" to="version" type="package-info" />
                   7905:    </file>
                   7906:    <file md5sum="ef7d06b95df06047a46df12187997a4f" name="PEAR/PackageFile/Parser/v1.php" role="php">
                   7907:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7908:    </file>
                   7909:    <file md5sum="98b457406963b0ba61d6206ee3b22615" name="PEAR/PackageFile/Parser/v2.php" role="php">
                   7910:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7911:    </file>
                   7912:    <file md5sum="6cb5b523de08db7641d53fbd01161806" name="PEAR/PackageFile/v2/rw.php" role="php">
                   7913:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7914:    </file>
                   7915:    <file md5sum="4bb188500dcecfca3ee085572a6f88d2" name="PEAR/PackageFile/v2/Validator.php" role="php">
                   7916:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7917:    </file>
                   7918:    <file md5sum="6211d1048871e00e38509001e3a0248a" name="PEAR/PackageFile/v1.php" role="php">
                   7919:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7920:    </file>
                   7921:    <file md5sum="76d76e677471159a4bd4595190f849f8" name="PEAR/PackageFile/v2.php" role="php">
                   7922:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7923:    </file>
                   7924:    <file md5sum="e4a28d36a4e0e4d406034acc92f563de" name="PEAR/REST/10.php" role="php">
                   7925:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7926:    </file>
                   7927:    <file md5sum="256b8c9bd6f2411f17054a8bb8e56fa5" name="PEAR/REST/11.php" role="php">
                   7928:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7929:    </file>
                   7930:    <file md5sum="45b3138f8102e186da7cfdf8d2bd4150" name="PEAR/REST/13.php" role="php">
                   7931:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7932:    </file>
                   7933:    <file md5sum="77205d37ba0c4233ee343a78ddb6cd9d" name="PEAR/Task/Postinstallscript/rw.php" role="php">
                   7934:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7935:    </file>
                   7936:    <file md5sum="3c27b135962a1826a4e7d6b977b0b288" name="PEAR/Task/Replace/rw.php" role="php">
                   7937:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7938:    </file>
                   7939:    <file md5sum="0441c97aa22e4c281f1974df324a5cfb" name="PEAR/Task/Unixeol/rw.php" role="php">
                   7940:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7941:    </file>
                   7942:    <file md5sum="e9a7f560abe1db1c114b0cc7f3134a4a" name="PEAR/Task/Windowseol/rw.php" role="php">
                   7943:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7944:    </file>
                   7945:    <file md5sum="53e67f33a146cf9ee2d951239ab95ba0" name="PEAR/Task/Common.php" role="php">
                   7946:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7947:    </file>
                   7948:    <file md5sum="9eed944f3f795c52caba0cb87665cd7f" name="PEAR/Task/Postinstallscript.php" role="php">
                   7949:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7950:    </file>
                   7951:    <file md5sum="b51702374ca8c34dd4e540f8848f8f57" name="PEAR/Task/Replace.php" role="php">
                   7952:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7953:    </file>
                   7954:    <file md5sum="7a280f398b108bc030a126a10e75af7e" name="PEAR/Task/Unixeol.php" role="php">
                   7955:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7956:    </file>
                   7957:    <file md5sum="c321484c304ebb4de50cd204b6a61c6d" name="PEAR/Task/Windowseol.php" role="php">
                   7958:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7959:    </file>
                   7960:    <file md5sum="b8d475e539a47999dd78ddc0f2831b0e" name="PEAR/Validator/PECL.php" role="php">
                   7961:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7962:    </file>
                   7963:    <file md5sum="598ad0a7c788a4ee154501223f607fa5" name="PEAR/Autoloader.php" role="php">
                   7964:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7965:    </file>
                   7966:    <file md5sum="3a236b984c43be942864e9a2c2f7f618" name="PEAR/Builder.php" role="php">
                   7967:     <tasks:replace from="@PEAR-VER@" to="version" type="package-info" />
                   7968:    </file>
                   7969:    <file md5sum="fe1651f49d9b4e77e252c817c5ac8fb8" name="PEAR/ChannelFile.php" role="php">
                   7970:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7971:    </file>
                   7972:    <file md5sum="8dfb2616d94dc0d54ca05d6d2a9a3d60" name="PEAR/Command.php" role="php">
                   7973:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7974:    </file>
                   7975:    <file md5sum="3134df96c00615c595bc3c74c0fb605f" name="PEAR/Common.php" role="php">
                   7976:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7977:    </file>
                   7978:    <file md5sum="ef2e1652bed814e36676d605c9a7b599" name="PEAR/Config.php" role="php">
                   7979:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7980:    </file>
                   7981:    <file md5sum="708a3a44875759e005b881179b3d5ed4" name="PEAR/DependencyDB.php" role="php">
                   7982:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7983:    </file>
                   7984:    <file md5sum="0744ce601546afb988e2542b27d82aa9" name="PEAR/Dependency2.php" role="php">
                   7985:     <tasks:replace from="@PEAR-VER@" to="version" type="package-info" />
                   7986:    </file>
                   7987:    <file md5sum="3f62de6899c2ca37c89810e3510b77b9" name="PEAR/Downloader.php" role="php">
                   7988:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7989:    </file>
                   7990:    <file md5sum="3d1ee44f11a5c927f98149041cbba536" name="PEAR/ErrorStack.php" role="php">
                   7991:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7992:    </file>
                   7993:    <file md5sum="ebea74b4b24af93a0982536ae6faeb76" name="PEAR/Exception.php" role="php">
                   7994:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7995:    </file>
                   7996:    <file md5sum="e0e4cbcec4a972fbad779d0f9d323120" name="PEAR/FixPHP5PEARWarnings.php" role="php" />
                   7997:    <file md5sum="e00af62b175d4a15430be6394b09afaa" name="PEAR/Frontend.php" role="php">
                   7998:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   7999:    </file>
                   8000:    <file md5sum="5b77738449ea8d539883d520f0f05d2a" name="PEAR/Installer.php" role="php">
                   8001:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   8002:    </file>
                   8003:    <file md5sum="60600f35203b87481eb354b9b58c05f9" name="PEAR/PackageFile.php" role="php">
                   8004:     <tasks:replace from="@PEAR-VER@" to="version" type="package-info" />
                   8005:    </file>
                   8006:    <file md5sum="5e553c0ac9530fc8757735675f0837ee" name="PEAR/Packager.php" role="php">
                   8007:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   8008:    </file>
                   8009:    <file md5sum="5ff450e917d7128af3dc5d596e02bd04" name="PEAR/Registry.php" role="php">
                   8010:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   8011:    </file>
                   8012:    <file md5sum="9d0e60efa1884de7d2a812e815cbd30e" name="PEAR/REST.php" role="php">
                   8013:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   8014:    </file>
                   8015:    <file md5sum="20315d45a87c2c9fb9992f5e27a0e354" name="PEAR/RunTest.php" role="php">
                   8016:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   8017:    </file>
                   8018:    <file md5sum="709e306baa715e79696de0fcd7f5db6a" name="PEAR/Validate.php" role="php">
                   8019:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   8020:    </file>
                   8021:    <file md5sum="496230695ea1e3f7e0eb1a1e7030383f" name="PEAR/XMLParser.php" role="php">
                   8022:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   8023:    </file>
                   8024:    <file baseinstalldir="/" md5sum="d888d06143e3cac0dae78bbb2e761366" name="scripts/pear.bat" role="script">
                   8025:     <tasks:replace from="@bin_dir@" to="bin_dir" type="pear-config" />
                   8026:     <tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
                   8027:     <tasks:replace from="@include_path@" to="php_dir" type="pear-config" />
                   8028:     <tasks:windowseol />
                   8029:    </file>
                   8030:    <file baseinstalldir="/" md5sum="762c9aeb3a91f7160a12896ce197acb6" name="scripts/peardev.bat" role="script">
                   8031:     <tasks:replace from="@bin_dir@" to="bin_dir" type="pear-config" />
                   8032:     <tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
                   8033:     <tasks:replace from="@include_path@" to="php_dir" type="pear-config" />
                   8034:     <tasks:windowseol />
                   8035:    </file>
                   8036:    <file baseinstalldir="/" md5sum="2bd742ce721c8dd5aa164613c063a8a9" name="scripts/pecl.bat" role="script">
                   8037:     <tasks:replace from="@bin_dir@" to="bin_dir" type="pear-config" />
                   8038:     <tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
                   8039:     <tasks:replace from="@include_path@" to="php_dir" type="pear-config" />
                   8040:     <tasks:windowseol />
                   8041:    </file>
                   8042:    <file baseinstalldir="/" md5sum="8ac139504e80bede470aef6d405100b6" name="scripts/pear.sh" role="script">
                   8043:     <tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
                   8044:     <tasks:replace from="@php_dir@" to="php_dir" type="pear-config" />
                   8045:     <tasks:replace from="@pear_version@" to="version" type="package-info" />
                   8046:     <tasks:replace from="@include_path@" to="php_dir" type="pear-config" />
                   8047:     <tasks:unixeol />
                   8048:    </file>
                   8049:    <file baseinstalldir="/" md5sum="08ea03525b4ba914dfd9ec69c4238cf4" name="scripts/peardev.sh" role="script">
                   8050:     <tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
                   8051:     <tasks:replace from="@php_dir@" to="php_dir" type="pear-config" />
                   8052:     <tasks:replace from="@pear_version@" to="version" type="package-info" />
                   8053:     <tasks:replace from="@include_path@" to="php_dir" type="pear-config" />
                   8054:     <tasks:unixeol />
                   8055:    </file>
                   8056:    <file baseinstalldir="/" md5sum="41fab77b7808267d88b8e06097a1fbbe" name="scripts/pecl.sh" role="script">
                   8057:     <tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
                   8058:     <tasks:replace from="@php_dir@" to="php_dir" type="pear-config" />
                   8059:     <tasks:replace from="@pear_version@" to="version" type="package-info" />
                   8060:     <tasks:replace from="@include_path@" to="php_dir" type="pear-config" />
                   8061:     <tasks:unixeol />
                   8062:    </file>
                   8063:    <file baseinstalldir="/" md5sum="fc547ba1ab80167d9c9cfcbb439d1537" name="scripts/pearcmd.php" role="php">
                   8064:     <tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
                   8065:     <tasks:replace from="@php_dir@" to="php_dir" type="pear-config" />
                   8066:     <tasks:replace from="@pear_version@" to="version" type="package-info" />
                   8067:     <tasks:replace from="@include_path@" to="php_dir" type="pear-config" />
                   8068:    </file>
                   8069:    <file baseinstalldir="/" md5sum="e758c3c57ace46749eb39868fe98b2ca" name="scripts/peclcmd.php" role="php">
                   8070:     <tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
                   8071:     <tasks:replace from="@php_dir@" to="php_dir" type="pear-config" />
                   8072:     <tasks:replace from="@pear_version@" to="version" type="package-info" />
                   8073:     <tasks:replace from="@include_path@" to="php_dir" type="pear-config" />
                   8074:    </file>
                   8075:    <file md5sum="45b44486d8090de17b2a8b4211fab247" name="LICENSE" role="doc" />
                   8076:    <file md5sum="8e9d494169d0dea3d7b24bae14d85aba" name="INSTALL" role="doc" />
                   8077:    <file md5sum="4a49bc83a392934e57af45c70a589fda" name="package.dtd" role="data" />
                   8078:    <file md5sum="1a8f67d58009372a6cbcddd638b128cf" name="PEAR5.php" role="php" />
                   8079:    <file md5sum="962bdcdbc2e4467f047b233fa45296bd" name="PEAR.php" role="php">
                   8080:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   8081:    </file>
                   8082:    <file md5sum="b10231f9dd564ac24951758b67f6e155" name="README" role="doc" />
                   8083:    <file md5sum="1d62197f092116e711e6c9b7ed0c4fe9" name="System.php" role="php">
                   8084:     <tasks:replace from="@package_version@" to="version" type="package-info" />
                   8085:    </file>
                   8086:    <file md5sum="acd010e3bc43c0f72df584acde7b9158" name="template.spec" role="data" />
                   8087:   </dir>
                   8088:  </contents>
                   8089:  <dependencies>
                   8090:   <required>
                   8091:    <php>
                   8092:     <min>4.4.0</min>
                   8093:     <exclude>5.0</exclude>
                   8094:     <exclude>5.1.0</exclude>
                   8095:     <exclude>5.1.1</exclude>
                   8096:     <exclude>5.1.2</exclude>
                   8097:     <exclude>5.1.3</exclude>
                   8098:     <exclude>5.1.4</exclude>
                   8099:     <exclude>5.1.5</exclude>
                   8100:    </php>
                   8101:    <pearinstaller>
                   8102:     <min>1.4.3</min>
                   8103:    </pearinstaller>
                   8104:    <package>
                   8105:     <name>Archive_Tar</name>
                   8106:     <channel>pear.php.net</channel>
                   8107:     <min>1.3.7</min>
                   8108:    </package>
                   8109:    <package>
                   8110:     <name>Structures_Graph</name>
                   8111:     <channel>pear.php.net</channel>
                   8112:     <min>1.0.2</min>
                   8113:     <recommended>1.0.4</recommended>
                   8114:    </package>
                   8115:    <package>
                   8116:     <name>Console_Getopt</name>
                   8117:     <channel>pear.php.net</channel>
                   8118:     <min>1.2</min>
                   8119:     <recommended>1.2.3</recommended>
                   8120:    </package>
                   8121:    <package>
                   8122:     <name>XML_Util</name>
                   8123:     <channel>pear.php.net</channel>
                   8124:     <min>1.2.0</min>
                   8125:     <recommended>1.2.1</recommended>
                   8126:    </package>
                   8127:    <package>
                   8128:     <name>PEAR_Frontend_Web</name>
                   8129:     <channel>pear.php.net</channel>
                   8130:     <max>0.4</max>
                   8131:     <conflicts />
                   8132:    </package>
                   8133:    <package>
                   8134:     <name>PEAR_Frontend_Gtk</name>
                   8135:     <channel>pear.php.net</channel>
                   8136:     <max>0.4.0</max>
                   8137:     <exclude>0.4.0</exclude>
                   8138:     <conflicts />
                   8139:    </package>
                   8140:    <extension>
                   8141:     <name>xml</name>
                   8142:    </extension>
                   8143:    <extension>
                   8144:     <name>pcre</name>
                   8145:    </extension>
                   8146:   </required>
                   8147:   <group hint="PEAR's web-based installer" name="webinstaller">
                   8148:    <package>
                   8149:     <name>PEAR_Frontend_Web</name>
                   8150:     <channel>pear.php.net</channel>
                   8151:     <min>0.5.1</min>
                   8152:    </package>
                   8153:   </group>
                   8154:   <group hint="PEAR's PHP-GTK-based installer" name="gtkinstaller">
                   8155:    <package>
                   8156:     <name>PEAR_Frontend_Gtk</name>
                   8157:     <channel>pear.php.net</channel>
                   8158:     <min>0.4.0</min>
                   8159:    </package>
                   8160:   </group>
                   8161:   <group hint="PEAR's PHP-GTK2-based installer" name="gtk2installer">
                   8162:    <package>
                   8163:     <name>PEAR_Frontend_Gtk2</name>
                   8164:     <channel>pear.php.net</channel>
                   8165:    </package>
                   8166:   </group>
                   8167:  </dependencies>
                   8168:  <phprelease>
                   8169:   <installconditions>
                   8170:    <os>
                   8171:     <name>windows</name>
                   8172:    </os>
                   8173:   </installconditions>
                   8174:   <filelist>
                   8175:    <install as="pear.bat" name="scripts/pear.bat" />
                   8176:    <install as="peardev.bat" name="scripts/peardev.bat" />
                   8177:    <install as="pecl.bat" name="scripts/pecl.bat" />
                   8178:    <install as="pearcmd.php" name="scripts/pearcmd.php" />
                   8179:    <install as="peclcmd.php" name="scripts/peclcmd.php" />
                   8180:    <ignore name="scripts/peardev.sh" />
                   8181:    <ignore name="scripts/pear.sh" />
                   8182:    <ignore name="scripts/pecl.sh" />
                   8183:   </filelist>
                   8184:  </phprelease>
                   8185:  <phprelease>
                   8186:   <filelist>
                   8187:    <install as="pear" name="scripts/pear.sh" />
                   8188:    <install as="peardev" name="scripts/peardev.sh" />
                   8189:    <install as="pecl" name="scripts/pecl.sh" />
                   8190:    <install as="pearcmd.php" name="scripts/pearcmd.php" />
                   8191:    <install as="peclcmd.php" name="scripts/peclcmd.php" />
                   8192:    <ignore name="scripts/pear.bat" />
                   8193:    <ignore name="scripts/peardev.bat" />
                   8194:    <ignore name="scripts/pecl.bat" />
                   8195:   </filelist>
                   8196:  </phprelease>
                   8197:  <changelog>
                   8198:   <release>
                   8199:    <version>
                   8200:     <release>1.8.0alpha1</release>
                   8201:     <api>1.8.0</api>
                   8202:    </version>
                   8203:    <stability>
                   8204:     <release>alpha</release>
                   8205:     <api>stable</api>
                   8206:    </stability>
                   8207:    <date>2009-03-09</date>
                   8208:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8209:    <notes>
                   8210: * Implement Request #10373: if pref_state=stable and installed package=beta, allow up to latest beta version [dufuz]
                   8211: * Implement Request #10581: login / logout should map to channel-login / channel-logout [dufuz]
                   8212: * Implement Request #10825: Only display the &quot;invalid or missing package file&quot;-error if it makes sense [dufuz]
                   8213: * Implement Request #11170: script to generate Command/[command].xml [dufuz]
                   8214: * Implement Request #11176: improve channel ... has updated its protocols message [dufuz]
                   8215: * Implement Request #12706: pear list -a hard to read [dufuz]
                   8216: * Implement Request #11353: upgrade-all and upgrade commands to upgrade within the same stability level [dufuz]
                   8217: * Implement Request #13015: Add https discovery for channel.xml [dufuz / initial patch by Martin Roos]
                   8218: * Implement Request #13927: install-pear.php should have option to set www_dir [timj]
                   8219: * Implement Request #14324: Make the pear install command behave similar to apt-get [dufuz]
                   8220: * Implement Request #14325: make pear upgrade with no params behave like pear upgrade-all [dufuz]
                   8221:   - upgrade-all can be considered deprecated in favor of calling upgrade with no parameters to replicate
                   8222:     better what other package managers are doing. upgrade-all will still work as intended.
                   8223: * Implement Request #14504: add a channel parameter support to the upgrade function [dufuz]
                   8224:   - Options -c ezc and --channel=ezc got added to upgrade and upgrade-all to allow for
                   8225:     channel specific upgrades
                   8226: * Implement Request #14556: install-pear-nozlib.phar should get download_dir config and other options [cweiske]
                   8227: * Implement Request #15566: Add doc.php.net as a default channel [dufuz / saltybeagle]
                   8228: 
                   8229: * Fix PHP Bug #43857: --program-suffix not always reflected everywhere [cellog]
                   8230: * Fix PHP Bug #47323: strotime warnings in make install [dufuz]
                   8231: 
                   8232: * Fix Bug #13908: pear info command and maintainers inactive not mentioned [dufuz]
                   8233: * Fix Bug #13926: install-pear.php does not set cfg_dir if -d option set with no -c option [timj]
                   8234: * Fix Bug #13943: tests fail when php.exe path contains spaces [dufuz / jorrit]
                   8235: * Fix Bug #13953: config-set/config-show with channel alias fail [cellog]
                   8236: * Fix Bug #13958: When a phpt tests exit() or die() xdebug coverage is not generated, patch by izi (David Jean Louis) [izi / dufuz]
                   8237: * Fix Bug #14041: Unpredictable unit test processing sequence [dufuz]
                   8238: * Fix Bug #14140: Strict warning not suppressed in the shutdown function [dufuz]
                   8239: * Fix Bug #14210: pear list -ia brings warnings [dufuz]
                   8240: * Fix Bug #14274: PEAR packager mangles package.xml encoding, then complains about it [dufuz]
                   8241: * Fix Bug #14287: cannot upgrade from stable to beta via -beta when config is set to stable [dufuz]
                   8242: * Fix Bug #14300: Package files themselves can not be served over https [dufuz / initial patch by Martin Roos]
                   8243: * Fix Bug #14437: openbasedir warning when loading config [dufuz]
                   8244: * Fix Bug #14558: PackageFile.php creates tmp directory outside configured temp_dir [cweiske]
                   8245: * Fix Bug #14947: downloadHttp() is missing Host part of the HTTP Request when using Proxy [ifeghali]
                   8246: * Fix Bug #14977: PEAR/Frontend.php doesn&apos;t require_once PEAR.php [dufuz]
                   8247: * Fix Bug #15750: Unreachable code in PEAR_Downloader [dufuz]
                   8248: * Fix Bug #15979: Package files incorrectly removed when splitting a package into multiple pkgs [dufuz]
                   8249: * Fix Bug #15914: pear upgrade installs different version if desired version not found [dufuz]
                   8250: 
                   8251: NOTE!
                   8252: Functions that have been deprecated for 3+ years in PEAR_Common, please take a moment
                   8253: to migrate over to one of the alternatives that have ben provided:
                   8254: * PEAR_Common-&gt;downloadHttp (use PEAR_Downloader-&gt;downloadHttp instead)
                   8255: * PEAR_Common-&gt;infoFromTgzFile (use PEAR_PackageFile-&gt;fromTgzFile instead)
                   8256: * PEAR_Common-&gt;infoFromDescriptionFile (use PEAR_PackageFile-&gt;fromPackageFile instead)
                   8257: * PEAR_Common-&gt;infoFromString (use PEAR_PackageFile-&gt;fromXmlstring instead)
                   8258: * PEAR_Common-&gt;infoFromArray (use PEAR_PackageFile-&gt;fromAnyFile instead)
                   8259: * PEAR_Common-&gt;xmlFromInfo (use a PEAR_PackageFile_v* object&apos;s generator instead)
                   8260: * PEAR_Common-&gt;validatePackageInfo (use the validation of PEAR_PackageFile objects)
                   8261: * PEAR_Common-&gt;analyzeSourceCode (use a PEAR_PackageFile_v* object instead)
                   8262: * PEAR_Common-&gt;detectDependencies (use PEAR_Downloader_Package-&gt;detectDependencies instead)
                   8263: * PEAR_Common-&gt;buildProvidesArray (use PEAR_PackageFile_v1-&gt;_buildProvidesArray or
                   8264:   PEAR_PackageFile_v2_Validator-&gt;_buildProvidesArray)
                   8265: 
                   8266: PHP 4.4 and 5.1.6 are now the minimum PHP requirements, for brave souls
                   8267: pear upgrade -f PEAR will allow people with lower versions
                   8268: to upgrade to this release but no guarantees will be made that it will work properly.
                   8269: 
                   8270: Support for XML RPC channels has been dropped - The only ones that used it
                   8271: (pear.php.net and pecl.php.net) have used the REST interface for years now.
                   8272: SOAP support also removed as it was only proof of concept.
                   8273: 
                   8274: Move codebase from the PHP License to New BSD 2 clause license
                   8275:    </notes>
                   8276:   </release>
                   8277:   <release>
                   8278:    <date>2009-03-27</date>
                   8279:    <version>
                   8280:     <release>1.8.0RC1</release>
                   8281:     <api>1.8.0</api>
                   8282:    </version>
                   8283:    <stability>
                   8284:     <release>beta</release>
                   8285:     <api>stable</api>
                   8286:    </stability>
                   8287:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8288:    <notes>
                   8289: * Fix Bug #14331: pear cvstag only works from inside the package directory [dufuz]
                   8290: * Fix Bug #16045: E_Notice: Undefined index: channel in PEAR/DependencyDB.php [dufuz]
                   8291: 
                   8292: * Implemented Request #11230: better error message when mirror not in channel.xml file [dufuz]
                   8293: * Implemented Request #13150: Add support for following HTTP 302 redirects [dufuz]
                   8294:    </notes>
                   8295:   </release>
                   8296:   <release>
                   8297:    <date>2009-04-10</date>
                   8298:    <version>
                   8299:     <release>1.8.0</release>
                   8300:     <api>1.8.0</api>
                   8301:    </version>
                   8302:    <stability>
                   8303:     <release>stable</release>
                   8304:     <api>stable</api>
                   8305:    </stability>
                   8306:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8307:    <notes>
                   8308: Changes since RC1:
                   8309:   * Fix Bug #14792: Bad md5sum for files with replaced content [dufuz]
                   8310:   * Fix Bug #16057:-r is limited to 4 directories in depth [dufuz]
                   8311:   * Fix Bug #16077: PEAR5::getStaticProperty does not return a reference to the property [dufuz]
                   8312: 
                   8313:   Remove custom XML_Util class in favor of using upstream XML_Util package as dependency
                   8314: 
                   8315: RC1 Release Notes:
                   8316:   * Fix Bug #14331: pear cvstag only works from inside the package directory [dufuz]
                   8317:   * Fix Bug #16045: E_Notice: Undefined index: channel in PEAR/DependencyDB.php [dufuz]
                   8318: 
                   8319:   * Implemented Request #11230: better error message when mirror not in channel.xml file [dufuz]
                   8320:   * Implemented Request #13150: Add support for following HTTP 302 redirects [dufuz]
                   8321: 
                   8322: Alpha1 Release Notes:
                   8323:   * Implement Request #10373: if pref_state=stable and installed package=beta, allow up to latest beta version [dufuz]
                   8324:   * Implement Request #10581: login / logout should map to channel-login / channel-logout [dufuz]
                   8325:   * Implement Request #10825: Only display the &quot;invalid or missing package file&quot;-error if it makes sense [dufuz]
                   8326:   * Implement Request #11170: script to generate Command/[command].xml [dufuz]
                   8327:   * Implement Request #11176: improve channel ... has updated its protocols message [dufuz]
                   8328:   * Implement Request #12706: pear list -a hard to read [dufuz]
                   8329:   * Implement Request #11353: upgrade-all and upgrade commands to upgrade within the same stability level [dufuz]
                   8330:   * Implement Request #13015: Add https discovery for channel.xml [dufuz / initial patch by Martin Roos]
                   8331:   * Implement Request #13927: install-pear.php should have option to set www_dir [timj]
                   8332:   * Implement Request #14324: Make the pear install command behave similar to apt-get [dufuz]
                   8333:   * Implement Request #14325: make pear upgrade with no params behave like pear upgrade-all [dufuz]
                   8334:     - upgrade-all can be considered deprecated in favor of calling upgrade with no parameters to replicate
                   8335:       better what other package managers are doing. upgrade-all will still work as intended.
                   8336:   * Implement Request #14504: add a channel parameter support to the upgrade function [dufuz]
                   8337:     - Options -c ezc and --channel=ezc got added to upgrade and upgrade-all to allow for
                   8338:       channel specific upgrades
                   8339:   * Implement Request #14556: install-pear-nozlib.phar should get download_dir config and other options [cweiske]
                   8340:   * Implement Request #15566: Add doc.php.net as a default channel [dufuz / saltybeagle]
                   8341: 
                   8342:   * Fix PHP Bug #43857: --program-suffix not always reflected everywhere [cellog]
                   8343:   * Fix PHP Bug #47323: strotime warnings in make install [dufuz]
                   8344: 
                   8345:   * Fix Bug #13908: pear info command and maintainers inactive not mentioned [dufuz]
                   8346:   * Fix Bug #13926: install-pear.php does not set cfg_dir if -d option set with no -c option [timj]
                   8347:   * Fix Bug #13943: tests fail when php.exe path contains spaces [dufuz / jorrit]
                   8348:   * Fix Bug #13953: config-set/config-show with channel alias fail [cellog]
                   8349:   * Fix Bug #13958: When a phpt tests exit() or die() xdebug coverage is not generated, patch by izi (David Jean Louis) [izi / dufuz]
                   8350:   * Fix Bug #14041: Unpredictable unit test processing sequence [dufuz]
                   8351:   * Fix Bug #14140: Strict warning not suppressed in the shutdown function [dufuz]
                   8352:   * Fix Bug #14210: pear list -ia brings warnings [dufuz]
                   8353:   * Fix Bug #14274: PEAR packager mangles package.xml encoding, then complains about it [dufuz]
                   8354:   * Fix Bug #14287: cannot upgrade from stable to beta via -beta when config is set to stable [dufuz]
                   8355:   * Fix Bug #14300: Package files themselves can not be served over https [dufuz / initial patch by Martin Roos]
                   8356:   * Fix Bug #14437: openbasedir warning when loading config [dufuz]
                   8357:   * Fix Bug #14558: PackageFile.php creates tmp directory outside configured temp_dir [cweiske]
                   8358:   * Fix Bug #14947: downloadHttp() is missing Host part of the HTTP Request when using Proxy [ifeghali]
                   8359:   * Fix Bug #14977: PEAR/Frontend.php doesn&apos;t require_once PEAR.php [dufuz]
                   8360:   * Fix Bug #15750: Unreachable code in PEAR_Downloader [dufuz]
                   8361:   * Fix Bug #15979: Package files incorrectly removed when splitting a package into multiple pkgs [dufuz]
                   8362:   * Fix Bug #15914: pear upgrade installs different version if desired version not found [dufuz]
                   8363: 
                   8364:   NOTE!
                   8365:   Functions that have been deprecated for 3+ years in PEAR_Common, please take a moment
                   8366:   to migrate over to one of the alternatives that have ben provided:
                   8367:   * PEAR_Common-&gt;downloadHttp (use PEAR_Downloader-&gt;downloadHttp instead)
                   8368:   * PEAR_Common-&gt;infoFromTgzFile (use PEAR_PackageFile-&gt;fromTgzFile instead)
                   8369:   * PEAR_Common-&gt;infoFromDescriptionFile (use PEAR_PackageFile-&gt;fromPackageFile instead)
                   8370:   * PEAR_Common-&gt;infoFromString (use PEAR_PackageFile-&gt;fromXmlstring instead)
                   8371:   * PEAR_Common-&gt;infoFromArray (use PEAR_PackageFile-&gt;fromAnyFile instead)
                   8372:   * PEAR_Common-&gt;xmlFromInfo (use a PEAR_PackageFile_v* object&apos;s generator instead)
                   8373:   * PEAR_Common-&gt;validatePackageInfo (use the validation of PEAR_PackageFile objects)
                   8374:   * PEAR_Common-&gt;analyzeSourceCode (use a PEAR_PackageFile_v* object instead)
                   8375:   * PEAR_Common-&gt;detectDependencies (use PEAR_Downloader_Package-&gt;detectDependencies instead)
                   8376:   * PEAR_Common-&gt;buildProvidesArray (use PEAR_PackageFile_v1-&gt;_buildProvidesArray or
                   8377:     PEAR_PackageFile_v2_Validator-&gt;_buildProvidesArray)
                   8378: 
                   8379:   PHP 4.4 and 5.1.6 are now the minimum PHP requirements, for brave souls
                   8380:   pear upgrade -f PEAR will allow people with lower versions
                   8381:   to upgrade to this release but no guarantees will be made that it will work properly.
                   8382: 
                   8383:   Support for XML RPC channels has been dropped - The only ones that used it
                   8384:   (pear.php.net and pecl.php.net) have used the REST interface for years now.
                   8385:   SOAP support also removed as it was only proof of concept.
                   8386: 
                   8387:   Move codebase from the PHP License to New BSD 2 clause license
                   8388:    </notes>
                   8389:   </release>
                   8390:   <release>
                   8391:    <date>2009-04-15</date>
                   8392:    <version>
                   8393:     <release>1.8.1</release>
                   8394:     <api>1.8.1</api>
                   8395:    </version>
                   8396:    <stability>
                   8397:     <release>stable</release>
                   8398:     <api>stable</api>
                   8399:    </stability>
                   8400:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8401:    <notes>
                   8402: * Fix Bug #16099       PEAR crash on PHP4 (parse error) [dufuz]
                   8403:    </notes>
                   8404:   </release>
                   8405:   <release>
                   8406:    <date>2009-08-18</date>
                   8407:    <version>
                   8408:     <release>1.9.0RC1</release>
                   8409:     <api>1.9.0RC1</api>
                   8410:    </version>
                   8411:    <stability>
                   8412:     <release>beta</release>
                   8413:     <api>stable</api>
                   8414:    </stability>
                   8415:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8416:    <notes>
                   8417: * Implement Request #16213: add alias to list-channels output [dufuz]
                   8418: * Implement Request #16378: pear svntag [dufuz]
                   8419: * Implement Request #16386: PEAR_Config::remove() does not support specifying a channel [timj]
                   8420: * Implement Request #16396: package-dependencies should allow package names [dufuz]
                   8421: 
                   8422: * Fix Bug #11181: pear requests channel.xml from main server instead from mirror [dufuz]
                   8423: * Fix Bug #14493: pear install --offline doesn&apos;t print out errors [dufuz]
                   8424: * Fix Bug #11348: pear package-dependencies isn&apos;t well explained [dufuz]
                   8425: * Fix Bug #16108: PEAR_PackageFile_Generator_v2 PHP4 parse error when running upgrade-all [dufuz]
                   8426: * Fix Bug #16113: Installing certain packages fails due incorrect encoding handling [dufuz]
                   8427: * Fix Bug #16122: PEAR RunTest failed to run as expected [dufuz]
                   8428: * Fix Bug #16366: compiling 5.2.10 leads to non-functioning pear [dufuz]
                   8429: * Fix Bug #16387: channel-logout does not support logging out from a non-default channel [timj]
                   8430: * Fix Bug #16444: Setting preferred mirror fails [dufuz]
                   8431: * Fix the shutdown functions where a index might not exist and thus raise a notice [derick]
                   8432:    </notes>
                   8433:   </release>
                   8434:   <release>
                   8435:    <date>2009-08-20</date>
                   8436:    <version>
                   8437:     <release>1.9.0RC2</release>
                   8438:     <api>1.9.0RC2</api>
                   8439:    </version>
                   8440:    <stability>
                   8441:     <release>beta</release>
                   8442:     <api>stable</api>
                   8443:    </stability>
                   8444:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8445:    <notes>
                   8446: * REST 1.4 file was occasionally being included but REST 1.4 is not intended for this release cycle [dufuz]
                   8447:    </notes>
                   8448:   </release>
                   8449:   <release>
                   8450:    <date>2009-08-21</date>
                   8451:    <version>
                   8452:     <release>1.9.0RC3</release>
                   8453:     <api>1.9.0RC3</api>
                   8454:    </version>
                   8455:    <stability>
                   8456:     <release>beta</release>
                   8457:     <api>stable</api>
                   8458:    </stability>
                   8459:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8460:    <notes>
                   8461: * Improved svntag support to handle packages like PEAR it self [dufuz]
                   8462:    </notes>
                   8463:   </release>
                   8464:   <release>
                   8465:    <date>2009-08-23</date>
                   8466:    <version>
                   8467:     <release>1.9.0RC4</release>
                   8468:     <api>1.9.0RC4</api>
                   8469:    </version>
                   8470:    <stability>
                   8471:     <release>beta</release>
                   8472:     <api>stable</api>
                   8473:    </stability>
                   8474:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8475:    <notes>
                   8476: * Fixed a problem where the original channel could not be set as a preferred_mirror again [dufuz]
                   8477: * Make sure channel aliases can&apos;t be made to start with - [dufuz]
                   8478: * Output issues with pear search [dufuz]
                   8479: * Fixed couple of stray notices [dufuz]
                   8480:    </notes>
                   8481:   </release>
                   8482:   <release>
                   8483:    <date>2009-09-03</date>
                   8484:    <version>
                   8485:     <release>1.9.0</release>
                   8486:     <api>1.9.0</api>
                   8487:    </version>
                   8488:    <stability>
                   8489:     <release>stable</release>
                   8490:     <api>stable</api>
                   8491:    </stability>
                   8492:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8493:    <notes>
                   8494: * Fix  Bug #16547: The phar for PEAR installer uses ereg() which is deprecated [dufuz]
                   8495:    </notes>
                   8496:   </release>
                   8497:   <release>
                   8498:    <date>2010-05-26</date>
                   8499:    <version>
                   8500:     <release>1.9.1</release>
                   8501:     <api>1.9.1</api>
                   8502:    </version>
                   8503:    <stability>
                   8504:     <release>stable</release>
                   8505:     <api>stable</api>
                   8506:    </stability>
                   8507:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8508:    <notes>
                   8509: * svntag improvements, tag package files passed into the command and better directory checks [dufuz]
                   8510: * rely on Structures_Graph minimum version instead of recommended version [saltybeagle]
                   8511: * Fix Bug #12613: running go-pear.phar from C:\ fails [dufuz]
                   8512: * Fix Bug #14841: Installing pear into directory with space fails [dufuz]
                   8513: * Fix Bug #16644: pear.bat returns syntax error when parenthesis are in install path. [dufuz] [patch by bwaters (Bryan Waters)]
                   8514: * Fix Bug #16767: Use of Depreciated HTML Attributes in the Exception class [dufuz] [patch by fuhrysteve (Stephen J. Fuhry)]
                   8515: * Fix Bug #16864: &quot;pear list-upgrades -i&quot; issues E_WARNINGS [dufuz] [patch by rquadling (Richard Quadling)]
                   8516: * Fix Bug #17220: command `pear help` outputs to stderr instead of stdout [dufuz]
                   8517: * Fix Bug #17234: channel-discover adds port to HTTP Host header [dufuz]
                   8518: * Fix Bug #17292: Code Coverage in PEAR_RunTest does not work with namespaces [sebastian]
                   8519: * Fix Bug #17359: loadExtension() fails over missing dl() when used in multithread env [dufuz]
                   8520: * Fix Bug #17378: pear info $package fails if directory with that name exists [dufuz]
                   8521:    </notes>
                   8522:   </release>
                   8523:   <release>
                   8524:    <date>2011-02-28</date>
                   8525:    <time>18:30:00</time>
                   8526:    <version>
                   8527:     <release>1.9.2</release>
                   8528:     <api>1.9.2</api>
                   8529:    </version>
                   8530:    <stability>
                   8531:     <release>stable</release>
                   8532:     <api>stable</api>
                   8533:    </stability>
                   8534:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8535:    <notes>
                   8536: Important! This is a security fix release. The advisory can be found at
                   8537: http://pear.php.net/advisory-20110228.txt
                   8538: 
                   8539:     Bugs:
                   8540:     * Fixed Bug #17463: Regression: On Windows, svntag [patch by doconnor]
                   8541:     * Fixed Bug #17641: pecl-list doesn&apos;t sort packages by name [dufuz]
                   8542:     * Fixed Bug #17781: invalid argument warning on foreach due to an empty optional dependencie [dufuz]
                   8543:     * Fixed Bug #17801: PEAR run-tests wrongly detects php-cgi [patch by David Jean Louis (izi)]
                   8544:     * Fixed Bug #17839: pear svntag does not tag package.xml file [dufuz]
                   8545:     * Fixed Bug #17986: PEAR Installer cannot handle files moved between packages [dufuz]
                   8546:     * Fixed Bug #17997: Strange output if directories are not writeable [dufuz]
                   8547:     * Fixed Bug #18001: PEAR/RunTest coverage fails [dufuz]
                   8548:     * Fixed Bug #18056 [SECURITY]: Symlink attack in PEAR install [dufuz]
                   8549:     * Fixed Bug #18218: &quot;pear package&quot; does not allow the use of late static binding [dufuz and Christer Edvartsen]
                   8550:     * Fixed Bug #18238: Wrong return code from &quot;pear help&quot; [till]
                   8551:     * Fixed Bug #18308: Broken error message about missing channel validator [yunosh]
                   8552: 
                   8553:     This feature is implemented as a result of #18056
                   8554:     * Implemented Request #16648: Use TMPDIR for builds instead of /var/tmp [dufuz]
                   8555:    </notes>
                   8556:   </release>
                   8557:   <release>
                   8558:    <date>2011-06-04</date>
                   8559:    <time>15:30:00</time>
                   8560:    <version>
                   8561:     <release>1.9.3</release>
                   8562:     <api>1.9.2</api>
                   8563:    </version>
                   8564:    <stability>
                   8565:     <release>stable</release>
                   8566:     <api>stable</api>
                   8567:    </stability>
                   8568:    <license uri="http://opensource.org/licenses/bsd-license.php">New BSD License</license>
                   8569:    <notes>
                   8570: * Fixed Bug #17744: Empty changelog causes fatal error in setChangelogentry [dufuz]
                   8571: * Fixed Bug #18340: raiseErro typo [doconnor]
                   8572: * Fixed Bug #18349: package.xml version not recognized when single quoted [dufuz]
                   8573: * Fixed Bug #18364: date.timezone errors for sh/bat files when TZ is not set in php.ini [dufuz]
                   8574: * Fixed Bug #18388: Parentheses error in REST.php line 232 [dufuz]
                   8575: * Fixed Bug #18428: invalid preg_match patterns [glen]
                   8576: * Fixed Bug #18486: REST/10.php does not check error condition [dufuz]
                   8577: * Fixed a problem in RunTest and code coverage. Correctly register the
                   8578:   code coverage shutdown function in case we are inside a namespace. [sebastian]
                   8579: * Fixed a bug with extensions not providing their config.m4 and co in the root directory of
                   8580:   their pecl package but rather in a sub directory, such as xhprof. [dufuz]
                   8581:    </notes>
                   8582:   </release>
                   8583:  </changelog>
                   8584: </package>
1.1.1.2 ! misho    8585: PEAR-1.9.4/OS/Guess.php0000644000076500000240000002463411605156614013365 0ustar  helgistaff<?php
1.1       misho    8586: /**
                   8587:  * The OS_Guess class
                   8588:  *
                   8589:  * PHP versions 4 and 5
                   8590:  *
                   8591:  * @category   pear
                   8592:  * @package    PEAR
                   8593:  * @author     Stig Bakken <ssb@php.net>
                   8594:  * @author     Gregory Beaver <cellog@php.net>
                   8595:  * @copyright  1997-2009 The Authors
                   8596:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   8597:  * @version    CVS: $Id: Guess.php 313023 2011-07-06 19:17:11Z dufuz $
                   8598:  * @link       http://pear.php.net/package/PEAR
                   8599:  * @since      File available since PEAR 0.1
                   8600:  */
                   8601: 
                   8602: // {{{ uname examples
                   8603: 
                   8604: // php_uname() without args returns the same as 'uname -a', or a PHP-custom
                   8605: // string for Windows.
                   8606: // PHP versions prior to 4.3 return the uname of the host where PHP was built,
                   8607: // as of 4.3 it returns the uname of the host running the PHP code.
                   8608: //
                   8609: // PC RedHat Linux 7.1:
                   8610: // Linux host.example.com 2.4.2-2 #1 Sun Apr 8 20:41:30 EDT 2001 i686 unknown
                   8611: //
                   8612: // PC Debian Potato:
                   8613: // Linux host 2.4.17 #2 SMP Tue Feb 12 15:10:04 CET 2002 i686 unknown
                   8614: //
                   8615: // PC FreeBSD 3.3:
                   8616: // FreeBSD host.example.com 3.3-STABLE FreeBSD 3.3-STABLE #0: Mon Feb 21 00:42:31 CET 2000     root@example.com:/usr/src/sys/compile/CONFIG  i386
                   8617: //
                   8618: // PC FreeBSD 4.3:
                   8619: // FreeBSD host.example.com 4.3-RELEASE FreeBSD 4.3-RELEASE #1: Mon Jun 25 11:19:43 EDT 2001     root@example.com:/usr/src/sys/compile/CONFIG  i386
                   8620: //
                   8621: // PC FreeBSD 4.5:
                   8622: // FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb  6 23:59:23 CET 2002     root@example.com:/usr/src/sys/compile/CONFIG  i386
                   8623: //
                   8624: // PC FreeBSD 4.5 w/uname from GNU shellutils:
                   8625: // FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb  i386 unknown
                   8626: //
                   8627: // HP 9000/712 HP-UX 10:
                   8628: // HP-UX iq B.10.10 A 9000/712 2008429113 two-user license
                   8629: //
                   8630: // HP 9000/712 HP-UX 10 w/uname from GNU shellutils:
                   8631: // HP-UX host B.10.10 A 9000/712 unknown
                   8632: //
                   8633: // IBM RS6000/550 AIX 4.3:
                   8634: // AIX host 3 4 000003531C00
                   8635: //
                   8636: // AIX 4.3 w/uname from GNU shellutils:
                   8637: // AIX host 3 4 000003531C00 unknown
                   8638: //
                   8639: // SGI Onyx IRIX 6.5 w/uname from GNU shellutils:
                   8640: // IRIX64 host 6.5 01091820 IP19 mips
                   8641: //
                   8642: // SGI Onyx IRIX 6.5:
                   8643: // IRIX64 host 6.5 01091820 IP19
                   8644: //
                   8645: // SparcStation 20 Solaris 8 w/uname from GNU shellutils:
                   8646: // SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc
                   8647: //
                   8648: // SparcStation 20 Solaris 8:
                   8649: // SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc SUNW,SPARCstation-20
                   8650: //
                   8651: // Mac OS X (Darwin)
                   8652: // Darwin home-eden.local 7.5.0 Darwin Kernel Version 7.5.0: Thu Aug  5 19:26:16 PDT 2004; root:xnu/xnu-517.7.21.obj~3/RELEASE_PPC  Power Macintosh
                   8653: //
                   8654: // Mac OS X early versions
                   8655: //
                   8656: 
                   8657: // }}}
                   8658: 
                   8659: /* TODO:
                   8660:  * - define endianness, to allow matchSignature("bigend") etc.
                   8661:  */
                   8662: 
                   8663: /**
                   8664:  * Retrieves information about the current operating system
                   8665:  *
                   8666:  * This class uses php_uname() to grok information about the current OS
                   8667:  *
                   8668:  * @category   pear
                   8669:  * @package    PEAR
                   8670:  * @author     Stig Bakken <ssb@php.net>
                   8671:  * @author     Gregory Beaver <cellog@php.net>
                   8672:  * @copyright  1997-2009 The Authors
                   8673:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   8674:  * @version    Release: 1.9.4
                   8675:  * @link       http://pear.php.net/package/PEAR
                   8676:  * @since      Class available since Release 0.1
                   8677:  */
                   8678: class OS_Guess
                   8679: {
                   8680:     var $sysname;
                   8681:     var $nodename;
                   8682:     var $cpu;
                   8683:     var $release;
                   8684:     var $extra;
                   8685: 
                   8686:     function OS_Guess($uname = null)
                   8687:     {
                   8688:         list($this->sysname,
                   8689:              $this->release,
                   8690:              $this->cpu,
                   8691:              $this->extra,
                   8692:              $this->nodename) = $this->parseSignature($uname);
                   8693:     }
                   8694: 
                   8695:     function parseSignature($uname = null)
                   8696:     {
                   8697:         static $sysmap = array(
                   8698:             'HP-UX' => 'hpux',
                   8699:             'IRIX64' => 'irix',
                   8700:         );
                   8701:         static $cpumap = array(
                   8702:             'i586' => 'i386',
                   8703:             'i686' => 'i386',
                   8704:             'ppc' => 'powerpc',
                   8705:         );
                   8706:         if ($uname === null) {
                   8707:             $uname = php_uname();
                   8708:         }
                   8709:         $parts = preg_split('/\s+/', trim($uname));
                   8710:         $n = count($parts);
                   8711: 
                   8712:         $release  = $machine = $cpu = '';
                   8713:         $sysname  = $parts[0];
                   8714:         $nodename = $parts[1];
                   8715:         $cpu      = $parts[$n-1];
                   8716:         $extra = '';
                   8717:         if ($cpu == 'unknown') {
                   8718:             $cpu = $parts[$n - 2];
                   8719:         }
                   8720: 
                   8721:         switch ($sysname) {
                   8722:             case 'AIX' :
                   8723:                 $release = "$parts[3].$parts[2]";
                   8724:                 break;
                   8725:             case 'Windows' :
                   8726:                 switch ($parts[1]) {
                   8727:                     case '95/98':
                   8728:                         $release = '9x';
                   8729:                         break;
                   8730:                     default:
                   8731:                         $release = $parts[1];
                   8732:                         break;
                   8733:                 }
                   8734:                 $cpu = 'i386';
                   8735:                 break;
                   8736:             case 'Linux' :
                   8737:                 $extra = $this->_detectGlibcVersion();
                   8738:                 // use only the first two digits from the kernel version
                   8739:                 $release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]);
                   8740:                 break;
                   8741:             case 'Mac' :
                   8742:                 $sysname = 'darwin';
                   8743:                 $nodename = $parts[2];
                   8744:                 $release = $parts[3];
                   8745:                 if ($cpu == 'Macintosh') {
                   8746:                     if ($parts[$n - 2] == 'Power') {
                   8747:                         $cpu = 'powerpc';
                   8748:                     }
                   8749:                 }
                   8750:                 break;
                   8751:             case 'Darwin' :
                   8752:                 if ($cpu == 'Macintosh') {
                   8753:                     if ($parts[$n - 2] == 'Power') {
                   8754:                         $cpu = 'powerpc';
                   8755:                     }
                   8756:                 }
                   8757:                 $release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]);
                   8758:                 break;
                   8759:             default:
                   8760:                 $release = preg_replace('/-.*/', '', $parts[2]);
                   8761:                 break;
                   8762:         }
                   8763: 
                   8764:         if (isset($sysmap[$sysname])) {
                   8765:             $sysname = $sysmap[$sysname];
                   8766:         } else {
                   8767:             $sysname = strtolower($sysname);
                   8768:         }
                   8769:         if (isset($cpumap[$cpu])) {
                   8770:             $cpu = $cpumap[$cpu];
                   8771:         }
                   8772:         return array($sysname, $release, $cpu, $extra, $nodename);
                   8773:     }
                   8774: 
                   8775:     function _detectGlibcVersion()
                   8776:     {
                   8777:         static $glibc = false;
                   8778:         if ($glibc !== false) {
                   8779:             return $glibc; // no need to run this multiple times
                   8780:         }
                   8781:         $major = $minor = 0;
                   8782:         include_once "System.php";
                   8783:         // Use glibc's <features.h> header file to
                   8784:         // get major and minor version number:
                   8785:         if (@file_exists('/usr/include/features.h') &&
                   8786:               @is_readable('/usr/include/features.h')) {
                   8787:             if (!@file_exists('/usr/bin/cpp') || !@is_executable('/usr/bin/cpp')) {
                   8788:                 $features_file = fopen('/usr/include/features.h', 'rb');
                   8789:                 while (!feof($features_file)) {
                   8790:                     $line = fgets($features_file, 8192);
                   8791:                     if (!$line || (strpos($line, '#define') === false)) {
                   8792:                         continue;
                   8793:                     }
                   8794:                     if (strpos($line, '__GLIBC__')) {
                   8795:                         // major version number #define __GLIBC__ version
                   8796:                         $line = preg_split('/\s+/', $line);
                   8797:                         $glibc_major = trim($line[2]);
                   8798:                         if (isset($glibc_minor)) {
                   8799:                             break;
                   8800:                         }
                   8801:                         continue;
                   8802:                     }
                   8803: 
                   8804:                     if (strpos($line, '__GLIBC_MINOR__'))  {
                   8805:                         // got the minor version number
                   8806:                         // #define __GLIBC_MINOR__ version
                   8807:                         $line = preg_split('/\s+/', $line);
                   8808:                         $glibc_minor = trim($line[2]);
                   8809:                         if (isset($glibc_major)) {
                   8810:                             break;
                   8811:                         }
                   8812:                         continue;
                   8813:                     }
                   8814:                 }
                   8815:                 fclose($features_file);
                   8816:                 if (!isset($glibc_major) || !isset($glibc_minor)) {
                   8817:                     return $glibc = '';
                   8818:                 }
                   8819:                 return $glibc = 'glibc' . trim($glibc_major) . "." . trim($glibc_minor) ;
                   8820:             } // no cpp
                   8821: 
                   8822:             $tmpfile = System::mktemp("glibctest");
                   8823:             $fp = fopen($tmpfile, "w");
                   8824:             fwrite($fp, "#include <features.h>\n__GLIBC__ __GLIBC_MINOR__\n");
                   8825:             fclose($fp);
                   8826:             $cpp = popen("/usr/bin/cpp $tmpfile", "r");
                   8827:             while ($line = fgets($cpp, 1024)) {
                   8828:                 if ($line{0} == '#' || trim($line) == '') {
                   8829:                     continue;
                   8830:                 }
                   8831: 
                   8832:                 if (list($major, $minor) = explode(' ', trim($line))) {
                   8833:                     break;
                   8834:                 }
                   8835:             }
                   8836:             pclose($cpp);
                   8837:             unlink($tmpfile);
                   8838:         } // features.h
                   8839: 
                   8840:         if (!($major && $minor) && @is_link('/lib/libc.so.6')) {
                   8841:             // Let's try reading the libc.so.6 symlink
                   8842:             if (preg_match('/^libc-(.*)\.so$/', basename(readlink('/lib/libc.so.6')), $matches)) {
                   8843:                 list($major, $minor) = explode('.', $matches[1]);
                   8844:             }
                   8845:         }
                   8846: 
                   8847:         if (!($major && $minor)) {
                   8848:             return $glibc = '';
                   8849:         }
                   8850: 
                   8851:         return $glibc = "glibc{$major}.{$minor}";
                   8852:     }
                   8853: 
                   8854:     function getSignature()
                   8855:     {
                   8856:         if (empty($this->extra)) {
                   8857:             return "{$this->sysname}-{$this->release}-{$this->cpu}";
                   8858:         }
                   8859:         return "{$this->sysname}-{$this->release}-{$this->cpu}-{$this->extra}";
                   8860:     }
                   8861: 
                   8862:     function getSysname()
                   8863:     {
                   8864:         return $this->sysname;
                   8865:     }
                   8866: 
                   8867:     function getNodename()
                   8868:     {
                   8869:         return $this->nodename;
                   8870:     }
                   8871: 
                   8872:     function getCpu()
                   8873:     {
                   8874:         return $this->cpu;
                   8875:     }
                   8876: 
                   8877:     function getRelease()
                   8878:     {
                   8879:         return $this->release;
                   8880:     }
                   8881: 
                   8882:     function getExtra()
                   8883:     {
                   8884:         return $this->extra;
                   8885:     }
                   8886: 
                   8887:     function matchSignature($match)
                   8888:     {
                   8889:         $fragments = is_array($match) ? $match : explode('-', $match);
                   8890:         $n = count($fragments);
                   8891:         $matches = 0;
                   8892:         if ($n > 0) {
                   8893:             $matches += $this->_matchFragment($fragments[0], $this->sysname);
                   8894:         }
                   8895:         if ($n > 1) {
                   8896:             $matches += $this->_matchFragment($fragments[1], $this->release);
                   8897:         }
                   8898:         if ($n > 2) {
                   8899:             $matches += $this->_matchFragment($fragments[2], $this->cpu);
                   8900:         }
                   8901:         if ($n > 3) {
                   8902:             $matches += $this->_matchFragment($fragments[3], $this->extra);
                   8903:         }
                   8904:         return ($matches == $n);
                   8905:     }
                   8906: 
                   8907:     function _matchFragment($fragment, $value)
                   8908:     {
                   8909:         if (strcspn($fragment, '*?') < strlen($fragment)) {
                   8910:             $reg = '/^' . str_replace(array('*', '?', '/'), array('.*', '.', '\\/'), $fragment) . '\\z/';
                   8911:             return preg_match($reg, $value);
                   8912:         }
                   8913:         return ($fragment == '*' || !strcasecmp($fragment, $value));
                   8914:     }
                   8915: 
                   8916: }
                   8917: /*
                   8918:  * Local Variables:
                   8919:  * indent-tabs-mode: nil
                   8920:  * c-basic-offset: 4
                   8921:  * End:
1.1.1.2 ! misho    8922:  */PEAR-1.9.4/PEAR/ChannelFile/Parser.php0000644000076500000240000000336211605156614016104 0ustar  helgistaff<?php
1.1       misho    8923: /**
                   8924:  * PEAR_ChannelFile_Parser for parsing channel.xml
                   8925:  *
                   8926:  * PHP versions 4 and 5
                   8927:  *
                   8928:  * @category   pear
                   8929:  * @package    PEAR
                   8930:  * @author     Greg Beaver <cellog@php.net>
                   8931:  * @copyright  1997-2009 The Authors
                   8932:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   8933:  * @version    CVS: $Id: Parser.php 313023 2011-07-06 19:17:11Z dufuz $
                   8934:  * @link       http://pear.php.net/package/PEAR
                   8935:  * @since      File available since Release 1.4.0a1
                   8936:  */
                   8937: 
                   8938: /**
                   8939:  * base xml parser class
                   8940:  */
                   8941: require_once 'PEAR/XMLParser.php';
                   8942: require_once 'PEAR/ChannelFile.php';
                   8943: /**
                   8944:  * Parser for channel.xml
                   8945:  * @category   pear
                   8946:  * @package    PEAR
                   8947:  * @author     Greg Beaver <cellog@php.net>
                   8948:  * @copyright  1997-2009 The Authors
                   8949:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   8950:  * @version    Release: 1.9.4
                   8951:  * @link       http://pear.php.net/package/PEAR
                   8952:  * @since      Class available since Release 1.4.0a1
                   8953:  */
                   8954: class PEAR_ChannelFile_Parser extends PEAR_XMLParser
                   8955: {
                   8956:     var $_config;
                   8957:     var $_logger;
                   8958:     var $_registry;
                   8959: 
                   8960:     function setConfig(&$c)
                   8961:     {
                   8962:         $this->_config = &$c;
                   8963:         $this->_registry = &$c->getRegistry();
                   8964:     }
                   8965: 
                   8966:     function setLogger(&$l)
                   8967:     {
                   8968:         $this->_logger = &$l;
                   8969:     }
                   8970: 
                   8971:     function parse($data, $file)
                   8972:     {
                   8973:         if (PEAR::isError($err = parent::parse($data, $file))) {
                   8974:             return $err;
                   8975:         }
                   8976: 
                   8977:         $ret = new PEAR_ChannelFile;
                   8978:         $ret->setConfig($this->_config);
                   8979:         if (isset($this->_logger)) {
                   8980:             $ret->setLogger($this->_logger);
                   8981:         }
                   8982: 
                   8983:         $ret->fromArray($this->_unserializedData);
                   8984:         // make sure the filelist is in the easy to read format needed
                   8985:         $ret->flattenFilelist();
                   8986:         $ret->setPackagefile($file, $archive);
                   8987:         return $ret;
                   8988:     }
1.1.1.2 ! misho    8989: }PEAR-1.9.4/PEAR/Command/Auth.xml0000644000076500000240000000231411605156614014764 0ustar  helgistaff<commands version="1.0">
1.1       misho    8990:  <login>
                   8991:   <summary>Connects and authenticates to remote server [Deprecated in favor of channel-login]</summary>
                   8992:   <function>doLogin</function>
                   8993:   <shortcut>li</shortcut>
                   8994:   <options />
                   8995:   <doc>&lt;channel name&gt;
                   8996: WARNING: This function is deprecated in favor of using channel-login
                   8997: 
                   8998: Log in to a remote channel server.  If &lt;channel name&gt; is not supplied,
                   8999: the default channel is used. To use remote functions in the installer
                   9000: that require any kind of privileges, you need to log in first.  The
                   9001: username and password you enter here will be stored in your per-user
                   9002: PEAR configuration (~/.pearrc on Unix-like systems).  After logging
                   9003: in, your username and password will be sent along in subsequent
                   9004: operations on the remote server.</doc>
                   9005:  </login>
                   9006:  <logout>
                   9007:   <summary>Logs out from the remote server [Deprecated in favor of channel-logout]</summary>
                   9008:   <function>doLogout</function>
                   9009:   <shortcut>lo</shortcut>
                   9010:   <options />
                   9011:   <doc>
                   9012: WARNING: This function is deprecated in favor of using channel-logout
                   9013: 
                   9014: Logs out from the remote server.  This command does not actually
                   9015: connect to the remote server, it only deletes the stored username and
                   9016: password from your user configuration.</doc>
                   9017:  </logout>
1.1.1.2 ! misho    9018: </commands>PEAR-1.9.4/PEAR/Command/Auth.php0000644000076500000240000000513611605156614014760 0ustar  helgistaff<?php
1.1       misho    9019: /**
                   9020:  * PEAR_Command_Auth (login, logout commands)
                   9021:  *
                   9022:  * PHP versions 4 and 5
                   9023:  *
                   9024:  * @category   pear
                   9025:  * @package    PEAR
                   9026:  * @author     Stig Bakken <ssb@php.net>
                   9027:  * @author     Greg Beaver <cellog@php.net>
                   9028:  * @copyright  1997-2009 The Authors
                   9029:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   9030:  * @version    CVS: $Id: Auth.php 313023 2011-07-06 19:17:11Z dufuz $
                   9031:  * @link       http://pear.php.net/package/PEAR
                   9032:  * @since      File available since Release 0.1
                   9033:  * @deprecated since 1.8.0alpha1
                   9034:  */
                   9035: 
                   9036: /**
                   9037:  * base class
                   9038:  */
                   9039: require_once 'PEAR/Command/Channels.php';
                   9040: 
                   9041: /**
                   9042:  * PEAR commands for login/logout
                   9043:  *
                   9044:  * @category   pear
                   9045:  * @package    PEAR
                   9046:  * @author     Stig Bakken <ssb@php.net>
                   9047:  * @author     Greg Beaver <cellog@php.net>
                   9048:  * @copyright  1997-2009 The Authors
                   9049:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   9050:  * @version    Release: 1.9.4
                   9051:  * @link       http://pear.php.net/package/PEAR
                   9052:  * @since      Class available since Release 0.1
                   9053:  * @deprecated since 1.8.0alpha1
                   9054:  */
                   9055: class PEAR_Command_Auth extends PEAR_Command_Channels
                   9056: {
                   9057:     var $commands = array(
                   9058:         'login' => array(
                   9059:             'summary' => 'Connects and authenticates to remote server [Deprecated in favor of channel-login]',
                   9060:             'shortcut' => 'li',
                   9061:             'function' => 'doLogin',
                   9062:             'options' => array(),
                   9063:             'doc' => '<channel name>
                   9064: WARNING: This function is deprecated in favor of using channel-login
                   9065: 
                   9066: Log in to a remote channel server.  If <channel name> is not supplied,
                   9067: the default channel is used. To use remote functions in the installer
                   9068: that require any kind of privileges, you need to log in first.  The
                   9069: username and password you enter here will be stored in your per-user
                   9070: PEAR configuration (~/.pearrc on Unix-like systems).  After logging
                   9071: in, your username and password will be sent along in subsequent
                   9072: operations on the remote server.',
                   9073:             ),
                   9074:         'logout' => array(
                   9075:             'summary' => 'Logs out from the remote server [Deprecated in favor of channel-logout]',
                   9076:             'shortcut' => 'lo',
                   9077:             'function' => 'doLogout',
                   9078:             'options' => array(),
                   9079:             'doc' => '
                   9080: WARNING: This function is deprecated in favor of using channel-logout
                   9081: 
                   9082: Logs out from the remote server.  This command does not actually
                   9083: connect to the remote server, it only deletes the stored username and
                   9084: password from your user configuration.',
                   9085:             )
                   9086: 
                   9087:         );
                   9088: 
                   9089:     /**
                   9090:      * PEAR_Command_Auth constructor.
                   9091:      *
                   9092:      * @access public
                   9093:      */
                   9094:     function PEAR_Command_Auth(&$ui, &$config)
                   9095:     {
                   9096:         parent::PEAR_Command_Channels($ui, $config);
                   9097:     }
1.1.1.2 ! misho    9098: }PEAR-1.9.4/PEAR/Command/Build.xml0000644000076500000240000000040411605156614015120 0ustar  helgistaff<commands version="1.0">
1.1       misho    9099:  <build>
                   9100:   <summary>Build an Extension From C Source</summary>
                   9101:   <function>doBuild</function>
                   9102:   <shortcut>b</shortcut>
                   9103:   <options />
                   9104:   <doc>[package.xml]
                   9105: Builds one or more extensions contained in a package.</doc>
                   9106:  </build>
1.1.1.2 ! misho    9107: </commands>PEAR-1.9.4/PEAR/Command/Build.php0000644000076500000240000000445311605156614015117 0ustar  helgistaff<?php
1.1       misho    9108: /**
                   9109:  * PEAR_Command_Auth (build command)
                   9110:  *
                   9111:  * PHP versions 4 and 5
                   9112:  *
                   9113:  * @category   pear
                   9114:  * @package    PEAR
                   9115:  * @author     Stig Bakken <ssb@php.net>
                   9116:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   9117:  * @author     Greg Beaver <cellog@php.net>
                   9118:  * @copyright  1997-2009 The Authors
                   9119:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   9120:  * @version    CVS: $Id: Build.php 313023 2011-07-06 19:17:11Z dufuz $
                   9121:  * @link       http://pear.php.net/package/PEAR
                   9122:  * @since      File available since Release 0.1
                   9123:  */
                   9124: 
                   9125: /**
                   9126:  * base class
                   9127:  */
                   9128: require_once 'PEAR/Command/Common.php';
                   9129: 
                   9130: /**
                   9131:  * PEAR commands for building extensions.
                   9132:  *
                   9133:  * @category   pear
                   9134:  * @package    PEAR
                   9135:  * @author     Stig Bakken <ssb@php.net>
                   9136:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   9137:  * @author     Greg Beaver <cellog@php.net>
                   9138:  * @copyright  1997-2009 The Authors
                   9139:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   9140:  * @version    Release: 1.9.4
                   9141:  * @link       http://pear.php.net/package/PEAR
                   9142:  * @since      Class available since Release 0.1
                   9143:  */
                   9144: class PEAR_Command_Build extends PEAR_Command_Common
                   9145: {
                   9146:     var $commands = array(
                   9147:         'build' => array(
                   9148:             'summary' => 'Build an Extension From C Source',
                   9149:             'function' => 'doBuild',
                   9150:             'shortcut' => 'b',
                   9151:             'options' => array(),
                   9152:             'doc' => '[package.xml]
                   9153: Builds one or more extensions contained in a package.'
                   9154:             ),
                   9155:         );
                   9156: 
                   9157:     /**
                   9158:      * PEAR_Command_Build constructor.
                   9159:      *
                   9160:      * @access public
                   9161:      */
                   9162:     function PEAR_Command_Build(&$ui, &$config)
                   9163:     {
                   9164:         parent::PEAR_Command_Common($ui, $config);
                   9165:     }
                   9166: 
                   9167:     function doBuild($command, $options, $params)
                   9168:     {
                   9169:         require_once 'PEAR/Builder.php';
                   9170:         if (sizeof($params) < 1) {
                   9171:             $params[0] = 'package.xml';
                   9172:         }
                   9173: 
                   9174:         $builder = &new PEAR_Builder($this->ui);
                   9175:         $this->debug = $this->config->get('verbose');
                   9176:         $err = $builder->build($params[0], array(&$this, 'buildCallback'));
                   9177:         if (PEAR::isError($err)) {
                   9178:             return $err;
                   9179:         }
                   9180: 
                   9181:         return true;
                   9182:     }
                   9183: 
                   9184:     function buildCallback($what, $data)
                   9185:     {
                   9186:         if (($what == 'cmdoutput' && $this->debug > 1) ||
                   9187:             ($what == 'output' && $this->debug > 0)) {
                   9188:             $this->ui->outputData(rtrim($data), 'build');
                   9189:         }
                   9190:     }
1.1.1.2 ! misho    9191: }PEAR-1.9.4/PEAR/Command/Channels.xml0000644000076500000240000001017211605156614015617 0ustar  helgistaff<commands version="1.0">
1.1       misho    9192:  <list-channels>
                   9193:   <summary>List Available Channels</summary>
                   9194:   <function>doList</function>
                   9195:   <shortcut>lc</shortcut>
                   9196:   <options />
                   9197:   <doc>
                   9198: List all available channels for installation.
                   9199: </doc>
                   9200:  </list-channels>
                   9201:  <update-channels>
                   9202:   <summary>Update the Channel List</summary>
                   9203:   <function>doUpdateAll</function>
                   9204:   <shortcut>uc</shortcut>
                   9205:   <options />
                   9206:   <doc>
                   9207: List all installed packages in all channels.
                   9208: </doc>
                   9209:  </update-channels>
                   9210:  <channel-delete>
                   9211:   <summary>Remove a Channel From the List</summary>
                   9212:   <function>doDelete</function>
                   9213:   <shortcut>cde</shortcut>
                   9214:   <options />
                   9215:   <doc>&lt;channel name&gt;
                   9216: Delete a channel from the registry.  You may not
                   9217: remove any channel that has installed packages.
                   9218: </doc>
                   9219:  </channel-delete>
                   9220:  <channel-add>
                   9221:   <summary>Add a Channel</summary>
                   9222:   <function>doAdd</function>
                   9223:   <shortcut>ca</shortcut>
                   9224:   <options />
                   9225:   <doc>&lt;channel.xml&gt;
                   9226: Add a private channel to the channel list.  Note that all
                   9227: public channels should be synced using &quot;update-channels&quot;.
                   9228: Parameter may be either a local file or remote URL to a
                   9229: channel.xml.
                   9230: </doc>
                   9231:  </channel-add>
                   9232:  <channel-update>
                   9233:   <summary>Update an Existing Channel</summary>
                   9234:   <function>doUpdate</function>
                   9235:   <shortcut>cu</shortcut>
                   9236:   <options>
                   9237:    <force>
                   9238:     <shortopt>f</shortopt>
                   9239:     <doc>will force download of new channel.xml if an existing channel name is used</doc>
                   9240:    </force>
                   9241:    <channel>
                   9242:     <shortopt>c</shortopt>
                   9243:     <doc>will force download of new channel.xml if an existing channel name is used</doc>
                   9244:     <arg>CHANNEL</arg>
                   9245:    </channel>
                   9246:   </options>
                   9247:   <doc>[&lt;channel.xml&gt;|&lt;channel name&gt;]
                   9248: Update a channel in the channel list directly.  Note that all
                   9249: public channels can be synced using &quot;update-channels&quot;.
                   9250: Parameter may be a local or remote channel.xml, or the name of
                   9251: an existing channel.
                   9252: </doc>
                   9253:  </channel-update>
                   9254:  <channel-info>
                   9255:   <summary>Retrieve Information on a Channel</summary>
                   9256:   <function>doInfo</function>
                   9257:   <shortcut>ci</shortcut>
                   9258:   <options />
                   9259:   <doc>&lt;package&gt;
                   9260: List the files in an installed package.
                   9261: </doc>
                   9262:  </channel-info>
                   9263:  <channel-alias>
                   9264:   <summary>Specify an alias to a channel name</summary>
                   9265:   <function>doAlias</function>
                   9266:   <shortcut>cha</shortcut>
                   9267:   <options />
                   9268:   <doc>&lt;channel&gt; &lt;alias&gt;
                   9269: Specify a specific alias to use for a channel name.
                   9270: The alias may not be an existing channel name or
                   9271: alias.
                   9272: </doc>
                   9273:  </channel-alias>
                   9274:  <channel-discover>
                   9275:   <summary>Initialize a Channel from its server</summary>
                   9276:   <function>doDiscover</function>
                   9277:   <shortcut>di</shortcut>
                   9278:   <options />
                   9279:   <doc>[&lt;channel.xml&gt;|&lt;channel name&gt;]
                   9280: Initialize a channel from its server and create a local channel.xml.
                   9281: If &lt;channel name&gt; is in the format &quot;&lt;username&gt;:&lt;password&gt;@&lt;channel&gt;&quot; then
                   9282: &lt;username&gt; and &lt;password&gt; will be set as the login username/password for
                   9283: &lt;channel&gt;. Use caution when passing the username/password in this way, as
                   9284: it may allow other users on your computer to briefly view your username/
                   9285: password via the system&#039;s process list.
                   9286: </doc>
                   9287:  </channel-discover>
                   9288:  <channel-login>
                   9289:   <summary>Connects and authenticates to remote channel server</summary>
                   9290:   <function>doLogin</function>
                   9291:   <shortcut>cli</shortcut>
                   9292:   <options />
                   9293:   <doc>&lt;channel name&gt;
                   9294: Log in to a remote channel server.  If &lt;channel name&gt; is not supplied,
                   9295: the default channel is used. To use remote functions in the installer
                   9296: that require any kind of privileges, you need to log in first.  The
                   9297: username and password you enter here will be stored in your per-user
                   9298: PEAR configuration (~/.pearrc on Unix-like systems).  After logging
                   9299: in, your username and password will be sent along in subsequent
                   9300: operations on the remote server.</doc>
                   9301:  </channel-login>
                   9302:  <channel-logout>
                   9303:   <summary>Logs out from the remote channel server</summary>
                   9304:   <function>doLogout</function>
                   9305:   <shortcut>clo</shortcut>
                   9306:   <options />
                   9307:   <doc>&lt;channel name&gt;
                   9308: Logs out from a remote channel server.  If &lt;channel name&gt; is not supplied,
                   9309: the default channel is used. This command does not actually connect to the
                   9310: remote server, it only deletes the stored username and password from your user
                   9311: configuration.</doc>
                   9312:  </channel-logout>
1.1.1.2 ! misho    9313: </commands>PEAR-1.9.4/PEAR/Command/Channels.php0000644000076500000240000010137711605156614015616 0ustar  helgistaff<?php
1.1       misho    9314: // /* vim: set expandtab tabstop=4 shiftwidth=4: */
                   9315: /**
                   9316:  * PEAR_Command_Channels (list-channels, update-channels, channel-delete, channel-add,
                   9317:  * channel-update, channel-info, channel-alias, channel-discover commands)
                   9318:  *
                   9319:  * PHP versions 4 and 5
                   9320:  *
                   9321:  * @category   pear
                   9322:  * @package    PEAR
                   9323:  * @author     Stig Bakken <ssb@php.net>
                   9324:  * @author     Greg Beaver <cellog@php.net>
                   9325:  * @copyright  1997-2009 The Authors
                   9326:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   9327:  * @version    CVS: $Id: Channels.php 313023 2011-07-06 19:17:11Z dufuz $
                   9328:  * @link       http://pear.php.net/package/PEAR
                   9329:  * @since      File available since Release 1.4.0a1
                   9330:  */
                   9331: 
                   9332: /**
                   9333:  * base class
                   9334:  */
                   9335: require_once 'PEAR/Command/Common.php';
                   9336: 
                   9337: define('PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS', -500);
                   9338: 
                   9339: /**
                   9340:  * PEAR commands for managing channels.
                   9341:  *
                   9342:  * @category   pear
                   9343:  * @package    PEAR
                   9344:  * @author     Greg Beaver <cellog@php.net>
                   9345:  * @copyright  1997-2009 The Authors
                   9346:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   9347:  * @version    Release: 1.9.4
                   9348:  * @link       http://pear.php.net/package/PEAR
                   9349:  * @since      Class available since Release 1.4.0a1
                   9350:  */
                   9351: class PEAR_Command_Channels extends PEAR_Command_Common
                   9352: {
                   9353:     var $commands = array(
                   9354:         'list-channels' => array(
                   9355:             'summary' => 'List Available Channels',
                   9356:             'function' => 'doList',
                   9357:             'shortcut' => 'lc',
                   9358:             'options' => array(),
                   9359:             'doc' => '
                   9360: List all available channels for installation.
                   9361: ',
                   9362:             ),
                   9363:         'update-channels' => array(
                   9364:             'summary' => 'Update the Channel List',
                   9365:             'function' => 'doUpdateAll',
                   9366:             'shortcut' => 'uc',
                   9367:             'options' => array(),
                   9368:             'doc' => '
                   9369: List all installed packages in all channels.
                   9370: '
                   9371:             ),
                   9372:         'channel-delete' => array(
                   9373:             'summary' => 'Remove a Channel From the List',
                   9374:             'function' => 'doDelete',
                   9375:             'shortcut' => 'cde',
                   9376:             'options' => array(),
                   9377:             'doc' => '<channel name>
                   9378: Delete a channel from the registry.  You may not
                   9379: remove any channel that has installed packages.
                   9380: '
                   9381:             ),
                   9382:         'channel-add' => array(
                   9383:             'summary' => 'Add a Channel',
                   9384:             'function' => 'doAdd',
                   9385:             'shortcut' => 'ca',
                   9386:             'options' => array(),
                   9387:             'doc' => '<channel.xml>
                   9388: Add a private channel to the channel list.  Note that all
                   9389: public channels should be synced using "update-channels".
                   9390: Parameter may be either a local file or remote URL to a
                   9391: channel.xml.
                   9392: '
                   9393:             ),
                   9394:         'channel-update' => array(
                   9395:             'summary' => 'Update an Existing Channel',
                   9396:             'function' => 'doUpdate',
                   9397:             'shortcut' => 'cu',
                   9398:             'options' => array(
                   9399:                 'force' => array(
                   9400:                     'shortopt' => 'f',
                   9401:                     'doc' => 'will force download of new channel.xml if an existing channel name is used',
                   9402:                     ),
                   9403:                 'channel' => array(
                   9404:                     'shortopt' => 'c',
                   9405:                     'arg' => 'CHANNEL',
                   9406:                     'doc' => 'will force download of new channel.xml if an existing channel name is used',
                   9407:                     ),
                   9408: ),
                   9409:             'doc' => '[<channel.xml>|<channel name>]
                   9410: Update a channel in the channel list directly.  Note that all
                   9411: public channels can be synced using "update-channels".
                   9412: Parameter may be a local or remote channel.xml, or the name of
                   9413: an existing channel.
                   9414: '
                   9415:             ),
                   9416:         'channel-info' => array(
                   9417:             'summary' => 'Retrieve Information on a Channel',
                   9418:             'function' => 'doInfo',
                   9419:             'shortcut' => 'ci',
                   9420:             'options' => array(),
                   9421:             'doc' => '<package>
                   9422: List the files in an installed package.
                   9423: '
                   9424:             ),
                   9425:         'channel-alias' => array(
                   9426:             'summary' => 'Specify an alias to a channel name',
                   9427:             'function' => 'doAlias',
                   9428:             'shortcut' => 'cha',
                   9429:             'options' => array(),
                   9430:             'doc' => '<channel> <alias>
                   9431: Specify a specific alias to use for a channel name.
                   9432: The alias may not be an existing channel name or
                   9433: alias.
                   9434: '
                   9435:             ),
                   9436:         'channel-discover' => array(
                   9437:             'summary' => 'Initialize a Channel from its server',
                   9438:             'function' => 'doDiscover',
                   9439:             'shortcut' => 'di',
                   9440:             'options' => array(),
                   9441:             'doc' => '[<channel.xml>|<channel name>]
                   9442: Initialize a channel from its server and create a local channel.xml.
                   9443: If <channel name> is in the format "<username>:<password>@<channel>" then
                   9444: <username> and <password> will be set as the login username/password for
                   9445: <channel>. Use caution when passing the username/password in this way, as
                   9446: it may allow other users on your computer to briefly view your username/
                   9447: password via the system\'s process list.
                   9448: '
                   9449:             ),
                   9450:         'channel-login' => array(
                   9451:             'summary' => 'Connects and authenticates to remote channel server',
                   9452:             'shortcut' => 'cli',
                   9453:             'function' => 'doLogin',
                   9454:             'options' => array(),
                   9455:             'doc' => '<channel name>
                   9456: Log in to a remote channel server.  If <channel name> is not supplied,
                   9457: the default channel is used. To use remote functions in the installer
                   9458: that require any kind of privileges, you need to log in first.  The
                   9459: username and password you enter here will be stored in your per-user
                   9460: PEAR configuration (~/.pearrc on Unix-like systems).  After logging
                   9461: in, your username and password will be sent along in subsequent
                   9462: operations on the remote server.',
                   9463:             ),
                   9464:         'channel-logout' => array(
                   9465:             'summary' => 'Logs out from the remote channel server',
                   9466:             'shortcut' => 'clo',
                   9467:             'function' => 'doLogout',
                   9468:             'options' => array(),
                   9469:             'doc' => '<channel name>
                   9470: Logs out from a remote channel server.  If <channel name> is not supplied,
                   9471: the default channel is used. This command does not actually connect to the
                   9472: remote server, it only deletes the stored username and password from your user
                   9473: configuration.',
                   9474:             ),
                   9475:         );
                   9476: 
                   9477:     /**
                   9478:      * PEAR_Command_Registry constructor.
                   9479:      *
                   9480:      * @access public
                   9481:      */
                   9482:     function PEAR_Command_Channels(&$ui, &$config)
                   9483:     {
                   9484:         parent::PEAR_Command_Common($ui, $config);
                   9485:     }
                   9486: 
                   9487:     function _sortChannels($a, $b)
                   9488:     {
                   9489:         return strnatcasecmp($a->getName(), $b->getName());
                   9490:     }
                   9491: 
                   9492:     function doList($command, $options, $params)
                   9493:     {
                   9494:         $reg = &$this->config->getRegistry();
                   9495:         $registered = $reg->getChannels();
                   9496:         usort($registered, array(&$this, '_sortchannels'));
                   9497:         $i = $j = 0;
                   9498:         $data = array(
                   9499:             'caption' => 'Registered Channels:',
                   9500:             'border' => true,
                   9501:             'headline' => array('Channel', 'Alias', 'Summary')
                   9502:             );
                   9503:         foreach ($registered as $channel) {
                   9504:             $data['data'][] = array($channel->getName(),
                   9505:                                     $channel->getAlias(),
                   9506:                                     $channel->getSummary());
                   9507:         }
                   9508: 
                   9509:         if (count($registered) === 0) {
                   9510:             $data = '(no registered channels)';
                   9511:         }
                   9512:         $this->ui->outputData($data, $command);
                   9513:         return true;
                   9514:     }
                   9515: 
                   9516:     function doUpdateAll($command, $options, $params)
                   9517:     {
                   9518:         $reg = &$this->config->getRegistry();
                   9519:         $channels = $reg->getChannels();
                   9520: 
                   9521:         $success = true;
                   9522:         foreach ($channels as $channel) {
                   9523:             if ($channel->getName() != '__uri') {
                   9524:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   9525:                 $err = $this->doUpdate('channel-update',
                   9526:                                           $options,
                   9527:                                           array($channel->getName()));
                   9528:                 if (PEAR::isError($err)) {
                   9529:                     $this->ui->outputData($err->getMessage(), $command);
                   9530:                     $success = false;
                   9531:                 } else {
                   9532:                     $success &= $err;
                   9533:                 }
                   9534:             }
                   9535:         }
                   9536:         return $success;
                   9537:     }
                   9538: 
                   9539:     function doInfo($command, $options, $params)
                   9540:     {
                   9541:         if (count($params) !== 1) {
                   9542:             return $this->raiseError("No channel specified");
                   9543:         }
                   9544: 
                   9545:         $reg     = &$this->config->getRegistry();
                   9546:         $channel = strtolower($params[0]);
                   9547:         if ($reg->channelExists($channel)) {
                   9548:             $chan = $reg->getChannel($channel);
                   9549:             if (PEAR::isError($chan)) {
                   9550:                 return $this->raiseError($chan);
                   9551:             }
                   9552:         } else {
                   9553:             if (strpos($channel, '://')) {
                   9554:                 $downloader = &$this->getDownloader();
                   9555:                 $tmpdir = $this->config->get('temp_dir');
                   9556:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   9557:                 $loc = $downloader->downloadHttp($channel, $this->ui, $tmpdir);
                   9558:                 PEAR::staticPopErrorHandling();
                   9559:                 if (PEAR::isError($loc)) {
                   9560:                     return $this->raiseError('Cannot open "' . $channel .
                   9561:                         '" (' . $loc->getMessage() . ')');
                   9562:                 } else {
                   9563:                     $contents = implode('', file($loc));
                   9564:                 }
                   9565:             } else {
                   9566:                 if (!file_exists($params[0])) {
                   9567:                     return $this->raiseError('Unknown channel "' . $channel . '"');
                   9568:                 }
                   9569: 
                   9570:                 $fp = fopen($params[0], 'r');
                   9571:                 if (!$fp) {
                   9572:                     return $this->raiseError('Cannot open "' . $params[0] . '"');
                   9573:                 }
                   9574: 
                   9575:                 $contents = '';
                   9576:                 while (!feof($fp)) {
                   9577:                     $contents .= fread($fp, 1024);
                   9578:                 }
                   9579:                 fclose($fp);
                   9580:             }
                   9581: 
                   9582:             if (!class_exists('PEAR_ChannelFile')) {
                   9583:                 require_once 'PEAR/ChannelFile.php';
                   9584:             }
                   9585: 
                   9586:             $chan = new PEAR_ChannelFile;
                   9587:             $chan->fromXmlString($contents);
                   9588:             $chan->validate();
                   9589:             if ($errs = $chan->getErrors(true)) {
                   9590:                 foreach ($errs as $err) {
                   9591:                     $this->ui->outputData($err['level'] . ': ' . $err['message']);
                   9592:                 }
                   9593:                 return $this->raiseError('Channel file "' . $params[0] . '" is not valid');
                   9594:             }
                   9595:         }
                   9596: 
                   9597:         if (!$chan) {
                   9598:             return $this->raiseError('Serious error: Channel "' . $params[0] .
                   9599:                 '" has a corrupted registry entry');
                   9600:         }
                   9601: 
                   9602:         $channel = $chan->getName();
                   9603:         $caption = 'Channel ' . $channel . ' Information:';
                   9604:         $data1 = array(
                   9605:             'caption' => $caption,
                   9606:             'border' => true);
                   9607:         $data1['data']['server'] = array('Name and Server', $chan->getName());
                   9608:         if ($chan->getAlias() != $chan->getName()) {
                   9609:             $data1['data']['alias'] = array('Alias', $chan->getAlias());
                   9610:         }
                   9611: 
                   9612:         $data1['data']['summary'] = array('Summary', $chan->getSummary());
                   9613:         $validate = $chan->getValidationPackage();
                   9614:         $data1['data']['vpackage'] = array('Validation Package Name', $validate['_content']);
                   9615:         $data1['data']['vpackageversion'] =
                   9616:             array('Validation Package Version', $validate['attribs']['version']);
                   9617:         $d = array();
                   9618:         $d['main'] = $data1;
                   9619: 
                   9620:         $data['data'] = array();
                   9621:         $data['caption'] = 'Server Capabilities';
                   9622:         $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
                   9623:         if ($chan->supportsREST()) {
                   9624:             if ($chan->supportsREST()) {
                   9625:                 $funcs = $chan->getFunctions('rest');
                   9626:                 if (!isset($funcs[0])) {
                   9627:                     $funcs = array($funcs);
                   9628:                 }
                   9629:                 foreach ($funcs as $protocol) {
                   9630:                     $data['data'][] = array('rest', $protocol['attribs']['type'],
                   9631:                         $protocol['_content']);
                   9632:                 }
                   9633:             }
                   9634:         } else {
                   9635:             $data['data'][] = array('No supported protocols');
                   9636:         }
                   9637: 
                   9638:         $d['protocols'] = $data;
                   9639:         $data['data'] = array();
                   9640:         $mirrors = $chan->getMirrors();
                   9641:         if ($mirrors) {
                   9642:             $data['caption'] = 'Channel ' . $channel . ' Mirrors:';
                   9643:             unset($data['headline']);
                   9644:             foreach ($mirrors as $mirror) {
                   9645:                 $data['data'][] = array($mirror['attribs']['host']);
                   9646:                 $d['mirrors'] = $data;
                   9647:             }
                   9648: 
                   9649:             foreach ($mirrors as $i => $mirror) {
                   9650:                 $data['data'] = array();
                   9651:                 $data['caption'] = 'Mirror ' . $mirror['attribs']['host'] . ' Capabilities';
                   9652:                 $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
                   9653:                 if ($chan->supportsREST($mirror['attribs']['host'])) {
                   9654:                     if ($chan->supportsREST($mirror['attribs']['host'])) {
                   9655:                         $funcs = $chan->getFunctions('rest', $mirror['attribs']['host']);
                   9656:                         if (!isset($funcs[0])) {
                   9657:                             $funcs = array($funcs);
                   9658:                         }
                   9659: 
                   9660:                         foreach ($funcs as $protocol) {
                   9661:                             $data['data'][] = array('rest', $protocol['attribs']['type'],
                   9662:                                 $protocol['_content']);
                   9663:                         }
                   9664:                     }
                   9665:                 } else {
                   9666:                     $data['data'][] = array('No supported protocols');
                   9667:                 }
                   9668:                 $d['mirrorprotocols' . $i] = $data;
                   9669:             }
                   9670:         }
                   9671:         $this->ui->outputData($d, 'channel-info');
                   9672:     }
                   9673: 
                   9674:     // }}}
                   9675: 
                   9676:     function doDelete($command, $options, $params)
                   9677:     {
                   9678:         if (count($params) !== 1) {
                   9679:             return $this->raiseError('channel-delete: no channel specified');
                   9680:         }
                   9681: 
                   9682:         $reg = &$this->config->getRegistry();
                   9683:         if (!$reg->channelExists($params[0])) {
                   9684:             return $this->raiseError('channel-delete: channel "' . $params[0] . '" does not exist');
                   9685:         }
                   9686: 
                   9687:         $channel = $reg->channelName($params[0]);
                   9688:         if ($channel == 'pear.php.net') {
                   9689:             return $this->raiseError('Cannot delete the pear.php.net channel');
                   9690:         }
                   9691: 
                   9692:         if ($channel == 'pecl.php.net') {
                   9693:             return $this->raiseError('Cannot delete the pecl.php.net channel');
                   9694:         }
                   9695: 
                   9696:         if ($channel == 'doc.php.net') {
                   9697:             return $this->raiseError('Cannot delete the doc.php.net channel');
                   9698:         }
                   9699: 
                   9700:         if ($channel == '__uri') {
                   9701:             return $this->raiseError('Cannot delete the __uri pseudo-channel');
                   9702:         }
                   9703: 
                   9704:         if (PEAR::isError($err = $reg->listPackages($channel))) {
                   9705:             return $err;
                   9706:         }
                   9707: 
                   9708:         if (count($err)) {
                   9709:             return $this->raiseError('Channel "' . $channel .
                   9710:                 '" has installed packages, cannot delete');
                   9711:         }
                   9712: 
                   9713:         if (!$reg->deleteChannel($channel)) {
                   9714:             return $this->raiseError('Channel "' . $channel . '" deletion failed');
                   9715:         } else {
                   9716:             $this->config->deleteChannel($channel);
                   9717:             $this->ui->outputData('Channel "' . $channel . '" deleted', $command);
                   9718:         }
                   9719:     }
                   9720: 
                   9721:     function doAdd($command, $options, $params)
                   9722:     {
                   9723:         if (count($params) !== 1) {
                   9724:             return $this->raiseError('channel-add: no channel file specified');
                   9725:         }
                   9726: 
                   9727:         if (strpos($params[0], '://')) {
                   9728:             $downloader = &$this->getDownloader();
                   9729:             $tmpdir = $this->config->get('temp_dir');
                   9730:             if (!file_exists($tmpdir)) {
                   9731:                 require_once 'System.php';
                   9732:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   9733:                 $err = System::mkdir(array('-p', $tmpdir));
                   9734:                 PEAR::staticPopErrorHandling();
                   9735:                 if (PEAR::isError($err)) {
                   9736:                     return $this->raiseError('channel-add: temp_dir does not exist: "' .
                   9737:                         $tmpdir .
                   9738:                         '" - You can change this location with "pear config-set temp_dir"');
                   9739:                 }
                   9740:             }
                   9741: 
                   9742:             if (!is_writable($tmpdir)) {
                   9743:                 return $this->raiseError('channel-add: temp_dir is not writable: "' .
                   9744:                     $tmpdir .
                   9745:                     '" - You can change this location with "pear config-set temp_dir"');
                   9746:             }
                   9747: 
                   9748:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   9749:             $loc = $downloader->downloadHttp($params[0], $this->ui, $tmpdir, null, false);
                   9750:             PEAR::staticPopErrorHandling();
                   9751:             if (PEAR::isError($loc)) {
                   9752:                 return $this->raiseError('channel-add: Cannot open "' . $params[0] .
                   9753:                     '" (' . $loc->getMessage() . ')');
                   9754:             }
                   9755: 
                   9756:             list($loc, $lastmodified) = $loc;
                   9757:             $contents = implode('', file($loc));
                   9758:         } else {
                   9759:             $lastmodified = $fp = false;
                   9760:             if (file_exists($params[0])) {
                   9761:                 $fp = fopen($params[0], 'r');
                   9762:             }
                   9763: 
                   9764:             if (!$fp) {
                   9765:                 return $this->raiseError('channel-add: cannot open "' . $params[0] . '"');
                   9766:             }
                   9767: 
                   9768:             $contents = '';
                   9769:             while (!feof($fp)) {
                   9770:                 $contents .= fread($fp, 1024);
                   9771:             }
                   9772:             fclose($fp);
                   9773:         }
                   9774: 
                   9775:         if (!class_exists('PEAR_ChannelFile')) {
                   9776:             require_once 'PEAR/ChannelFile.php';
                   9777:         }
                   9778: 
                   9779:         $channel = new PEAR_ChannelFile;
                   9780:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   9781:         $result = $channel->fromXmlString($contents);
                   9782:         PEAR::staticPopErrorHandling();
                   9783:         if (!$result) {
                   9784:             $exit = false;
                   9785:             if (count($errors = $channel->getErrors(true))) {
                   9786:                 foreach ($errors as $error) {
                   9787:                     $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
                   9788:                     if (!$exit) {
                   9789:                         $exit = $error['level'] == 'error' ? true : false;
                   9790:                     }
                   9791:                 }
                   9792:                 if ($exit) {
                   9793:                     return $this->raiseError('channel-add: invalid channel.xml file');
                   9794:                 }
                   9795:             }
                   9796:         }
                   9797: 
                   9798:         $reg = &$this->config->getRegistry();
                   9799:         if ($reg->channelExists($channel->getName())) {
                   9800:             return $this->raiseError('channel-add: Channel "' . $channel->getName() .
                   9801:                 '" exists, use channel-update to update entry', PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS);
                   9802:         }
                   9803: 
                   9804:         $ret = $reg->addChannel($channel, $lastmodified);
                   9805:         if (PEAR::isError($ret)) {
                   9806:             return $ret;
                   9807:         }
                   9808: 
                   9809:         if (!$ret) {
                   9810:             return $this->raiseError('channel-add: adding Channel "' . $channel->getName() .
                   9811:                 '" to registry failed');
                   9812:         }
                   9813: 
                   9814:         $this->config->setChannels($reg->listChannels());
                   9815:         $this->config->writeConfigFile();
                   9816:         $this->ui->outputData('Adding Channel "' . $channel->getName() . '" succeeded', $command);
                   9817:     }
                   9818: 
                   9819:     function doUpdate($command, $options, $params)
                   9820:     {
                   9821:         if (count($params) !== 1) {
                   9822:             return $this->raiseError("No channel file specified");
                   9823:         }
                   9824: 
                   9825:         $tmpdir = $this->config->get('temp_dir');
                   9826:         if (!file_exists($tmpdir)) {
                   9827:             require_once 'System.php';
                   9828:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   9829:             $err = System::mkdir(array('-p', $tmpdir));
                   9830:             PEAR::staticPopErrorHandling();
                   9831:             if (PEAR::isError($err)) {
                   9832:                 return $this->raiseError('channel-add: temp_dir does not exist: "' .
                   9833:                     $tmpdir .
                   9834:                     '" - You can change this location with "pear config-set temp_dir"');
                   9835:             }
                   9836:         }
                   9837: 
                   9838:         if (!is_writable($tmpdir)) {
                   9839:             return $this->raiseError('channel-add: temp_dir is not writable: "' .
                   9840:                 $tmpdir .
                   9841:                 '" - You can change this location with "pear config-set temp_dir"');
                   9842:         }
                   9843: 
                   9844:         $reg = &$this->config->getRegistry();
                   9845:         $lastmodified = false;
                   9846:         if ((!file_exists($params[0]) || is_dir($params[0]))
                   9847:               && $reg->channelExists(strtolower($params[0]))) {
                   9848:             $c = $reg->getChannel(strtolower($params[0]));
                   9849:             if (PEAR::isError($c)) {
                   9850:                 return $this->raiseError($c);
                   9851:             }
                   9852: 
                   9853:             $this->ui->outputData("Updating channel \"$params[0]\"", $command);
                   9854:             $dl = &$this->getDownloader(array());
                   9855:             // if force is specified, use a timestamp of "1" to force retrieval
                   9856:             $lastmodified = isset($options['force']) ? false : $c->lastModified();
                   9857:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   9858:             $contents = $dl->downloadHttp('http://' . $c->getName() . '/channel.xml',
                   9859:                 $this->ui, $tmpdir, null, $lastmodified);
                   9860:             PEAR::staticPopErrorHandling();
                   9861:             if (PEAR::isError($contents)) {
                   9862:                 // Attempt to fall back to https
                   9863:                 $this->ui->outputData("Channel \"$params[0]\" is not responding over http://, failed with message: " . $contents->getMessage());
                   9864:                 $this->ui->outputData("Trying channel \"$params[0]\" over https:// instead");
                   9865:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   9866:                 $contents = $dl->downloadHttp('https://' . $c->getName() . '/channel.xml',
                   9867:                     $this->ui, $tmpdir, null, $lastmodified);
                   9868:                 PEAR::staticPopErrorHandling();
                   9869:                 if (PEAR::isError($contents)) {
                   9870:                     return $this->raiseError('Cannot retrieve channel.xml for channel "' .
                   9871:                         $c->getName() . '" (' . $contents->getMessage() . ')');
                   9872:                 }
                   9873:             }
                   9874: 
                   9875:             list($contents, $lastmodified) = $contents;
                   9876:             if (!$contents) {
                   9877:                 $this->ui->outputData("Channel \"$params[0]\" is up to date");
                   9878:                 return;
                   9879:             }
                   9880: 
                   9881:             $contents = implode('', file($contents));
                   9882:             if (!class_exists('PEAR_ChannelFile')) {
                   9883:                 require_once 'PEAR/ChannelFile.php';
                   9884:             }
                   9885: 
                   9886:             $channel = new PEAR_ChannelFile;
                   9887:             $channel->fromXmlString($contents);
                   9888:             if (!$channel->getErrors()) {
                   9889:                 // security check: is the downloaded file for the channel we got it from?
                   9890:                 if (strtolower($channel->getName()) != strtolower($c->getName())) {
                   9891:                     if (!isset($options['force'])) {
                   9892:                         return $this->raiseError('ERROR: downloaded channel definition file' .
                   9893:                             ' for channel "' . $channel->getName() . '" from channel "' .
                   9894:                             strtolower($c->getName()) . '"');
                   9895:                     }
                   9896: 
                   9897:                     $this->ui->log(0, 'WARNING: downloaded channel definition file' .
                   9898:                         ' for channel "' . $channel->getName() . '" from channel "' .
                   9899:                         strtolower($c->getName()) . '"');
                   9900:                 }
                   9901:             }
                   9902:         } else {
                   9903:             if (strpos($params[0], '://')) {
                   9904:                 $dl = &$this->getDownloader();
                   9905:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   9906:                 $loc = $dl->downloadHttp($params[0],
                   9907:                     $this->ui, $tmpdir, null, $lastmodified);
                   9908:                 PEAR::staticPopErrorHandling();
                   9909:                 if (PEAR::isError($loc)) {
                   9910:                     return $this->raiseError("Cannot open " . $params[0] .
                   9911:                          ' (' . $loc->getMessage() . ')');
                   9912:                 }
                   9913: 
                   9914:                 list($loc, $lastmodified) = $loc;
                   9915:                 $contents = implode('', file($loc));
                   9916:             } else {
                   9917:                 $fp = false;
                   9918:                 if (file_exists($params[0])) {
                   9919:                     $fp = fopen($params[0], 'r');
                   9920:                 }
                   9921: 
                   9922:                 if (!$fp) {
                   9923:                     return $this->raiseError("Cannot open " . $params[0]);
                   9924:                 }
                   9925: 
                   9926:                 $contents = '';
                   9927:                 while (!feof($fp)) {
                   9928:                     $contents .= fread($fp, 1024);
                   9929:                 }
                   9930:                 fclose($fp);
                   9931:             }
                   9932: 
                   9933:             if (!class_exists('PEAR_ChannelFile')) {
                   9934:                 require_once 'PEAR/ChannelFile.php';
                   9935:             }
                   9936: 
                   9937:             $channel = new PEAR_ChannelFile;
                   9938:             $channel->fromXmlString($contents);
                   9939:         }
                   9940: 
                   9941:         $exit = false;
                   9942:         if (count($errors = $channel->getErrors(true))) {
                   9943:             foreach ($errors as $error) {
                   9944:                 $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
                   9945:                 if (!$exit) {
                   9946:                     $exit = $error['level'] == 'error' ? true : false;
                   9947:                 }
                   9948:             }
                   9949:             if ($exit) {
                   9950:                 return $this->raiseError('Invalid channel.xml file');
                   9951:             }
                   9952:         }
                   9953: 
                   9954:         if (!$reg->channelExists($channel->getName())) {
                   9955:             return $this->raiseError('Error: Channel "' . $channel->getName() .
                   9956:                 '" does not exist, use channel-add to add an entry');
                   9957:         }
                   9958: 
                   9959:         $ret = $reg->updateChannel($channel, $lastmodified);
                   9960:         if (PEAR::isError($ret)) {
                   9961:             return $ret;
                   9962:         }
                   9963: 
                   9964:         if (!$ret) {
                   9965:             return $this->raiseError('Updating Channel "' . $channel->getName() .
                   9966:                 '" in registry failed');
                   9967:         }
                   9968: 
                   9969:         $this->config->setChannels($reg->listChannels());
                   9970:         $this->config->writeConfigFile();
                   9971:         $this->ui->outputData('Update of Channel "' . $channel->getName() . '" succeeded');
                   9972:     }
                   9973: 
                   9974:     function &getDownloader()
                   9975:     {
                   9976:         if (!class_exists('PEAR_Downloader')) {
                   9977:             require_once 'PEAR/Downloader.php';
                   9978:         }
                   9979:         $a = new PEAR_Downloader($this->ui, array(), $this->config);
                   9980:         return $a;
                   9981:     }
                   9982: 
                   9983:     function doAlias($command, $options, $params)
                   9984:     {
                   9985:         if (count($params) === 1) {
                   9986:             return $this->raiseError('No channel alias specified');
                   9987:         }
                   9988: 
                   9989:         if (count($params) !== 2 || (!empty($params[1]) && $params[1]{0} == '-')) {
                   9990:             return $this->raiseError(
                   9991:                 'Invalid format, correct is: channel-alias channel alias');
                   9992:         }
                   9993: 
                   9994:         $reg = &$this->config->getRegistry();
                   9995:         if (!$reg->channelExists($params[0], true)) {
                   9996:             $extra = '';
                   9997:             if ($reg->isAlias($params[0])) {
                   9998:                 $extra = ' (use "channel-alias ' . $reg->channelName($params[0]) . ' ' .
                   9999:                     strtolower($params[1]) . '")';
                   10000:             }
                   10001: 
                   10002:             return $this->raiseError('"' . $params[0] . '" is not a valid channel' . $extra);
                   10003:         }
                   10004: 
                   10005:         if ($reg->isAlias($params[1])) {
                   10006:             return $this->raiseError('Channel "' . $reg->channelName($params[1]) . '" is ' .
                   10007:                 'already aliased to "' . strtolower($params[1]) . '", cannot re-alias');
                   10008:         }
                   10009: 
                   10010:         $chan = &$reg->getChannel($params[0]);
                   10011:         if (PEAR::isError($chan)) {
                   10012:             return $this->raiseError('Corrupt registry?  Error retrieving channel "' . $params[0] .
                   10013:                 '" information (' . $chan->getMessage() . ')');
                   10014:         }
                   10015: 
                   10016:         // make it a local alias
                   10017:         if (!$chan->setAlias(strtolower($params[1]), true)) {
                   10018:             return $this->raiseError('Alias "' . strtolower($params[1]) .
                   10019:                 '" is not a valid channel alias');
                   10020:         }
                   10021: 
                   10022:         $reg->updateChannel($chan);
                   10023:         $this->ui->outputData('Channel "' . $chan->getName() . '" aliased successfully to "' .
                   10024:             strtolower($params[1]) . '"');
                   10025:     }
                   10026: 
                   10027:     /**
                   10028:      * The channel-discover command
                   10029:      *
                   10030:      * @param string $command command name
                   10031:      * @param array  $options option_name => value
                   10032:      * @param array  $params  list of additional parameters.
                   10033:      *               $params[0] should contain a string with either:
                   10034:      *               - <channel name> or
                   10035:      *               - <username>:<password>@<channel name>
                   10036:      * @return null|PEAR_Error
                   10037:      */
                   10038:     function doDiscover($command, $options, $params)
                   10039:     {
                   10040:         if (count($params) !== 1) {
                   10041:             return $this->raiseError("No channel server specified");
                   10042:         }
                   10043: 
                   10044:         // Look for the possible input format "<username>:<password>@<channel>"
                   10045:         if (preg_match('/^(.+):(.+)@(.+)\\z/', $params[0], $matches)) {
                   10046:             $username = $matches[1];
                   10047:             $password = $matches[2];
                   10048:             $channel  = $matches[3];
                   10049:         } else {
                   10050:             $channel = $params[0];
                   10051:         }
                   10052: 
                   10053:         $reg = &$this->config->getRegistry();
                   10054:         if ($reg->channelExists($channel)) {
                   10055:             if (!$reg->isAlias($channel)) {
                   10056:                 return $this->raiseError("Channel \"$channel\" is already initialized", PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS);
                   10057:             }
                   10058: 
                   10059:             return $this->raiseError("A channel alias named \"$channel\" " .
                   10060:                 'already exists, aliasing channel "' . $reg->channelName($channel)
                   10061:                 . '"');
                   10062:         }
                   10063: 
                   10064:         $this->pushErrorHandling(PEAR_ERROR_RETURN);
                   10065:         $err = $this->doAdd($command, $options, array('http://' . $channel . '/channel.xml'));
                   10066:         $this->popErrorHandling();
                   10067:         if (PEAR::isError($err)) {
                   10068:             if ($err->getCode() === PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS) {
                   10069:                 return $this->raiseError("Discovery of channel \"$channel\" failed (" .
                   10070:                     $err->getMessage() . ')');
                   10071:             }
                   10072:             // Attempt fetch via https
                   10073:             $this->ui->outputData("Discovering channel $channel over http:// failed with message: " . $err->getMessage());
                   10074:             $this->ui->outputData("Trying to discover channel $channel over https:// instead");
                   10075:             $this->pushErrorHandling(PEAR_ERROR_RETURN);
                   10076:             $err = $this->doAdd($command, $options, array('https://' . $channel . '/channel.xml'));
                   10077:             $this->popErrorHandling();
                   10078:             if (PEAR::isError($err)) {
                   10079:                 return $this->raiseError("Discovery of channel \"$channel\" failed (" .
                   10080:                     $err->getMessage() . ')');
                   10081:             }
                   10082:         }
                   10083: 
                   10084:         // Store username/password if they were given
                   10085:         // Arguably we should do a logintest on the channel here, but since
                   10086:         // that's awkward on a REST-based channel (even "pear login" doesn't
                   10087:         // do it for those), and XML-RPC is deprecated, it's fairly pointless.
                   10088:         if (isset($username)) {
                   10089:             $this->config->set('username', $username, 'user', $channel);
                   10090:             $this->config->set('password', $password, 'user', $channel);
                   10091:             $this->config->store();
                   10092:             $this->ui->outputData("Stored login for channel \"$channel\" using username \"$username\"", $command);
                   10093:         }
                   10094: 
                   10095:         $this->ui->outputData("Discovery of channel \"$channel\" succeeded", $command);
                   10096:     }
                   10097: 
                   10098:     /**
                   10099:      * Execute the 'login' command.
                   10100:      *
                   10101:      * @param string $command command name
                   10102:      * @param array $options option_name => value
                   10103:      * @param array $params list of additional parameters
                   10104:      *
                   10105:      * @return bool TRUE on success or
                   10106:      * a PEAR error on failure
                   10107:      *
                   10108:      * @access public
                   10109:      */
                   10110:     function doLogin($command, $options, $params)
                   10111:     {
                   10112:         $reg = &$this->config->getRegistry();
                   10113: 
                   10114:         // If a parameter is supplied, use that as the channel to log in to
                   10115:         $channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel');
                   10116: 
                   10117:         $chan = $reg->getChannel($channel);
                   10118:         if (PEAR::isError($chan)) {
                   10119:             return $this->raiseError($chan);
                   10120:         }
                   10121: 
                   10122:         $server   = $this->config->get('preferred_mirror', null, $channel);
                   10123:         $username = $this->config->get('username',         null, $channel);
                   10124:         if (empty($username)) {
                   10125:             $username = isset($_ENV['USER']) ? $_ENV['USER'] : null;
                   10126:         }
                   10127:         $this->ui->outputData("Logging in to $server.", $command);
                   10128: 
                   10129:         list($username, $password) = $this->ui->userDialog(
                   10130:             $command,
                   10131:             array('Username', 'Password'),
                   10132:             array('text',     'password'),
                   10133:             array($username,  '')
                   10134:             );
                   10135:         $username = trim($username);
                   10136:         $password = trim($password);
                   10137: 
                   10138:         $ourfile = $this->config->getConfFile('user');
                   10139:         if (!$ourfile) {
                   10140:             $ourfile = $this->config->getConfFile('system');
                   10141:         }
                   10142: 
                   10143:         $this->config->set('username', $username, 'user', $channel);
                   10144:         $this->config->set('password', $password, 'user', $channel);
                   10145: 
                   10146:         if ($chan->supportsREST()) {
                   10147:             $ok = true;
                   10148:         }
                   10149: 
                   10150:         if ($ok !== true) {
                   10151:             return $this->raiseError('Login failed!');
                   10152:         }
                   10153: 
                   10154:         $this->ui->outputData("Logged in.", $command);
                   10155:         // avoid changing any temporary settings changed with -d
                   10156:         $ourconfig = new PEAR_Config($ourfile, $ourfile);
                   10157:         $ourconfig->set('username', $username, 'user', $channel);
                   10158:         $ourconfig->set('password', $password, 'user', $channel);
                   10159:         $ourconfig->store();
                   10160: 
                   10161:         return true;
                   10162:     }
                   10163: 
                   10164:     /**
                   10165:      * Execute the 'logout' command.
                   10166:      *
                   10167:      * @param string $command command name
                   10168:      * @param array $options option_name => value
                   10169:      * @param array $params list of additional parameters
                   10170:      *
                   10171:      * @return bool TRUE on success or
                   10172:      * a PEAR error on failure
                   10173:      *
                   10174:      * @access public
                   10175:      */
                   10176:     function doLogout($command, $options, $params)
                   10177:     {
                   10178:         $reg     = &$this->config->getRegistry();
                   10179: 
                   10180:         // If a parameter is supplied, use that as the channel to log in to
                   10181:         $channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel');
                   10182: 
                   10183:         $chan    = $reg->getChannel($channel);
                   10184:         if (PEAR::isError($chan)) {
                   10185:             return $this->raiseError($chan);
                   10186:         }
                   10187: 
                   10188:         $server = $this->config->get('preferred_mirror', null, $channel);
                   10189:         $this->ui->outputData("Logging out from $server.", $command);
                   10190:         $this->config->remove('username', 'user', $channel);
                   10191:         $this->config->remove('password', 'user', $channel);
                   10192:         $this->config->store();
                   10193:         return true;
                   10194:     }
1.1.1.2 ! misho    10195: }PEAR-1.9.4/PEAR/Command/Common.php0000644000076500000240000002014411605156614015303 0ustar  helgistaff<?php
1.1       misho    10196: /**
                   10197:  * PEAR_Command_Common base class
                   10198:  *
                   10199:  * PHP versions 4 and 5
                   10200:  *
                   10201:  * @category   pear
                   10202:  * @package    PEAR
                   10203:  * @author     Stig Bakken <ssb@php.net>
                   10204:  * @author     Greg Beaver <cellog@php.net>
                   10205:  * @copyright  1997-2009 The Authors
                   10206:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   10207:  * @version    CVS: $Id: Common.php 313023 2011-07-06 19:17:11Z dufuz $
                   10208:  * @link       http://pear.php.net/package/PEAR
                   10209:  * @since      File available since Release 0.1
                   10210:  */
                   10211: 
                   10212: /**
                   10213:  * base class
                   10214:  */
                   10215: require_once 'PEAR.php';
                   10216: 
                   10217: /**
                   10218:  * PEAR commands base class
                   10219:  *
                   10220:  * @category   pear
                   10221:  * @package    PEAR
                   10222:  * @author     Stig Bakken <ssb@php.net>
                   10223:  * @author     Greg Beaver <cellog@php.net>
                   10224:  * @copyright  1997-2009 The Authors
                   10225:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   10226:  * @version    Release: 1.9.4
                   10227:  * @link       http://pear.php.net/package/PEAR
                   10228:  * @since      Class available since Release 0.1
                   10229:  */
                   10230: class PEAR_Command_Common extends PEAR
                   10231: {
                   10232:     /**
                   10233:      * PEAR_Config object used to pass user system and configuration
                   10234:      * on when executing commands
                   10235:      *
                   10236:      * @var PEAR_Config
                   10237:      */
                   10238:     var $config;
                   10239:     /**
                   10240:      * @var PEAR_Registry
                   10241:      * @access protected
                   10242:      */
                   10243:     var $_registry;
                   10244: 
                   10245:     /**
                   10246:      * User Interface object, for all interaction with the user.
                   10247:      * @var object
                   10248:      */
                   10249:     var $ui;
                   10250: 
                   10251:     var $_deps_rel_trans = array(
                   10252:                                  'lt' => '<',
                   10253:                                  'le' => '<=',
                   10254:                                  'eq' => '=',
                   10255:                                  'ne' => '!=',
                   10256:                                  'gt' => '>',
                   10257:                                  'ge' => '>=',
                   10258:                                  'has' => '=='
                   10259:                                  );
                   10260: 
                   10261:     var $_deps_type_trans = array(
                   10262:                                   'pkg' => 'package',
                   10263:                                   'ext' => 'extension',
                   10264:                                   'php' => 'PHP',
                   10265:                                   'prog' => 'external program',
                   10266:                                   'ldlib' => 'external library for linking',
                   10267:                                   'rtlib' => 'external runtime library',
                   10268:                                   'os' => 'operating system',
                   10269:                                   'websrv' => 'web server',
                   10270:                                   'sapi' => 'SAPI backend'
                   10271:                                   );
                   10272: 
                   10273:     /**
                   10274:      * PEAR_Command_Common constructor.
                   10275:      *
                   10276:      * @access public
                   10277:      */
                   10278:     function PEAR_Command_Common(&$ui, &$config)
                   10279:     {
                   10280:         parent::PEAR();
                   10281:         $this->config = &$config;
                   10282:         $this->ui = &$ui;
                   10283:     }
                   10284: 
                   10285:     /**
                   10286:      * Return a list of all the commands defined by this class.
                   10287:      * @return array list of commands
                   10288:      * @access public
                   10289:      */
                   10290:     function getCommands()
                   10291:     {
                   10292:         $ret = array();
                   10293:         foreach (array_keys($this->commands) as $command) {
                   10294:             $ret[$command] = $this->commands[$command]['summary'];
                   10295:         }
                   10296: 
                   10297:         return $ret;
                   10298:     }
                   10299: 
                   10300:     /**
                   10301:      * Return a list of all the command shortcuts defined by this class.
                   10302:      * @return array shortcut => command
                   10303:      * @access public
                   10304:      */
                   10305:     function getShortcuts()
                   10306:     {
                   10307:         $ret = array();
                   10308:         foreach (array_keys($this->commands) as $command) {
                   10309:             if (isset($this->commands[$command]['shortcut'])) {
                   10310:                 $ret[$this->commands[$command]['shortcut']] = $command;
                   10311:             }
                   10312:         }
                   10313: 
                   10314:         return $ret;
                   10315:     }
                   10316: 
                   10317:     function getOptions($command)
                   10318:     {
                   10319:         $shortcuts = $this->getShortcuts();
                   10320:         if (isset($shortcuts[$command])) {
                   10321:             $command = $shortcuts[$command];
                   10322:         }
                   10323: 
                   10324:         if (isset($this->commands[$command]) &&
                   10325:               isset($this->commands[$command]['options'])) {
                   10326:             return $this->commands[$command]['options'];
                   10327:         }
                   10328: 
                   10329:         return null;
                   10330:     }
                   10331: 
                   10332:     function getGetoptArgs($command, &$short_args, &$long_args)
                   10333:     {
                   10334:         $short_args = '';
                   10335:         $long_args = array();
                   10336:         if (empty($this->commands[$command]) || empty($this->commands[$command]['options'])) {
                   10337:             return;
                   10338:         }
                   10339: 
                   10340:         reset($this->commands[$command]['options']);
                   10341:         while (list($option, $info) = each($this->commands[$command]['options'])) {
                   10342:             $larg = $sarg = '';
                   10343:             if (isset($info['arg'])) {
                   10344:                 if ($info['arg']{0} == '(') {
                   10345:                     $larg = '==';
                   10346:                     $sarg = '::';
                   10347:                     $arg = substr($info['arg'], 1, -1);
                   10348:                 } else {
                   10349:                     $larg = '=';
                   10350:                     $sarg = ':';
                   10351:                     $arg = $info['arg'];
                   10352:                 }
                   10353:             }
                   10354: 
                   10355:             if (isset($info['shortopt'])) {
                   10356:                 $short_args .= $info['shortopt'] . $sarg;
                   10357:             }
                   10358: 
                   10359:             $long_args[] = $option . $larg;
                   10360:         }
                   10361:     }
                   10362: 
                   10363:     /**
                   10364:     * Returns the help message for the given command
                   10365:     *
                   10366:     * @param string $command The command
                   10367:     * @return mixed A fail string if the command does not have help or
                   10368:     *               a two elements array containing [0]=>help string,
                   10369:     *               [1]=> help string for the accepted cmd args
                   10370:     */
                   10371:     function getHelp($command)
                   10372:     {
                   10373:         $config = &PEAR_Config::singleton();
                   10374:         if (!isset($this->commands[$command])) {
                   10375:             return "No such command \"$command\"";
                   10376:         }
                   10377: 
                   10378:         $help = null;
                   10379:         if (isset($this->commands[$command]['doc'])) {
                   10380:             $help = $this->commands[$command]['doc'];
                   10381:         }
                   10382: 
                   10383:         if (empty($help)) {
                   10384:             // XXX (cox) Fallback to summary if there is no doc (show both?)
                   10385:             if (!isset($this->commands[$command]['summary'])) {
                   10386:                 return "No help for command \"$command\"";
                   10387:             }
                   10388:             $help = $this->commands[$command]['summary'];
                   10389:         }
                   10390: 
                   10391:         if (preg_match_all('/{config\s+([^\}]+)}/e', $help, $matches)) {
                   10392:             foreach($matches[0] as $k => $v) {
                   10393:                 $help = preg_replace("/$v/", $config->get($matches[1][$k]), $help);
                   10394:             }
                   10395:         }
                   10396: 
                   10397:         return array($help, $this->getHelpArgs($command));
                   10398:     }
                   10399: 
                   10400:     /**
                   10401:      * Returns the help for the accepted arguments of a command
                   10402:      *
                   10403:      * @param  string $command
                   10404:      * @return string The help string
                   10405:      */
                   10406:     function getHelpArgs($command)
                   10407:     {
                   10408:         if (isset($this->commands[$command]['options']) &&
                   10409:             count($this->commands[$command]['options']))
                   10410:         {
                   10411:             $help = "Options:\n";
                   10412:             foreach ($this->commands[$command]['options'] as $k => $v) {
                   10413:                 if (isset($v['arg'])) {
                   10414:                     if ($v['arg'][0] == '(') {
                   10415:                         $arg = substr($v['arg'], 1, -1);
                   10416:                         $sapp = " [$arg]";
                   10417:                         $lapp = "[=$arg]";
                   10418:                     } else {
                   10419:                         $sapp = " $v[arg]";
                   10420:                         $lapp = "=$v[arg]";
                   10421:                     }
                   10422:                 } else {
                   10423:                     $sapp = $lapp = "";
                   10424:                 }
                   10425: 
                   10426:                 if (isset($v['shortopt'])) {
                   10427:                     $s = $v['shortopt'];
                   10428:                     $help .= "  -$s$sapp, --$k$lapp\n";
                   10429:                 } else {
                   10430:                     $help .= "  --$k$lapp\n";
                   10431:                 }
                   10432: 
                   10433:                 $p = "        ";
                   10434:                 $doc = rtrim(str_replace("\n", "\n$p", $v['doc']));
                   10435:                 $help .= "        $doc\n";
                   10436:             }
                   10437: 
                   10438:             return $help;
                   10439:         }
                   10440: 
                   10441:         return null;
                   10442:     }
                   10443: 
                   10444:     function run($command, $options, $params)
                   10445:     {
                   10446:         if (empty($this->commands[$command]['function'])) {
                   10447:             // look for shortcuts
                   10448:             foreach (array_keys($this->commands) as $cmd) {
                   10449:                 if (isset($this->commands[$cmd]['shortcut']) && $this->commands[$cmd]['shortcut'] == $command) {
                   10450:                     if (empty($this->commands[$cmd]['function'])) {
                   10451:                         return $this->raiseError("unknown command `$command'");
                   10452:                     } else {
                   10453:                         $func = $this->commands[$cmd]['function'];
                   10454:                     }
                   10455:                     $command = $cmd;
                   10456: 
                   10457:                     //$command = $this->commands[$cmd]['function'];
                   10458:                     break;
                   10459:                 }
                   10460:             }
                   10461:         } else {
                   10462:             $func = $this->commands[$command]['function'];
                   10463:         }
                   10464: 
                   10465:         return $this->$func($command, $options, $params);
                   10466:     }
1.1.1.2 ! misho    10467: }PEAR-1.9.4/PEAR/Command/Config.xml0000644000076500000240000000646611605156614015304 0ustar  helgistaff<commands version="1.0">
1.1       misho    10468:  <config-show>
                   10469:   <summary>Show All Settings</summary>
                   10470:   <function>doConfigShow</function>
                   10471:   <shortcut>csh</shortcut>
                   10472:   <options>
                   10473:    <channel>
                   10474:     <shortopt>c</shortopt>
                   10475:     <doc>show configuration variables for another channel</doc>
                   10476:     <arg>CHAN</arg>
                   10477:    </channel>
                   10478:   </options>
                   10479:   <doc>[layer]
                   10480: Displays all configuration values.  An optional argument
                   10481: may be used to tell which configuration layer to display.  Valid
                   10482: configuration layers are &quot;user&quot;, &quot;system&quot; and &quot;default&quot;. To display
                   10483: configurations for different channels, set the default_channel
                   10484: configuration variable and run config-show again.
                   10485: </doc>
                   10486:  </config-show>
                   10487:  <config-get>
                   10488:   <summary>Show One Setting</summary>
                   10489:   <function>doConfigGet</function>
                   10490:   <shortcut>cg</shortcut>
                   10491:   <options>
                   10492:    <channel>
                   10493:     <shortopt>c</shortopt>
                   10494:     <doc>show configuration variables for another channel</doc>
                   10495:     <arg>CHAN</arg>
                   10496:    </channel>
                   10497:   </options>
                   10498:   <doc>&lt;parameter&gt; [layer]
                   10499: Displays the value of one configuration parameter.  The
                   10500: first argument is the name of the parameter, an optional second argument
                   10501: may be used to tell which configuration layer to look in.  Valid configuration
                   10502: layers are &quot;user&quot;, &quot;system&quot; and &quot;default&quot;.  If no layer is specified, a value
                   10503: will be picked from the first layer that defines the parameter, in the order
                   10504: just specified.  The configuration value will be retrieved for the channel
                   10505: specified by the default_channel configuration variable.
                   10506: </doc>
                   10507:  </config-get>
                   10508:  <config-set>
                   10509:   <summary>Change Setting</summary>
                   10510:   <function>doConfigSet</function>
                   10511:   <shortcut>cs</shortcut>
                   10512:   <options>
                   10513:    <channel>
                   10514:     <shortopt>c</shortopt>
                   10515:     <doc>show configuration variables for another channel</doc>
                   10516:     <arg>CHAN</arg>
                   10517:    </channel>
                   10518:   </options>
                   10519:   <doc>&lt;parameter&gt; &lt;value&gt; [layer]
                   10520: Sets the value of one configuration parameter.  The first argument is
                   10521: the name of the parameter, the second argument is the new value.  Some
                   10522: parameters are subject to validation, and the command will fail with
                   10523: an error message if the new value does not make sense.  An optional
                   10524: third argument may be used to specify in which layer to set the
                   10525: configuration parameter.  The default layer is &quot;user&quot;.  The
                   10526: configuration value will be set for the current channel, which
                   10527: is controlled by the default_channel configuration variable.
                   10528: </doc>
                   10529:  </config-set>
                   10530:  <config-help>
                   10531:   <summary>Show Information About Setting</summary>
                   10532:   <function>doConfigHelp</function>
                   10533:   <shortcut>ch</shortcut>
                   10534:   <options />
                   10535:   <doc>[parameter]
                   10536: Displays help for a configuration parameter.  Without arguments it
                   10537: displays help for all configuration parameters.
                   10538: </doc>
                   10539:  </config-help>
                   10540:  <config-create>
                   10541:   <summary>Create a Default configuration file</summary>
                   10542:   <function>doConfigCreate</function>
                   10543:   <shortcut>coc</shortcut>
                   10544:   <options>
                   10545:    <windows>
                   10546:     <shortopt>w</shortopt>
                   10547:     <doc>create a config file for a windows install</doc>
                   10548:    </windows>
                   10549:   </options>
                   10550:   <doc>&lt;root path&gt; &lt;filename&gt;
                   10551: Create a default configuration file with all directory configuration
                   10552: variables set to subdirectories of &lt;root path&gt;, and save it as &lt;filename&gt;.
                   10553: This is useful especially for creating a configuration file for a remote
                   10554: PEAR installation (using the --remoteconfig option of install, upgrade,
                   10555: and uninstall).
                   10556: </doc>
                   10557:  </config-create>
1.1.1.2 ! misho    10558: </commands>PEAR-1.9.4/PEAR/Command/Config.php0000644000076500000240000003615611605156614015272 0ustar  helgistaff<?php
1.1       misho    10559: /**
                   10560:  * PEAR_Command_Config (config-show, config-get, config-set, config-help, config-create commands)
                   10561:  *
                   10562:  * PHP versions 4 and 5
                   10563:  *
                   10564:  * @category   pear
                   10565:  * @package    PEAR
                   10566:  * @author     Stig Bakken <ssb@php.net>
                   10567:  * @author     Greg Beaver <cellog@php.net>
                   10568:  * @copyright  1997-2009 The Authors
                   10569:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   10570:  * @version    CVS: $Id: Config.php 313024 2011-07-06 19:51:24Z dufuz $
                   10571:  * @link       http://pear.php.net/package/PEAR
                   10572:  * @since      File available since Release 0.1
                   10573:  */
                   10574: 
                   10575: /**
                   10576:  * base class
                   10577:  */
                   10578: require_once 'PEAR/Command/Common.php';
                   10579: 
                   10580: /**
                   10581:  * PEAR commands for managing configuration data.
                   10582:  *
                   10583:  * @category   pear
                   10584:  * @package    PEAR
                   10585:  * @author     Stig Bakken <ssb@php.net>
                   10586:  * @author     Greg Beaver <cellog@php.net>
                   10587:  * @copyright  1997-2009 The Authors
                   10588:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   10589:  * @version    Release: 1.9.4
                   10590:  * @link       http://pear.php.net/package/PEAR
                   10591:  * @since      Class available since Release 0.1
                   10592:  */
                   10593: class PEAR_Command_Config extends PEAR_Command_Common
                   10594: {
                   10595:     var $commands = array(
                   10596:         'config-show' => array(
                   10597:             'summary' => 'Show All Settings',
                   10598:             'function' => 'doConfigShow',
                   10599:             'shortcut' => 'csh',
                   10600:             'options' => array(
                   10601:                 'channel' => array(
                   10602:                     'shortopt' => 'c',
                   10603:                     'doc' => 'show configuration variables for another channel',
                   10604:                     'arg' => 'CHAN',
                   10605:                     ),
                   10606: ),
                   10607:             'doc' => '[layer]
                   10608: Displays all configuration values.  An optional argument
                   10609: may be used to tell which configuration layer to display.  Valid
                   10610: configuration layers are "user", "system" and "default". To display
                   10611: configurations for different channels, set the default_channel
                   10612: configuration variable and run config-show again.
                   10613: ',
                   10614:             ),
                   10615:         'config-get' => array(
                   10616:             'summary' => 'Show One Setting',
                   10617:             'function' => 'doConfigGet',
                   10618:             'shortcut' => 'cg',
                   10619:             'options' => array(
                   10620:                 'channel' => array(
                   10621:                     'shortopt' => 'c',
                   10622:                     'doc' => 'show configuration variables for another channel',
                   10623:                     'arg' => 'CHAN',
                   10624:                     ),
                   10625: ),
                   10626:             'doc' => '<parameter> [layer]
                   10627: Displays the value of one configuration parameter.  The
                   10628: first argument is the name of the parameter, an optional second argument
                   10629: may be used to tell which configuration layer to look in.  Valid configuration
                   10630: layers are "user", "system" and "default".  If no layer is specified, a value
                   10631: will be picked from the first layer that defines the parameter, in the order
                   10632: just specified.  The configuration value will be retrieved for the channel
                   10633: specified by the default_channel configuration variable.
                   10634: ',
                   10635:             ),
                   10636:         'config-set' => array(
                   10637:             'summary' => 'Change Setting',
                   10638:             'function' => 'doConfigSet',
                   10639:             'shortcut' => 'cs',
                   10640:             'options' => array(
                   10641:                 'channel' => array(
                   10642:                     'shortopt' => 'c',
                   10643:                     'doc' => 'show configuration variables for another channel',
                   10644:                     'arg' => 'CHAN',
                   10645:                     ),
                   10646: ),
                   10647:             'doc' => '<parameter> <value> [layer]
                   10648: Sets the value of one configuration parameter.  The first argument is
                   10649: the name of the parameter, the second argument is the new value.  Some
                   10650: parameters are subject to validation, and the command will fail with
                   10651: an error message if the new value does not make sense.  An optional
                   10652: third argument may be used to specify in which layer to set the
                   10653: configuration parameter.  The default layer is "user".  The
                   10654: configuration value will be set for the current channel, which
                   10655: is controlled by the default_channel configuration variable.
                   10656: ',
                   10657:             ),
                   10658:         'config-help' => array(
                   10659:             'summary' => 'Show Information About Setting',
                   10660:             'function' => 'doConfigHelp',
                   10661:             'shortcut' => 'ch',
                   10662:             'options' => array(),
                   10663:             'doc' => '[parameter]
                   10664: Displays help for a configuration parameter.  Without arguments it
                   10665: displays help for all configuration parameters.
                   10666: ',
                   10667:            ),
                   10668:         'config-create' => array(
                   10669:             'summary' => 'Create a Default configuration file',
                   10670:             'function' => 'doConfigCreate',
                   10671:             'shortcut' => 'coc',
                   10672:             'options' => array(
                   10673:                 'windows' => array(
                   10674:                     'shortopt' => 'w',
                   10675:                     'doc' => 'create a config file for a windows install',
                   10676:                     ),
                   10677:             ),
                   10678:             'doc' => '<root path> <filename>
                   10679: Create a default configuration file with all directory configuration
                   10680: variables set to subdirectories of <root path>, and save it as <filename>.
                   10681: This is useful especially for creating a configuration file for a remote
                   10682: PEAR installation (using the --remoteconfig option of install, upgrade,
                   10683: and uninstall).
                   10684: ',
                   10685:             ),
                   10686:         );
                   10687: 
                   10688:     /**
                   10689:      * PEAR_Command_Config constructor.
                   10690:      *
                   10691:      * @access public
                   10692:      */
                   10693:     function PEAR_Command_Config(&$ui, &$config)
                   10694:     {
                   10695:         parent::PEAR_Command_Common($ui, $config);
                   10696:     }
                   10697: 
                   10698:     function doConfigShow($command, $options, $params)
                   10699:     {
                   10700:         $layer = null;
                   10701:         if (is_array($params)) {
                   10702:             $layer = isset($params[0]) ? $params[0] : null;
                   10703:         }
                   10704: 
                   10705:         // $params[0] -> the layer
                   10706:         if ($error = $this->_checkLayer($layer)) {
                   10707:             return $this->raiseError("config-show:$error");
                   10708:         }
                   10709: 
                   10710:         $keys = $this->config->getKeys();
                   10711:         sort($keys);
                   10712:         $channel = isset($options['channel']) ? $options['channel'] :
                   10713:             $this->config->get('default_channel');
                   10714:         $reg = &$this->config->getRegistry();
                   10715:         if (!$reg->channelExists($channel)) {
                   10716:             return $this->raiseError('Channel "' . $channel . '" does not exist');
                   10717:         }
                   10718: 
                   10719:         $channel = $reg->channelName($channel);
                   10720:         $data = array('caption' => 'Configuration (channel ' . $channel . '):');
                   10721:         foreach ($keys as $key) {
                   10722:             $type = $this->config->getType($key);
                   10723:             $value = $this->config->get($key, $layer, $channel);
                   10724:             if ($type == 'password' && $value) {
                   10725:                 $value = '********';
                   10726:             }
                   10727: 
                   10728:             if ($value === false) {
                   10729:                 $value = 'false';
                   10730:             } elseif ($value === true) {
                   10731:                 $value = 'true';
                   10732:             }
                   10733: 
                   10734:             $data['data'][$this->config->getGroup($key)][] = array($this->config->getPrompt($key) , $key, $value);
                   10735:         }
                   10736: 
                   10737:         foreach ($this->config->getLayers() as $layer) {
                   10738:             $data['data']['Config Files'][] = array(ucfirst($layer) . ' Configuration File', 'Filename' , $this->config->getConfFile($layer));
                   10739:         }
                   10740: 
                   10741:         $this->ui->outputData($data, $command);
                   10742:         return true;
                   10743:     }
                   10744: 
                   10745:     function doConfigGet($command, $options, $params)
                   10746:     {
                   10747:         $args_cnt = is_array($params) ? count($params) : 0;
                   10748:         switch ($args_cnt) {
                   10749:             case 1:
                   10750:                 $config_key = $params[0];
                   10751:                 $layer = null;
                   10752:                 break;
                   10753:             case 2:
                   10754:                 $config_key = $params[0];
                   10755:                 $layer = $params[1];
                   10756:                 if ($error = $this->_checkLayer($layer)) {
                   10757:                     return $this->raiseError("config-get:$error");
                   10758:                 }
                   10759:                 break;
                   10760:             case 0:
                   10761:             default:
                   10762:                 return $this->raiseError("config-get expects 1 or 2 parameters");
                   10763:         }
                   10764: 
                   10765:         $reg = &$this->config->getRegistry();
                   10766:         $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
                   10767:         if (!$reg->channelExists($channel)) {
                   10768:             return $this->raiseError('Channel "' . $channel . '" does not exist');
                   10769:         }
                   10770: 
                   10771:         $channel = $reg->channelName($channel);
                   10772:         $this->ui->outputData($this->config->get($config_key, $layer, $channel), $command);
                   10773:         return true;
                   10774:     }
                   10775: 
                   10776:     function doConfigSet($command, $options, $params)
                   10777:     {
                   10778:         // $param[0] -> a parameter to set
                   10779:         // $param[1] -> the value for the parameter
                   10780:         // $param[2] -> the layer
                   10781:         $failmsg = '';
                   10782:         if (count($params) < 2 || count($params) > 3) {
                   10783:             $failmsg .= "config-set expects 2 or 3 parameters";
                   10784:             return PEAR::raiseError($failmsg);
                   10785:         }
                   10786: 
                   10787:         if (isset($params[2]) && ($error = $this->_checkLayer($params[2]))) {
                   10788:             $failmsg .= $error;
                   10789:             return PEAR::raiseError("config-set:$failmsg");
                   10790:         }
                   10791: 
                   10792:         $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
                   10793:         $reg = &$this->config->getRegistry();
                   10794:         if (!$reg->channelExists($channel)) {
                   10795:             return $this->raiseError('Channel "' . $channel . '" does not exist');
                   10796:         }
                   10797: 
                   10798:         $channel = $reg->channelName($channel);
                   10799:         if ($params[0] == 'default_channel' && !$reg->channelExists($params[1])) {
                   10800:             return $this->raiseError('Channel "' . $params[1] . '" does not exist');
                   10801:         }
                   10802: 
                   10803:         if ($params[0] == 'preferred_mirror'
                   10804:             && (
                   10805:                 !$reg->mirrorExists($channel, $params[1]) &&
                   10806:                 (!$reg->channelExists($params[1]) || $channel != $params[1])
                   10807:             )
                   10808:         ) {
                   10809:             $msg  = 'Channel Mirror "' . $params[1] . '" does not exist';
                   10810:             $msg .= ' in your registry for channel "' . $channel . '".';
                   10811:             $msg .= "\n" . 'Attempt to run "pear channel-update ' . $channel .'"';
                   10812:             $msg .= ' if you believe this mirror should exist as you may';
                   10813:             $msg .= ' have outdated channel information.';
                   10814:             return $this->raiseError($msg);
                   10815:         }
                   10816: 
                   10817:         if (count($params) == 2) {
                   10818:             array_push($params, 'user');
                   10819:             $layer = 'user';
                   10820:         } else {
                   10821:             $layer = $params[2];
                   10822:         }
                   10823: 
                   10824:         array_push($params, $channel);
                   10825:         if (!call_user_func_array(array(&$this->config, 'set'), $params)) {
                   10826:             array_pop($params);
                   10827:             $failmsg = "config-set (" . implode(", ", $params) . ") failed, channel $channel";
                   10828:         } else {
                   10829:             $this->config->store($layer);
                   10830:         }
                   10831: 
                   10832:         if ($failmsg) {
                   10833:             return $this->raiseError($failmsg);
                   10834:         }
                   10835: 
                   10836:         $this->ui->outputData('config-set succeeded', $command);
                   10837:         return true;
                   10838:     }
                   10839: 
                   10840:     function doConfigHelp($command, $options, $params)
                   10841:     {
                   10842:         if (empty($params)) {
                   10843:             $params = $this->config->getKeys();
                   10844:         }
                   10845: 
                   10846:         $data['caption']  = "Config help" . ((count($params) == 1) ? " for $params[0]" : '');
                   10847:         $data['headline'] = array('Name', 'Type', 'Description');
                   10848:         $data['border']   = true;
                   10849:         foreach ($params as $name) {
                   10850:             $type = $this->config->getType($name);
                   10851:             $docs = $this->config->getDocs($name);
                   10852:             if ($type == 'set') {
                   10853:                 $docs = rtrim($docs) . "\nValid set: " .
                   10854:                     implode(' ', $this->config->getSetValues($name));
                   10855:             }
                   10856: 
                   10857:             $data['data'][] = array($name, $type, $docs);
                   10858:         }
                   10859: 
                   10860:         $this->ui->outputData($data, $command);
                   10861:     }
                   10862: 
                   10863:     function doConfigCreate($command, $options, $params)
                   10864:     {
                   10865:         if (count($params) != 2) {
                   10866:             return PEAR::raiseError('config-create: must have 2 parameters, root path and ' .
                   10867:                 'filename to save as');
                   10868:         }
                   10869: 
                   10870:         $root = $params[0];
                   10871:         // Clean up the DIRECTORY_SEPARATOR mess
                   10872:         $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
                   10873:         $root = preg_replace(array('!\\\\+!', '!/+!', "!$ds2+!"),
                   10874:                              array('/', '/', '/'),
                   10875:                             $root);
                   10876:         if ($root{0} != '/') {
                   10877:             if (!isset($options['windows'])) {
                   10878:                 return PEAR::raiseError('Root directory must be an absolute path beginning ' .
                   10879:                     'with "/", was: "' . $root . '"');
                   10880:             }
                   10881: 
                   10882:             if (!preg_match('/^[A-Za-z]:/', $root)) {
                   10883:                 return PEAR::raiseError('Root directory must be an absolute path beginning ' .
                   10884:                     'with "\\" or "C:\\", was: "' . $root . '"');
                   10885:             }
                   10886:         }
                   10887: 
                   10888:         $windows = isset($options['windows']);
                   10889:         if ($windows) {
                   10890:             $root = str_replace('/', '\\', $root);
                   10891:         }
                   10892: 
                   10893:         if (!file_exists($params[1]) && !@touch($params[1])) {
                   10894:             return PEAR::raiseError('Could not create "' . $params[1] . '"');
                   10895:         }
                   10896: 
                   10897:         $params[1] = realpath($params[1]);
                   10898:         $config = &new PEAR_Config($params[1], '#no#system#config#', false, false);
                   10899:         if ($root{strlen($root) - 1} == '/') {
                   10900:             $root = substr($root, 0, strlen($root) - 1);
                   10901:         }
                   10902: 
                   10903:         $config->noRegistry();
                   10904:         $config->set('php_dir', $windows ? "$root\\pear\\php" : "$root/pear/php", 'user');
                   10905:         $config->set('data_dir', $windows ? "$root\\pear\\data" : "$root/pear/data");
                   10906:         $config->set('www_dir', $windows ? "$root\\pear\\www" : "$root/pear/www");
                   10907:         $config->set('cfg_dir', $windows ? "$root\\pear\\cfg" : "$root/pear/cfg");
                   10908:         $config->set('ext_dir', $windows ? "$root\\pear\\ext" : "$root/pear/ext");
                   10909:         $config->set('doc_dir', $windows ? "$root\\pear\\docs" : "$root/pear/docs");
                   10910:         $config->set('test_dir', $windows ? "$root\\pear\\tests" : "$root/pear/tests");
                   10911:         $config->set('cache_dir', $windows ? "$root\\pear\\cache" : "$root/pear/cache");
                   10912:         $config->set('download_dir', $windows ? "$root\\pear\\download" : "$root/pear/download");
                   10913:         $config->set('temp_dir', $windows ? "$root\\pear\\temp" : "$root/pear/temp");
                   10914:         $config->set('bin_dir', $windows ? "$root\\pear" : "$root/pear");
                   10915:         $config->writeConfigFile();
                   10916:         $this->_showConfig($config);
                   10917:         $this->ui->outputData('Successfully created default configuration file "' . $params[1] . '"',
                   10918:             $command);
                   10919:     }
                   10920: 
                   10921:     function _showConfig(&$config)
                   10922:     {
                   10923:         $params = array('user');
                   10924:         $keys = $config->getKeys();
                   10925:         sort($keys);
                   10926:         $channel = 'pear.php.net';
                   10927:         $data = array('caption' => 'Configuration (channel ' . $channel . '):');
                   10928:         foreach ($keys as $key) {
                   10929:             $type = $config->getType($key);
                   10930:             $value = $config->get($key, 'user', $channel);
                   10931:             if ($type == 'password' && $value) {
                   10932:                 $value = '********';
                   10933:             }
                   10934: 
                   10935:             if ($value === false) {
                   10936:                 $value = 'false';
                   10937:             } elseif ($value === true) {
                   10938:                 $value = 'true';
                   10939:             }
                   10940:             $data['data'][$config->getGroup($key)][] =
                   10941:                 array($config->getPrompt($key) , $key, $value);
                   10942:         }
                   10943: 
                   10944:         foreach ($config->getLayers() as $layer) {
                   10945:             $data['data']['Config Files'][] =
                   10946:                 array(ucfirst($layer) . ' Configuration File', 'Filename' ,
                   10947:                     $config->getConfFile($layer));
                   10948:         }
                   10949: 
                   10950:         $this->ui->outputData($data, 'config-show');
                   10951:         return true;
                   10952:     }
                   10953: 
                   10954:     /**
                   10955:      * Checks if a layer is defined or not
                   10956:      *
                   10957:      * @param string $layer The layer to search for
                   10958:      * @return mixed False on no error or the error message
                   10959:      */
                   10960:     function _checkLayer($layer = null)
                   10961:     {
                   10962:         if (!empty($layer) && $layer != 'default') {
                   10963:             $layers = $this->config->getLayers();
                   10964:             if (!in_array($layer, $layers)) {
                   10965:                 return " only the layers: \"" . implode('" or "', $layers) . "\" are supported";
                   10966:             }
                   10967:         }
                   10968: 
                   10969:         return false;
                   10970:     }
1.1.1.2 ! misho    10971: }PEAR-1.9.4/PEAR/Command/Install.xml0000644000076500000240000002057611605156614015503 0ustar  helgistaff<commands version="1.0">
1.1       misho    10972:  <install>
                   10973:   <summary>Install Package</summary>
                   10974:   <function>doInstall</function>
                   10975:   <shortcut>i</shortcut>
                   10976:   <options>
                   10977:    <force>
                   10978:     <shortopt>f</shortopt>
                   10979:     <doc>will overwrite newer installed packages</doc>
                   10980:    </force>
                   10981:    <loose>
                   10982:     <shortopt>l</shortopt>
                   10983:     <doc>do not check for recommended dependency version</doc>
                   10984:    </loose>
                   10985:    <nodeps>
                   10986:     <shortopt>n</shortopt>
                   10987:     <doc>ignore dependencies, install anyway</doc>
                   10988:    </nodeps>
                   10989:    <register-only>
                   10990:     <shortopt>r</shortopt>
                   10991:     <doc>do not install files, only register the package as installed</doc>
                   10992:    </register-only>
                   10993:    <soft>
                   10994:     <shortopt>s</shortopt>
                   10995:     <doc>soft install, fail silently, or upgrade if already installed</doc>
                   10996:    </soft>
                   10997:    <nobuild>
                   10998:     <shortopt>B</shortopt>
                   10999:     <doc>don&#039;t build C extensions</doc>
                   11000:    </nobuild>
                   11001:    <nocompress>
                   11002:     <shortopt>Z</shortopt>
                   11003:     <doc>request uncompressed files when downloading</doc>
                   11004:    </nocompress>
                   11005:    <installroot>
                   11006:     <shortopt>R</shortopt>
                   11007:     <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT), use packagingroot for RPM</doc>
                   11008:     <arg>DIR</arg>
                   11009:    </installroot>
                   11010:    <packagingroot>
                   11011:     <shortopt>P</shortopt>
                   11012:     <doc>root directory used when packaging files, like RPM packaging</doc>
                   11013:     <arg>DIR</arg>
                   11014:    </packagingroot>
                   11015:    <ignore-errors>
                   11016:     <shortopt></shortopt>
                   11017:     <doc>force install even if there were errors</doc>
                   11018:    </ignore-errors>
                   11019:    <alldeps>
                   11020:     <shortopt>a</shortopt>
                   11021:     <doc>install all required and optional dependencies</doc>
                   11022:    </alldeps>
                   11023:    <onlyreqdeps>
                   11024:     <shortopt>o</shortopt>
                   11025:     <doc>install all required dependencies</doc>
                   11026:    </onlyreqdeps>
                   11027:    <offline>
                   11028:     <shortopt>O</shortopt>
                   11029:     <doc>do not attempt to download any urls or contact channels</doc>
                   11030:    </offline>
                   11031:    <pretend>
                   11032:     <shortopt>p</shortopt>
                   11033:     <doc>Only list the packages that would be downloaded</doc>
                   11034:    </pretend>
                   11035:   </options>
                   11036:   <doc>[channel/]&lt;package&gt; ...
                   11037: Installs one or more PEAR packages.  You can specify a package to
                   11038: install in four ways:
                   11039: 
                   11040: &quot;Package-1.0.tgz&quot; : installs from a local file
                   11041: 
                   11042: &quot;http://example.com/Package-1.0.tgz&quot; : installs from
                   11043: anywhere on the net.
                   11044: 
                   11045: &quot;package.xml&quot; : installs the package described in
                   11046: package.xml.  Useful for testing, or for wrapping a PEAR package in
                   11047: another package manager such as RPM.
                   11048: 
                   11049: &quot;Package[-version/state][.tar]&quot; : queries your default channel&#039;s server
                   11050: ({config master_server}) and downloads the newest package with
                   11051: the preferred quality/state ({config preferred_state}).
                   11052: 
                   11053: To retrieve Package version 1.1, use &quot;Package-1.1,&quot; to retrieve
                   11054: Package state beta, use &quot;Package-beta.&quot;  To retrieve an uncompressed
                   11055: file, append .tar (make sure there is no file by the same name first)
                   11056: 
                   11057: To download a package from another channel, prefix with the channel name like
                   11058: &quot;channel/Package&quot;
                   11059: 
                   11060: More than one package may be specified at once.  It is ok to mix these
                   11061: four ways of specifying packages.
                   11062: </doc>
                   11063:  </install>
                   11064:  <upgrade>
                   11065:   <summary>Upgrade Package</summary>
                   11066:   <function>doInstall</function>
                   11067:   <shortcut>up</shortcut>
                   11068:   <options>
                   11069:    <channel>
                   11070:     <shortopt>c</shortopt>
                   11071:     <doc>upgrade packages from a specific channel</doc>
                   11072:     <arg>CHAN</arg>
                   11073:    </channel>
                   11074:    <force>
                   11075:     <shortopt>f</shortopt>
                   11076:     <doc>overwrite newer installed packages</doc>
                   11077:    </force>
                   11078:    <loose>
                   11079:     <shortopt>l</shortopt>
                   11080:     <doc>do not check for recommended dependency version</doc>
                   11081:    </loose>
                   11082:    <nodeps>
                   11083:     <shortopt>n</shortopt>
                   11084:     <doc>ignore dependencies, upgrade anyway</doc>
                   11085:    </nodeps>
                   11086:    <register-only>
                   11087:     <shortopt>r</shortopt>
                   11088:     <doc>do not install files, only register the package as upgraded</doc>
                   11089:    </register-only>
                   11090:    <nobuild>
                   11091:     <shortopt>B</shortopt>
                   11092:     <doc>don&#039;t build C extensions</doc>
                   11093:    </nobuild>
                   11094:    <nocompress>
                   11095:     <shortopt>Z</shortopt>
                   11096:     <doc>request uncompressed files when downloading</doc>
                   11097:    </nocompress>
                   11098:    <installroot>
                   11099:     <shortopt>R</shortopt>
                   11100:     <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT)</doc>
                   11101:     <arg>DIR</arg>
                   11102:    </installroot>
                   11103:    <ignore-errors>
                   11104:     <shortopt></shortopt>
                   11105:     <doc>force install even if there were errors</doc>
                   11106:    </ignore-errors>
                   11107:    <alldeps>
                   11108:     <shortopt>a</shortopt>
                   11109:     <doc>install all required and optional dependencies</doc>
                   11110:    </alldeps>
                   11111:    <onlyreqdeps>
                   11112:     <shortopt>o</shortopt>
                   11113:     <doc>install all required dependencies</doc>
                   11114:    </onlyreqdeps>
                   11115:    <offline>
                   11116:     <shortopt>O</shortopt>
                   11117:     <doc>do not attempt to download any urls or contact channels</doc>
                   11118:    </offline>
                   11119:    <pretend>
                   11120:     <shortopt>p</shortopt>
                   11121:     <doc>Only list the packages that would be downloaded</doc>
                   11122:    </pretend>
                   11123:   </options>
                   11124:   <doc>&lt;package&gt; ...
                   11125: Upgrades one or more PEAR packages.  See documentation for the
                   11126: &quot;install&quot; command for ways to specify a package.
                   11127: 
                   11128: When upgrading, your package will be updated if the provided new
                   11129: package has a higher version number (use the -f option if you need to
                   11130: upgrade anyway).
                   11131: 
                   11132: More than one package may be specified at once.
                   11133: </doc>
                   11134:  </upgrade>
                   11135:  <upgrade-all>
                   11136:   <summary>Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]</summary>
                   11137:   <function>doUpgradeAll</function>
                   11138:   <shortcut>ua</shortcut>
                   11139:   <options>
                   11140:    <channel>
                   11141:     <shortopt>c</shortopt>
                   11142:     <doc>upgrade packages from a specific channel</doc>
                   11143:     <arg>CHAN</arg>
                   11144:    </channel>
                   11145:    <nodeps>
                   11146:     <shortopt>n</shortopt>
                   11147:     <doc>ignore dependencies, upgrade anyway</doc>
                   11148:    </nodeps>
                   11149:    <register-only>
                   11150:     <shortopt>r</shortopt>
                   11151:     <doc>do not install files, only register the package as upgraded</doc>
                   11152:    </register-only>
                   11153:    <nobuild>
                   11154:     <shortopt>B</shortopt>
                   11155:     <doc>don&#039;t build C extensions</doc>
                   11156:    </nobuild>
                   11157:    <nocompress>
                   11158:     <shortopt>Z</shortopt>
                   11159:     <doc>request uncompressed files when downloading</doc>
                   11160:    </nocompress>
                   11161:    <installroot>
                   11162:     <shortopt>R</shortopt>
                   11163:     <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT), use packagingroot for RPM</doc>
                   11164:     <arg>DIR</arg>
                   11165:    </installroot>
                   11166:    <ignore-errors>
                   11167:     <shortopt></shortopt>
                   11168:     <doc>force install even if there were errors</doc>
                   11169:    </ignore-errors>
                   11170:    <loose>
                   11171:     <shortopt></shortopt>
                   11172:     <doc>do not check for recommended dependency version</doc>
                   11173:    </loose>
                   11174:   </options>
                   11175:   <doc>
                   11176: WARNING: This function is deprecated in favor of using the upgrade command with no params
                   11177: 
                   11178: Upgrades all packages that have a newer release available.  Upgrades are
                   11179: done only if there is a release available of the state specified in
                   11180: &quot;preferred_state&quot; (currently {config preferred_state}), or a state considered
                   11181: more stable.
                   11182: </doc>
                   11183:  </upgrade-all>
                   11184:  <uninstall>
                   11185:   <summary>Un-install Package</summary>
                   11186:   <function>doUninstall</function>
                   11187:   <shortcut>un</shortcut>
                   11188:   <options>
                   11189:    <nodeps>
                   11190:     <shortopt>n</shortopt>
                   11191:     <doc>ignore dependencies, uninstall anyway</doc>
                   11192:    </nodeps>
                   11193:    <register-only>
                   11194:     <shortopt>r</shortopt>
                   11195:     <doc>do not remove files, only register the packages as not installed</doc>
                   11196:    </register-only>
                   11197:    <installroot>
                   11198:     <shortopt>R</shortopt>
                   11199:     <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT)</doc>
                   11200:     <arg>DIR</arg>
                   11201:    </installroot>
                   11202:    <ignore-errors>
                   11203:     <shortopt></shortopt>
                   11204:     <doc>force install even if there were errors</doc>
                   11205:    </ignore-errors>
                   11206:    <offline>
                   11207:     <shortopt>O</shortopt>
                   11208:     <doc>do not attempt to uninstall remotely</doc>
                   11209:    </offline>
                   11210:   </options>
                   11211:   <doc>[channel/]&lt;package&gt; ...
                   11212: Uninstalls one or more PEAR packages.  More than one package may be
                   11213: specified at once.  Prefix with channel name to uninstall from a
                   11214: channel not in your default channel ({config default_channel})
                   11215: </doc>
                   11216:  </uninstall>
                   11217:  <bundle>
                   11218:   <summary>Unpacks a Pecl Package</summary>
                   11219:   <function>doBundle</function>
                   11220:   <shortcut>bun</shortcut>
                   11221:   <options>
                   11222:    <destination>
                   11223:     <shortopt>d</shortopt>
                   11224:     <doc>Optional destination directory for unpacking (defaults to current path or &quot;ext&quot; if exists)</doc>
                   11225:     <arg>DIR</arg>
                   11226:    </destination>
                   11227:    <force>
                   11228:     <shortopt>f</shortopt>
                   11229:     <doc>Force the unpacking even if there were errors in the package</doc>
                   11230:    </force>
                   11231:   </options>
                   11232:   <doc>&lt;package&gt;
                   11233: Unpacks a Pecl Package into the selected location. It will download the
                   11234: package if needed.
                   11235: </doc>
                   11236:  </bundle>
                   11237:  <run-scripts>
                   11238:   <summary>Run Post-Install Scripts bundled with a package</summary>
                   11239:   <function>doRunScripts</function>
                   11240:   <shortcut>rs</shortcut>
                   11241:   <options />
                   11242:   <doc>&lt;package&gt;
                   11243: Run post-installation scripts in package &lt;package&gt;, if any exist.
                   11244: </doc>
                   11245:  </run-scripts>
1.1.1.2 ! misho    11246: </commands>PEAR-1.9.4/PEAR/Command/Install.php0000644000076500000240000014323611605156614015471 0ustar  helgistaff<?php
1.1       misho    11247: /**
                   11248:  * PEAR_Command_Install (install, upgrade, upgrade-all, uninstall, bundle, run-scripts commands)
                   11249:  *
                   11250:  * PHP versions 4 and 5
                   11251:  *
                   11252:  * @category   pear
                   11253:  * @package    PEAR
                   11254:  * @author     Stig Bakken <ssb@php.net>
                   11255:  * @author     Greg Beaver <cellog@php.net>
                   11256:  * @copyright  1997-2009 The Authors
                   11257:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   11258:  * @version    CVS: $Id: Install.php 313023 2011-07-06 19:17:11Z dufuz $
                   11259:  * @link       http://pear.php.net/package/PEAR
                   11260:  * @since      File available since Release 0.1
                   11261:  */
                   11262: 
                   11263: /**
                   11264:  * base class
                   11265:  */
                   11266: require_once 'PEAR/Command/Common.php';
                   11267: 
                   11268: /**
                   11269:  * PEAR commands for installation or deinstallation/upgrading of
                   11270:  * packages.
                   11271:  *
                   11272:  * @category   pear
                   11273:  * @package    PEAR
                   11274:  * @author     Stig Bakken <ssb@php.net>
                   11275:  * @author     Greg Beaver <cellog@php.net>
                   11276:  * @copyright  1997-2009 The Authors
                   11277:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   11278:  * @version    Release: 1.9.4
                   11279:  * @link       http://pear.php.net/package/PEAR
                   11280:  * @since      Class available since Release 0.1
                   11281:  */
                   11282: class PEAR_Command_Install extends PEAR_Command_Common
                   11283: {
                   11284:     // {{{ properties
                   11285: 
                   11286:     var $commands = array(
                   11287:         'install' => array(
                   11288:             'summary' => 'Install Package',
                   11289:             'function' => 'doInstall',
                   11290:             'shortcut' => 'i',
                   11291:             'options' => array(
                   11292:                 'force' => array(
                   11293:                     'shortopt' => 'f',
                   11294:                     'doc' => 'will overwrite newer installed packages',
                   11295:                     ),
                   11296:                 'loose' => array(
                   11297:                     'shortopt' => 'l',
                   11298:                     'doc' => 'do not check for recommended dependency version',
                   11299:                     ),
                   11300:                 'nodeps' => array(
                   11301:                     'shortopt' => 'n',
                   11302:                     'doc' => 'ignore dependencies, install anyway',
                   11303:                     ),
                   11304:                 'register-only' => array(
                   11305:                     'shortopt' => 'r',
                   11306:                     'doc' => 'do not install files, only register the package as installed',
                   11307:                     ),
                   11308:                 'soft' => array(
                   11309:                     'shortopt' => 's',
                   11310:                     'doc' => 'soft install, fail silently, or upgrade if already installed',
                   11311:                     ),
                   11312:                 'nobuild' => array(
                   11313:                     'shortopt' => 'B',
                   11314:                     'doc' => 'don\'t build C extensions',
                   11315:                     ),
                   11316:                 'nocompress' => array(
                   11317:                     'shortopt' => 'Z',
                   11318:                     'doc' => 'request uncompressed files when downloading',
                   11319:                     ),
                   11320:                 'installroot' => array(
                   11321:                     'shortopt' => 'R',
                   11322:                     'arg' => 'DIR',
                   11323:                     'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
                   11324:                     ),
                   11325:                 'packagingroot' => array(
                   11326:                     'shortopt' => 'P',
                   11327:                     'arg' => 'DIR',
                   11328:                     'doc' => 'root directory used when packaging files, like RPM packaging',
                   11329:                     ),
                   11330:                 'ignore-errors' => array(
                   11331:                     'doc' => 'force install even if there were errors',
                   11332:                     ),
                   11333:                 'alldeps' => array(
                   11334:                     'shortopt' => 'a',
                   11335:                     'doc' => 'install all required and optional dependencies',
                   11336:                     ),
                   11337:                 'onlyreqdeps' => array(
                   11338:                     'shortopt' => 'o',
                   11339:                     'doc' => 'install all required dependencies',
                   11340:                     ),
                   11341:                 'offline' => array(
                   11342:                     'shortopt' => 'O',
                   11343:                     'doc' => 'do not attempt to download any urls or contact channels',
                   11344:                     ),
                   11345:                 'pretend' => array(
                   11346:                     'shortopt' => 'p',
                   11347:                     'doc' => 'Only list the packages that would be downloaded',
                   11348:                     ),
                   11349:                 ),
                   11350:             'doc' => '[channel/]<package> ...
                   11351: Installs one or more PEAR packages.  You can specify a package to
                   11352: install in four ways:
                   11353: 
                   11354: "Package-1.0.tgz" : installs from a local file
                   11355: 
                   11356: "http://example.com/Package-1.0.tgz" : installs from
                   11357: anywhere on the net.
                   11358: 
                   11359: "package.xml" : installs the package described in
                   11360: package.xml.  Useful for testing, or for wrapping a PEAR package in
                   11361: another package manager such as RPM.
                   11362: 
                   11363: "Package[-version/state][.tar]" : queries your default channel\'s server
                   11364: ({config master_server}) and downloads the newest package with
                   11365: the preferred quality/state ({config preferred_state}).
                   11366: 
                   11367: To retrieve Package version 1.1, use "Package-1.1," to retrieve
                   11368: Package state beta, use "Package-beta."  To retrieve an uncompressed
                   11369: file, append .tar (make sure there is no file by the same name first)
                   11370: 
                   11371: To download a package from another channel, prefix with the channel name like
                   11372: "channel/Package"
                   11373: 
                   11374: More than one package may be specified at once.  It is ok to mix these
                   11375: four ways of specifying packages.
                   11376: '),
                   11377:         'upgrade' => array(
                   11378:             'summary' => 'Upgrade Package',
                   11379:             'function' => 'doInstall',
                   11380:             'shortcut' => 'up',
                   11381:             'options' => array(
                   11382:                 'channel' => array(
                   11383:                     'shortopt' => 'c',
                   11384:                     'doc' => 'upgrade packages from a specific channel',
                   11385:                     'arg' => 'CHAN',
                   11386:                     ),
                   11387:                 'force' => array(
                   11388:                     'shortopt' => 'f',
                   11389:                     'doc' => 'overwrite newer installed packages',
                   11390:                     ),
                   11391:                 'loose' => array(
                   11392:                     'shortopt' => 'l',
                   11393:                     'doc' => 'do not check for recommended dependency version',
                   11394:                     ),
                   11395:                 'nodeps' => array(
                   11396:                     'shortopt' => 'n',
                   11397:                     'doc' => 'ignore dependencies, upgrade anyway',
                   11398:                     ),
                   11399:                 'register-only' => array(
                   11400:                     'shortopt' => 'r',
                   11401:                     'doc' => 'do not install files, only register the package as upgraded',
                   11402:                     ),
                   11403:                 'nobuild' => array(
                   11404:                     'shortopt' => 'B',
                   11405:                     'doc' => 'don\'t build C extensions',
                   11406:                     ),
                   11407:                 'nocompress' => array(
                   11408:                     'shortopt' => 'Z',
                   11409:                     'doc' => 'request uncompressed files when downloading',
                   11410:                     ),
                   11411:                 'installroot' => array(
                   11412:                     'shortopt' => 'R',
                   11413:                     'arg' => 'DIR',
                   11414:                     'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
                   11415:                     ),
                   11416:                 'ignore-errors' => array(
                   11417:                     'doc' => 'force install even if there were errors',
                   11418:                     ),
                   11419:                 'alldeps' => array(
                   11420:                     'shortopt' => 'a',
                   11421:                     'doc' => 'install all required and optional dependencies',
                   11422:                     ),
                   11423:                 'onlyreqdeps' => array(
                   11424:                     'shortopt' => 'o',
                   11425:                     'doc' => 'install all required dependencies',
                   11426:                     ),
                   11427:                 'offline' => array(
                   11428:                     'shortopt' => 'O',
                   11429:                     'doc' => 'do not attempt to download any urls or contact channels',
                   11430:                     ),
                   11431:                 'pretend' => array(
                   11432:                     'shortopt' => 'p',
                   11433:                     'doc' => 'Only list the packages that would be downloaded',
                   11434:                     ),
                   11435:                 ),
                   11436:             'doc' => '<package> ...
                   11437: Upgrades one or more PEAR packages.  See documentation for the
                   11438: "install" command for ways to specify a package.
                   11439: 
                   11440: When upgrading, your package will be updated if the provided new
                   11441: package has a higher version number (use the -f option if you need to
                   11442: upgrade anyway).
                   11443: 
                   11444: More than one package may be specified at once.
                   11445: '),
                   11446:         'upgrade-all' => array(
                   11447:             'summary' => 'Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]',
                   11448:             'function' => 'doUpgradeAll',
                   11449:             'shortcut' => 'ua',
                   11450:             'options' => array(
                   11451:                 'channel' => array(
                   11452:                     'shortopt' => 'c',
                   11453:                     'doc' => 'upgrade packages from a specific channel',
                   11454:                     'arg' => 'CHAN',
                   11455:                     ),
                   11456:                 'nodeps' => array(
                   11457:                     'shortopt' => 'n',
                   11458:                     'doc' => 'ignore dependencies, upgrade anyway',
                   11459:                     ),
                   11460:                 'register-only' => array(
                   11461:                     'shortopt' => 'r',
                   11462:                     'doc' => 'do not install files, only register the package as upgraded',
                   11463:                     ),
                   11464:                 'nobuild' => array(
                   11465:                     'shortopt' => 'B',
                   11466:                     'doc' => 'don\'t build C extensions',
                   11467:                     ),
                   11468:                 'nocompress' => array(
                   11469:                     'shortopt' => 'Z',
                   11470:                     'doc' => 'request uncompressed files when downloading',
                   11471:                     ),
                   11472:                 'installroot' => array(
                   11473:                     'shortopt' => 'R',
                   11474:                     'arg' => 'DIR',
                   11475:                     'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
                   11476:                     ),
                   11477:                 'ignore-errors' => array(
                   11478:                     'doc' => 'force install even if there were errors',
                   11479:                     ),
                   11480:                 'loose' => array(
                   11481:                     'doc' => 'do not check for recommended dependency version',
                   11482:                     ),
                   11483:                 ),
                   11484:             'doc' => '
                   11485: WARNING: This function is deprecated in favor of using the upgrade command with no params
                   11486: 
                   11487: Upgrades all packages that have a newer release available.  Upgrades are
                   11488: done only if there is a release available of the state specified in
                   11489: "preferred_state" (currently {config preferred_state}), or a state considered
                   11490: more stable.
                   11491: '),
                   11492:         'uninstall' => array(
                   11493:             'summary' => 'Un-install Package',
                   11494:             'function' => 'doUninstall',
                   11495:             'shortcut' => 'un',
                   11496:             'options' => array(
                   11497:                 'nodeps' => array(
                   11498:                     'shortopt' => 'n',
                   11499:                     'doc' => 'ignore dependencies, uninstall anyway',
                   11500:                     ),
                   11501:                 'register-only' => array(
                   11502:                     'shortopt' => 'r',
                   11503:                     'doc' => 'do not remove files, only register the packages as not installed',
                   11504:                     ),
                   11505:                 'installroot' => array(
                   11506:                     'shortopt' => 'R',
                   11507:                     'arg' => 'DIR',
                   11508:                     'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
                   11509:                     ),
                   11510:                 'ignore-errors' => array(
                   11511:                     'doc' => 'force install even if there were errors',
                   11512:                     ),
                   11513:                 'offline' => array(
                   11514:                     'shortopt' => 'O',
                   11515:                     'doc' => 'do not attempt to uninstall remotely',
                   11516:                     ),
                   11517:                 ),
                   11518:             'doc' => '[channel/]<package> ...
                   11519: Uninstalls one or more PEAR packages.  More than one package may be
                   11520: specified at once.  Prefix with channel name to uninstall from a
                   11521: channel not in your default channel ({config default_channel})
                   11522: '),
                   11523:         'bundle' => array(
                   11524:             'summary' => 'Unpacks a Pecl Package',
                   11525:             'function' => 'doBundle',
                   11526:             'shortcut' => 'bun',
                   11527:             'options' => array(
                   11528:                 'destination' => array(
                   11529:                    'shortopt' => 'd',
                   11530:                     'arg' => 'DIR',
                   11531:                     'doc' => 'Optional destination directory for unpacking (defaults to current path or "ext" if exists)',
                   11532:                     ),
                   11533:                 'force' => array(
                   11534:                     'shortopt' => 'f',
                   11535:                     'doc' => 'Force the unpacking even if there were errors in the package',
                   11536:                 ),
                   11537:             ),
                   11538:             'doc' => '<package>
                   11539: Unpacks a Pecl Package into the selected location. It will download the
                   11540: package if needed.
                   11541: '),
                   11542:         'run-scripts' => array(
                   11543:             'summary' => 'Run Post-Install Scripts bundled with a package',
                   11544:             'function' => 'doRunScripts',
                   11545:             'shortcut' => 'rs',
                   11546:             'options' => array(
                   11547:             ),
                   11548:             'doc' => '<package>
                   11549: Run post-installation scripts in package <package>, if any exist.
                   11550: '),
                   11551:     );
                   11552: 
                   11553:     // }}}
                   11554:     // {{{ constructor
                   11555: 
                   11556:     /**
                   11557:      * PEAR_Command_Install constructor.
                   11558:      *
                   11559:      * @access public
                   11560:      */
                   11561:     function PEAR_Command_Install(&$ui, &$config)
                   11562:     {
                   11563:         parent::PEAR_Command_Common($ui, $config);
                   11564:     }
                   11565: 
                   11566:     // }}}
                   11567: 
                   11568:     /**
                   11569:      * For unit testing purposes
                   11570:      */
                   11571:     function &getDownloader(&$ui, $options, &$config)
                   11572:     {
                   11573:         if (!class_exists('PEAR_Downloader')) {
                   11574:             require_once 'PEAR/Downloader.php';
                   11575:         }
                   11576:         $a = &new PEAR_Downloader($ui, $options, $config);
                   11577:         return $a;
                   11578:     }
                   11579: 
                   11580:     /**
                   11581:      * For unit testing purposes
                   11582:      */
                   11583:     function &getInstaller(&$ui)
                   11584:     {
                   11585:         if (!class_exists('PEAR_Installer')) {
                   11586:             require_once 'PEAR/Installer.php';
                   11587:         }
                   11588:         $a = &new PEAR_Installer($ui);
                   11589:         return $a;
                   11590:     }
                   11591: 
                   11592:     function enableExtension($binaries, $type)
                   11593:     {
                   11594:         if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) {
                   11595:             return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location');
                   11596:         }
                   11597:         $ini = $this->_parseIni($phpini);
                   11598:         if (PEAR::isError($ini)) {
                   11599:             return $ini;
                   11600:         }
                   11601:         $line = 0;
                   11602:         if ($type == 'extsrc' || $type == 'extbin') {
                   11603:             $search = 'extensions';
                   11604:             $enable = 'extension';
                   11605:         } else {
                   11606:             $search = 'zend_extensions';
                   11607:             ob_start();
                   11608:             phpinfo(INFO_GENERAL);
                   11609:             $info = ob_get_contents();
                   11610:             ob_end_clean();
                   11611:             $debug = function_exists('leak') ? '_debug' : '';
                   11612:             $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
                   11613:             $enable = 'zend_extension' . $debug . $ts;
                   11614:         }
                   11615:         foreach ($ini[$search] as $line => $extension) {
                   11616:             if (in_array($extension, $binaries, true) || in_array(
                   11617:                   $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) {
                   11618:                 // already enabled - assume if one is, all are
                   11619:                 return true;
                   11620:             }
                   11621:         }
                   11622:         if ($line) {
                   11623:             $newini = array_slice($ini['all'], 0, $line);
                   11624:         } else {
                   11625:             $newini = array();
                   11626:         }
                   11627:         foreach ($binaries as $binary) {
                   11628:             if ($ini['extension_dir']) {
                   11629:                 $binary = basename($binary);
                   11630:             }
                   11631:             $newini[] = $enable . '="' . $binary . '"' . (OS_UNIX ? "\n" : "\r\n");
                   11632:         }
                   11633:         $newini = array_merge($newini, array_slice($ini['all'], $line));
                   11634:         $fp = @fopen($phpini, 'wb');
                   11635:         if (!$fp) {
                   11636:             return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing');
                   11637:         }
                   11638:         foreach ($newini as $line) {
                   11639:             fwrite($fp, $line);
                   11640:         }
                   11641:         fclose($fp);
                   11642:         return true;
                   11643:     }
                   11644: 
                   11645:     function disableExtension($binaries, $type)
                   11646:     {
                   11647:         if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) {
                   11648:             return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location');
                   11649:         }
                   11650:         $ini = $this->_parseIni($phpini);
                   11651:         if (PEAR::isError($ini)) {
                   11652:             return $ini;
                   11653:         }
                   11654:         $line = 0;
                   11655:         if ($type == 'extsrc' || $type == 'extbin') {
                   11656:             $search = 'extensions';
                   11657:             $enable = 'extension';
                   11658:         } else {
                   11659:             $search = 'zend_extensions';
                   11660:             ob_start();
                   11661:             phpinfo(INFO_GENERAL);
                   11662:             $info = ob_get_contents();
                   11663:             ob_end_clean();
                   11664:             $debug = function_exists('leak') ? '_debug' : '';
                   11665:             $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
                   11666:             $enable = 'zend_extension' . $debug . $ts;
                   11667:         }
                   11668:         $found = false;
                   11669:         foreach ($ini[$search] as $line => $extension) {
                   11670:             if (in_array($extension, $binaries, true) || in_array(
                   11671:                   $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) {
                   11672:                 $found = true;
                   11673:                 break;
                   11674:             }
                   11675:         }
                   11676:         if (!$found) {
                   11677:             // not enabled
                   11678:             return true;
                   11679:         }
                   11680:         $fp = @fopen($phpini, 'wb');
                   11681:         if (!$fp) {
                   11682:             return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing');
                   11683:         }
                   11684:         if ($line) {
                   11685:             $newini = array_slice($ini['all'], 0, $line);
                   11686:             // delete the enable line
                   11687:             $newini = array_merge($newini, array_slice($ini['all'], $line + 1));
                   11688:         } else {
                   11689:             $newini = array_slice($ini['all'], 1);
                   11690:         }
                   11691:         foreach ($newini as $line) {
                   11692:             fwrite($fp, $line);
                   11693:         }
                   11694:         fclose($fp);
                   11695:         return true;
                   11696:     }
                   11697: 
                   11698:     function _parseIni($filename)
                   11699:     {
                   11700:         if (!file_exists($filename)) {
                   11701:             return PEAR::raiseError('php.ini "' . $filename . '" does not exist');
                   11702:         }
                   11703: 
                   11704:         if (filesize($filename) > 300000) {
                   11705:             return PEAR::raiseError('php.ini "' . $filename . '" is too large, aborting');
                   11706:         }
                   11707: 
                   11708:         ob_start();
                   11709:         phpinfo(INFO_GENERAL);
                   11710:         $info = ob_get_contents();
                   11711:         ob_end_clean();
                   11712:         $debug = function_exists('leak') ? '_debug' : '';
                   11713:         $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
                   11714:         $zend_extension_line = 'zend_extension' . $debug . $ts;
                   11715:         $all = @file($filename);
                   11716:         if (!$all) {
                   11717:             return PEAR::raiseError('php.ini "' . $filename .'" could not be read');
                   11718:         }
                   11719:         $zend_extensions = $extensions = array();
                   11720:         // assume this is right, but pull from the php.ini if it is found
                   11721:         $extension_dir = ini_get('extension_dir');
                   11722:         foreach ($all as $linenum => $line) {
                   11723:             $line = trim($line);
                   11724:             if (!$line) {
                   11725:                 continue;
                   11726:             }
                   11727:             if ($line[0] == ';') {
                   11728:                 continue;
                   11729:             }
                   11730:             if (strtolower(substr($line, 0, 13)) == 'extension_dir') {
                   11731:                 $line = trim(substr($line, 13));
                   11732:                 if ($line[0] == '=') {
                   11733:                     $x = trim(substr($line, 1));
                   11734:                     $x = explode(';', $x);
                   11735:                     $extension_dir = str_replace('"', '', array_shift($x));
                   11736:                     continue;
                   11737:                 }
                   11738:             }
                   11739:             if (strtolower(substr($line, 0, 9)) == 'extension') {
                   11740:                 $line = trim(substr($line, 9));
                   11741:                 if ($line[0] == '=') {
                   11742:                     $x = trim(substr($line, 1));
                   11743:                     $x = explode(';', $x);
                   11744:                     $extensions[$linenum] = str_replace('"', '', array_shift($x));
                   11745:                     continue;
                   11746:                 }
                   11747:             }
                   11748:             if (strtolower(substr($line, 0, strlen($zend_extension_line))) ==
                   11749:                   $zend_extension_line) {
                   11750:                 $line = trim(substr($line, strlen($zend_extension_line)));
                   11751:                 if ($line[0] == '=') {
                   11752:                     $x = trim(substr($line, 1));
                   11753:                     $x = explode(';', $x);
                   11754:                     $zend_extensions[$linenum] = str_replace('"', '', array_shift($x));
                   11755:                     continue;
                   11756:                 }
                   11757:             }
                   11758:         }
                   11759:         return array(
                   11760:             'extensions' => $extensions,
                   11761:             'zend_extensions' => $zend_extensions,
                   11762:             'extension_dir' => $extension_dir,
                   11763:             'all' => $all,
                   11764:         );
                   11765:     }
                   11766: 
                   11767:     // {{{ doInstall()
                   11768: 
                   11769:     function doInstall($command, $options, $params)
                   11770:     {
                   11771:         if (!class_exists('PEAR_PackageFile')) {
                   11772:             require_once 'PEAR/PackageFile.php';
                   11773:         }
                   11774: 
                   11775:         if (isset($options['installroot']) && isset($options['packagingroot'])) {
                   11776:             return $this->raiseError('ERROR: cannot use both --installroot and --packagingroot');
                   11777:         }
                   11778: 
                   11779:         $reg = &$this->config->getRegistry();
                   11780:         $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
                   11781:         if (!$reg->channelExists($channel)) {
                   11782:             return $this->raiseError('Channel "' . $channel . '" does not exist');
                   11783:         }
                   11784: 
                   11785:         if (empty($this->installer)) {
                   11786:             $this->installer = &$this->getInstaller($this->ui);
                   11787:         }
                   11788: 
                   11789:         if ($command == 'upgrade' || $command == 'upgrade-all') {
                   11790:             // If people run the upgrade command but pass nothing, emulate a upgrade-all
                   11791:             if ($command == 'upgrade' && empty($params)) {
                   11792:                 return $this->doUpgradeAll($command, $options, $params);
                   11793:             }
                   11794:             $options['upgrade'] = true;
                   11795:         } else {
                   11796:             $packages = $params;
                   11797:         }
                   11798: 
                   11799:         $instreg = &$reg; // instreg used to check if package is installed
                   11800:         if (isset($options['packagingroot']) && !isset($options['upgrade'])) {
                   11801:             $packrootphp_dir = $this->installer->_prependPath(
                   11802:                 $this->config->get('php_dir', null, 'pear.php.net'),
                   11803:                 $options['packagingroot']);
                   11804:             $instreg = new PEAR_Registry($packrootphp_dir); // other instreg!
                   11805: 
                   11806:             if ($this->config->get('verbose') > 2) {
                   11807:                 $this->ui->outputData('using package root: ' . $options['packagingroot']);
                   11808:             }
                   11809:         }
                   11810: 
                   11811:         $abstractpackages = $otherpackages = array();
                   11812:         // parse params
                   11813:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   11814: 
                   11815:         foreach ($params as $param) {
                   11816:             if (strpos($param, 'http://') === 0) {
                   11817:                 $otherpackages[] = $param;
                   11818:                 continue;
                   11819:             }
                   11820: 
                   11821:             if (strpos($param, 'channel://') === false && @file_exists($param)) {
                   11822:                 if (isset($options['force'])) {
                   11823:                     $otherpackages[] = $param;
                   11824:                     continue;
                   11825:                 }
                   11826: 
                   11827:                 $pkg = new PEAR_PackageFile($this->config);
                   11828:                 $pf  = $pkg->fromAnyFile($param, PEAR_VALIDATE_DOWNLOADING);
                   11829:                 if (PEAR::isError($pf)) {
                   11830:                     $otherpackages[] = $param;
                   11831:                     continue;
                   11832:                 }
                   11833: 
                   11834:                 $exists   = $reg->packageExists($pf->getPackage(), $pf->getChannel());
                   11835:                 $pversion = $reg->packageInfo($pf->getPackage(), 'version', $pf->getChannel());
                   11836:                 $version_compare = version_compare($pf->getVersion(), $pversion, '<=');
                   11837:                 if ($exists && $version_compare) {
                   11838:                     if ($this->config->get('verbose')) {
                   11839:                         $this->ui->outputData('Ignoring installed package ' .
                   11840:                             $reg->parsedPackageNameToString(
                   11841:                             array('package' => $pf->getPackage(),
                   11842:                                   'channel' => $pf->getChannel()), true));
                   11843:                     }
                   11844:                     continue;
                   11845:                 }
                   11846:                 $otherpackages[] = $param;
                   11847:                 continue;
                   11848:             }
                   11849: 
                   11850:             $e = $reg->parsePackageName($param, $channel);
                   11851:             if (PEAR::isError($e)) {
                   11852:                 $otherpackages[] = $param;
                   11853:             } else {
                   11854:                 $abstractpackages[] = $e;
                   11855:             }
                   11856:         }
                   11857:         PEAR::staticPopErrorHandling();
                   11858: 
                   11859:         // if there are any local package .tgz or remote static url, we can't
                   11860:         // filter.  The filter only works for abstract packages
                   11861:         if (count($abstractpackages) && !isset($options['force'])) {
                   11862:             // when not being forced, only do necessary upgrades/installs
                   11863:             if (isset($options['upgrade'])) {
                   11864:                 $abstractpackages = $this->_filterUptodatePackages($abstractpackages, $command);
                   11865:             } else {
                   11866:                 $count = count($abstractpackages);
                   11867:                 foreach ($abstractpackages as $i => $package) {
                   11868:                     if (isset($package['group'])) {
                   11869:                         // do not filter out install groups
                   11870:                         continue;
                   11871:                     }
                   11872: 
                   11873:                     if ($instreg->packageExists($package['package'], $package['channel'])) {
                   11874:                         if ($count > 1) {
                   11875:                             if ($this->config->get('verbose')) {
                   11876:                                 $this->ui->outputData('Ignoring installed package ' .
                   11877:                                     $reg->parsedPackageNameToString($package, true));
                   11878:                             }
                   11879:                             unset($abstractpackages[$i]);
                   11880:                         } elseif ($count === 1) {
                   11881:                             // Lets try to upgrade it since it's already installed
                   11882:                             $options['upgrade'] = true;
                   11883:                         }
                   11884:                     }
                   11885:                 }
                   11886:             }
                   11887:             $abstractpackages =
                   11888:                 array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages);
                   11889:         } elseif (count($abstractpackages)) {
                   11890:             $abstractpackages =
                   11891:                 array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages);
                   11892:         }
                   11893: 
                   11894:         $packages = array_merge($abstractpackages, $otherpackages);
                   11895:         if (!count($packages)) {
                   11896:             $c = '';
                   11897:             if (isset($options['channel'])){
                   11898:                 $c .= ' in channel "' . $options['channel'] . '"';
                   11899:             }
                   11900:             $this->ui->outputData('Nothing to ' . $command . $c);
                   11901:             return true;
                   11902:         }
                   11903: 
                   11904:         $this->downloader = &$this->getDownloader($this->ui, $options, $this->config);
                   11905:         $errors = $downloaded = $binaries = array();
                   11906:         $downloaded = &$this->downloader->download($packages);
                   11907:         if (PEAR::isError($downloaded)) {
                   11908:             return $this->raiseError($downloaded);
                   11909:         }
                   11910: 
                   11911:         $errors = $this->downloader->getErrorMsgs();
                   11912:         if (count($errors)) {
                   11913:             $err = array();
                   11914:             $err['data'] = array();
                   11915:             foreach ($errors as $error) {
                   11916:                 if ($error !== null) {
                   11917:                     $err['data'][] = array($error);
                   11918:                 }
                   11919:             }
                   11920: 
                   11921:             if (!empty($err['data'])) {
                   11922:                 $err['headline'] = 'Install Errors';
                   11923:                 $this->ui->outputData($err);
                   11924:             }
                   11925: 
                   11926:             if (!count($downloaded)) {
                   11927:                 return $this->raiseError("$command failed");
                   11928:             }
                   11929:         }
                   11930: 
                   11931:         $data = array(
                   11932:             'headline' => 'Packages that would be Installed'
                   11933:         );
                   11934: 
                   11935:         if (isset($options['pretend'])) {
                   11936:             foreach ($downloaded as $package) {
                   11937:                 $data['data'][] = array($reg->parsedPackageNameToString($package->getParsedPackage()));
                   11938:             }
                   11939:             $this->ui->outputData($data, 'pretend');
                   11940:             return true;
                   11941:         }
                   11942: 
                   11943:         $this->installer->setOptions($options);
                   11944:         $this->installer->sortPackagesForInstall($downloaded);
                   11945:         if (PEAR::isError($err = $this->installer->setDownloadedPackages($downloaded))) {
                   11946:             $this->raiseError($err->getMessage());
                   11947:             return true;
                   11948:         }
                   11949: 
                   11950:         $binaries = $extrainfo = array();
                   11951:         foreach ($downloaded as $param) {
                   11952:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   11953:             $info = $this->installer->install($param, $options);
                   11954:             PEAR::staticPopErrorHandling();
                   11955:             if (PEAR::isError($info)) {
                   11956:                 $oldinfo = $info;
                   11957:                 $pkg = &$param->getPackageFile();
                   11958:                 if ($info->getCode() != PEAR_INSTALLER_NOBINARY) {
                   11959:                     if (!($info = $pkg->installBinary($this->installer))) {
                   11960:                         $this->ui->outputData('ERROR: ' .$oldinfo->getMessage());
                   11961:                         continue;
                   11962:                     }
                   11963: 
                   11964:                     // we just installed a different package than requested,
                   11965:                     // let's change the param and info so that the rest of this works
                   11966:                     $param = $info[0];
                   11967:                     $info  = $info[1];
                   11968:                 }
                   11969:             }
                   11970: 
                   11971:             if (!is_array($info)) {
                   11972:                 return $this->raiseError("$command failed");
                   11973:             }
                   11974: 
                   11975:             if ($param->getPackageType() == 'extsrc' ||
                   11976:                   $param->getPackageType() == 'extbin' ||
                   11977:                   $param->getPackageType() == 'zendextsrc' ||
                   11978:                   $param->getPackageType() == 'zendextbin'
                   11979:             ) {
                   11980:                 $pkg = &$param->getPackageFile();
                   11981:                 if ($instbin = $pkg->getInstalledBinary()) {
                   11982:                     $instpkg = &$instreg->getPackage($instbin, $pkg->getChannel());
                   11983:                 } else {
                   11984:                     $instpkg = &$instreg->getPackage($pkg->getPackage(), $pkg->getChannel());
                   11985:                 }
                   11986: 
                   11987:                 foreach ($instpkg->getFilelist() as $name => $atts) {
                   11988:                     $pinfo = pathinfo($atts['installed_as']);
                   11989:                     if (!isset($pinfo['extension']) ||
                   11990:                           in_array($pinfo['extension'], array('c', 'h'))
                   11991:                     ) {
                   11992:                         continue; // make sure we don't match php_blah.h
                   11993:                     }
                   11994: 
                   11995:                     if ((strpos($pinfo['basename'], 'php_') === 0 &&
                   11996:                           $pinfo['extension'] == 'dll') ||
                   11997:                           // most unices
                   11998:                           $pinfo['extension'] == 'so' ||
                   11999:                           // hp-ux
                   12000:                           $pinfo['extension'] == 'sl') {
                   12001:                         $binaries[] = array($atts['installed_as'], $pinfo);
                   12002:                         break;
                   12003:                     }
                   12004:                 }
                   12005: 
                   12006:                 if (count($binaries)) {
                   12007:                     foreach ($binaries as $pinfo) {
                   12008:                         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   12009:                         $ret = $this->enableExtension(array($pinfo[0]), $param->getPackageType());
                   12010:                         PEAR::staticPopErrorHandling();
                   12011:                         if (PEAR::isError($ret)) {
                   12012:                             $extrainfo[] = $ret->getMessage();
                   12013:                             if ($param->getPackageType() == 'extsrc' ||
                   12014:                                   $param->getPackageType() == 'extbin') {
                   12015:                                 $exttype = 'extension';
                   12016:                             } else {
                   12017:                                 ob_start();
                   12018:                                 phpinfo(INFO_GENERAL);
                   12019:                                 $info = ob_get_contents();
                   12020:                                 ob_end_clean();
                   12021:                                 $debug = function_exists('leak') ? '_debug' : '';
                   12022:                                 $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
                   12023:                                 $exttype = 'zend_extension' . $debug . $ts;
                   12024:                             }
                   12025:                             $extrainfo[] = 'You should add "' . $exttype . '=' .
                   12026:                                 $pinfo[1]['basename'] . '" to php.ini';
                   12027:                         } else {
                   12028:                             $extrainfo[] = 'Extension ' . $instpkg->getProvidesExtension() .
                   12029:                                 ' enabled in php.ini';
                   12030:                         }
                   12031:                     }
                   12032:                 }
                   12033:             }
                   12034: 
                   12035:             if ($this->config->get('verbose') > 0) {
                   12036:                 $chan = $param->getChannel();
                   12037:                 $label = $reg->parsedPackageNameToString(
                   12038:                     array(
                   12039:                         'channel' => $chan,
                   12040:                         'package' => $param->getPackage(),
                   12041:                         'version' => $param->getVersion(),
                   12042:                     ));
                   12043:                 $out = array('data' => "$command ok: $label");
                   12044:                 if (isset($info['release_warnings'])) {
                   12045:                     $out['release_warnings'] = $info['release_warnings'];
                   12046:                 }
                   12047:                 $this->ui->outputData($out, $command);
                   12048: 
                   12049:                 if (!isset($options['register-only']) && !isset($options['offline'])) {
                   12050:                     if ($this->config->isDefinedLayer('ftp')) {
                   12051:                         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   12052:                         $info = $this->installer->ftpInstall($param);
                   12053:                         PEAR::staticPopErrorHandling();
                   12054:                         if (PEAR::isError($info)) {
                   12055:                             $this->ui->outputData($info->getMessage());
                   12056:                             $this->ui->outputData("remote install failed: $label");
                   12057:                         } else {
                   12058:                             $this->ui->outputData("remote install ok: $label");
                   12059:                         }
                   12060:                     }
                   12061:                 }
                   12062:             }
                   12063: 
                   12064:             $deps = $param->getDeps();
                   12065:             if ($deps) {
                   12066:                 if (isset($deps['group'])) {
                   12067:                     $groups = $deps['group'];
                   12068:                     if (!isset($groups[0])) {
                   12069:                         $groups = array($groups);
                   12070:                     }
                   12071: 
                   12072:                     foreach ($groups as $group) {
                   12073:                         if ($group['attribs']['name'] == 'default') {
                   12074:                             // default group is always installed, unless the user
                   12075:                             // explicitly chooses to install another group
                   12076:                             continue;
                   12077:                         }
                   12078:                         $extrainfo[] = $param->getPackage() . ': Optional feature ' .
                   12079:                             $group['attribs']['name'] . ' available (' .
                   12080:                             $group['attribs']['hint'] . ')';
                   12081:                     }
                   12082: 
                   12083:                     $extrainfo[] = $param->getPackage() .
                   12084:                         ': To install optional features use "pear install ' .
                   12085:                         $reg->parsedPackageNameToString(
                   12086:                             array('package' => $param->getPackage(),
                   12087:                                   'channel' => $param->getChannel()), true) .
                   12088:                               '#featurename"';
                   12089:                 }
                   12090:             }
                   12091: 
                   12092:             $pkg = &$instreg->getPackage($param->getPackage(), $param->getChannel());
                   12093:             // $pkg may be NULL if install is a 'fake' install via --packagingroot
                   12094:             if (is_object($pkg)) {
                   12095:                 $pkg->setConfig($this->config);
                   12096:                 if ($list = $pkg->listPostinstallScripts()) {
                   12097:                     $pn = $reg->parsedPackageNameToString(array('channel' =>
                   12098:                        $param->getChannel(), 'package' => $param->getPackage()), true);
                   12099:                     $extrainfo[] = $pn . ' has post-install scripts:';
                   12100:                     foreach ($list as $file) {
                   12101:                         $extrainfo[] = $file;
                   12102:                     }
                   12103:                     $extrainfo[] = $param->getPackage() .
                   12104:                         ': Use "pear run-scripts ' . $pn . '" to finish setup.';
                   12105:                     $extrainfo[] = 'DO NOT RUN SCRIPTS FROM UNTRUSTED SOURCES';
                   12106:                 }
                   12107:             }
                   12108:         }
                   12109: 
                   12110:         if (count($extrainfo)) {
                   12111:             foreach ($extrainfo as $info) {
                   12112:                 $this->ui->outputData($info);
                   12113:             }
                   12114:         }
                   12115: 
                   12116:         return true;
                   12117:     }
                   12118: 
                   12119:     // }}}
                   12120:     // {{{ doUpgradeAll()
                   12121: 
                   12122:     function doUpgradeAll($command, $options, $params)
                   12123:     {
                   12124:         $reg = &$this->config->getRegistry();
                   12125:         $upgrade = array();
                   12126: 
                   12127:         if (isset($options['channel'])) {
                   12128:             $channels = array($options['channel']);
                   12129:         } else {
                   12130:             $channels = $reg->listChannels();
                   12131:         }
                   12132: 
                   12133:         foreach ($channels as $channel) {
                   12134:             if ($channel == '__uri') {
                   12135:                 continue;
                   12136:             }
                   12137: 
                   12138:             // parse name with channel
                   12139:             foreach ($reg->listPackages($channel) as $name) {
                   12140:                 $upgrade[] = $reg->parsedPackageNameToString(array(
                   12141:                         'channel' => $channel,
                   12142:                         'package' => $name
                   12143:                     ));
                   12144:             }
                   12145:         }
                   12146: 
                   12147:         $err = $this->doInstall($command, $options, $upgrade);
                   12148:         if (PEAR::isError($err)) {
                   12149:             $this->ui->outputData($err->getMessage(), $command);
                   12150:         }
                   12151:    }
                   12152: 
                   12153:     // }}}
                   12154:     // {{{ doUninstall()
                   12155: 
                   12156:     function doUninstall($command, $options, $params)
                   12157:     {
                   12158:         if (count($params) < 1) {
                   12159:             return $this->raiseError("Please supply the package(s) you want to uninstall");
                   12160:         }
                   12161: 
                   12162:         if (empty($this->installer)) {
                   12163:             $this->installer = &$this->getInstaller($this->ui);
                   12164:         }
                   12165: 
                   12166:         if (isset($options['remoteconfig'])) {
                   12167:             $e = $this->config->readFTPConfigFile($options['remoteconfig']);
                   12168:             if (!PEAR::isError($e)) {
                   12169:                 $this->installer->setConfig($this->config);
                   12170:             }
                   12171:         }
                   12172: 
                   12173:         $reg = &$this->config->getRegistry();
                   12174:         $newparams = array();
                   12175:         $binaries = array();
                   12176:         $badparams = array();
                   12177:         foreach ($params as $pkg) {
                   12178:             $channel = $this->config->get('default_channel');
                   12179:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   12180:             $parsed = $reg->parsePackageName($pkg, $channel);
                   12181:             PEAR::staticPopErrorHandling();
                   12182:             if (!$parsed || PEAR::isError($parsed)) {
                   12183:                 $badparams[] = $pkg;
                   12184:                 continue;
                   12185:             }
                   12186:             $package = $parsed['package'];
                   12187:             $channel = $parsed['channel'];
                   12188:             $info = &$reg->getPackage($package, $channel);
                   12189:             if ($info === null &&
                   12190:                  ($channel == 'pear.php.net' || $channel == 'pecl.php.net')) {
                   12191:                 // make sure this isn't a package that has flipped from pear to pecl but
                   12192:                 // used a package.xml 1.0
                   12193:                 $testc = ($channel == 'pear.php.net') ? 'pecl.php.net' : 'pear.php.net';
                   12194:                 $info = &$reg->getPackage($package, $testc);
                   12195:                 if ($info !== null) {
                   12196:                     $channel = $testc;
                   12197:                 }
                   12198:             }
                   12199:             if ($info === null) {
                   12200:                 $badparams[] = $pkg;
                   12201:             } else {
                   12202:                 $newparams[] = &$info;
                   12203:                 // check for binary packages (this is an alias for those packages if so)
                   12204:                 if ($installedbinary = $info->getInstalledBinary()) {
                   12205:                     $this->ui->log('adding binary package ' .
                   12206:                         $reg->parsedPackageNameToString(array('channel' => $channel,
                   12207:                             'package' => $installedbinary), true));
                   12208:                     $newparams[] = &$reg->getPackage($installedbinary, $channel);
                   12209:                 }
                   12210:                 // add the contents of a dependency group to the list of installed packages
                   12211:                 if (isset($parsed['group'])) {
                   12212:                     $group = $info->getDependencyGroup($parsed['group']);
                   12213:                     if ($group) {
                   12214:                         $installed = $reg->getInstalledGroup($group);
                   12215:                         if ($installed) {
                   12216:                             foreach ($installed as $i => $p) {
                   12217:                                 $newparams[] = &$installed[$i];
                   12218:                             }
                   12219:                         }
                   12220:                     }
                   12221:                 }
                   12222:             }
                   12223:         }
                   12224:         $err = $this->installer->sortPackagesForUninstall($newparams);
                   12225:         if (PEAR::isError($err)) {
                   12226:             $this->ui->outputData($err->getMessage(), $command);
                   12227:             return true;
                   12228:         }
                   12229:         $params = $newparams;
                   12230:         // twist this to use it to check on whether dependent packages are also being uninstalled
                   12231:         // for circular dependencies like subpackages
                   12232:         $this->installer->setUninstallPackages($newparams);
                   12233:         $params = array_merge($params, $badparams);
                   12234:         $binaries = array();
                   12235:         foreach ($params as $pkg) {
                   12236:             $this->installer->pushErrorHandling(PEAR_ERROR_RETURN);
                   12237:             if ($err = $this->installer->uninstall($pkg, $options)) {
                   12238:                 $this->installer->popErrorHandling();
                   12239:                 if (PEAR::isError($err)) {
                   12240:                     $this->ui->outputData($err->getMessage(), $command);
                   12241:                     continue;
                   12242:                 }
                   12243:                 if ($pkg->getPackageType() == 'extsrc' ||
                   12244:                       $pkg->getPackageType() == 'extbin' ||
                   12245:                       $pkg->getPackageType() == 'zendextsrc' ||
                   12246:                       $pkg->getPackageType() == 'zendextbin') {
                   12247:                     if ($instbin = $pkg->getInstalledBinary()) {
                   12248:                         continue; // this will be uninstalled later
                   12249:                     }
                   12250: 
                   12251:                     foreach ($pkg->getFilelist() as $name => $atts) {
                   12252:                         $pinfo = pathinfo($atts['installed_as']);
                   12253:                         if (!isset($pinfo['extension']) ||
                   12254:                               in_array($pinfo['extension'], array('c', 'h'))) {
                   12255:                             continue; // make sure we don't match php_blah.h
                   12256:                         }
                   12257:                         if ((strpos($pinfo['basename'], 'php_') === 0 &&
                   12258:                               $pinfo['extension'] == 'dll') ||
                   12259:                               // most unices
                   12260:                               $pinfo['extension'] == 'so' ||
                   12261:                               // hp-ux
                   12262:                               $pinfo['extension'] == 'sl') {
                   12263:                             $binaries[] = array($atts['installed_as'], $pinfo);
                   12264:                             break;
                   12265:                         }
                   12266:                     }
                   12267:                     if (count($binaries)) {
                   12268:                         foreach ($binaries as $pinfo) {
                   12269:                             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   12270:                             $ret = $this->disableExtension(array($pinfo[0]), $pkg->getPackageType());
                   12271:                             PEAR::staticPopErrorHandling();
                   12272:                             if (PEAR::isError($ret)) {
                   12273:                                 $extrainfo[] = $ret->getMessage();
                   12274:                                 if ($pkg->getPackageType() == 'extsrc' ||
                   12275:                                       $pkg->getPackageType() == 'extbin') {
                   12276:                                     $exttype = 'extension';
                   12277:                                 } else {
                   12278:                                     ob_start();
                   12279:                                     phpinfo(INFO_GENERAL);
                   12280:                                     $info = ob_get_contents();
                   12281:                                     ob_end_clean();
                   12282:                                     $debug = function_exists('leak') ? '_debug' : '';
                   12283:                                     $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
                   12284:                                     $exttype = 'zend_extension' . $debug . $ts;
                   12285:                                 }
                   12286:                                 $this->ui->outputData('Unable to remove "' . $exttype . '=' .
                   12287:                                     $pinfo[1]['basename'] . '" from php.ini', $command);
                   12288:                             } else {
                   12289:                                 $this->ui->outputData('Extension ' . $pkg->getProvidesExtension() .
                   12290:                                     ' disabled in php.ini', $command);
                   12291:                             }
                   12292:                         }
                   12293:                     }
                   12294:                 }
                   12295:                 $savepkg = $pkg;
                   12296:                 if ($this->config->get('verbose') > 0) {
                   12297:                     if (is_object($pkg)) {
                   12298:                         $pkg = $reg->parsedPackageNameToString($pkg);
                   12299:                     }
                   12300:                     $this->ui->outputData("uninstall ok: $pkg", $command);
                   12301:                 }
                   12302:                 if (!isset($options['offline']) && is_object($savepkg) &&
                   12303:                       defined('PEAR_REMOTEINSTALL_OK')) {
                   12304:                     if ($this->config->isDefinedLayer('ftp')) {
                   12305:                         $this->installer->pushErrorHandling(PEAR_ERROR_RETURN);
                   12306:                         $info = $this->installer->ftpUninstall($savepkg);
                   12307:                         $this->installer->popErrorHandling();
                   12308:                         if (PEAR::isError($info)) {
                   12309:                             $this->ui->outputData($info->getMessage());
                   12310:                             $this->ui->outputData("remote uninstall failed: $pkg");
                   12311:                         } else {
                   12312:                             $this->ui->outputData("remote uninstall ok: $pkg");
                   12313:                         }
                   12314:                     }
                   12315:                 }
                   12316:             } else {
                   12317:                 $this->installer->popErrorHandling();
                   12318:                 if (!is_object($pkg)) {
                   12319:                     return $this->raiseError("uninstall failed: $pkg");
                   12320:                 }
                   12321:                 $pkg = $reg->parsedPackageNameToString($pkg);
                   12322:             }
                   12323:         }
                   12324: 
                   12325:         return true;
                   12326:     }
                   12327: 
                   12328:     // }}}
                   12329: 
                   12330: 
                   12331:     // }}}
                   12332:     // {{{ doBundle()
                   12333:     /*
                   12334:     (cox) It just downloads and untars the package, does not do
                   12335:             any check that the PEAR_Installer::_installFile() does.
                   12336:     */
                   12337: 
                   12338:     function doBundle($command, $options, $params)
                   12339:     {
                   12340:         $opts = array(
                   12341:             'force'        => true,
                   12342:             'nodeps'       => true,
                   12343:             'soft'         => true,
                   12344:             'downloadonly' => true
                   12345:         );
                   12346:         $downloader = &$this->getDownloader($this->ui, $opts, $this->config);
                   12347:         $reg = &$this->config->getRegistry();
                   12348:         if (count($params) < 1) {
                   12349:             return $this->raiseError("Please supply the package you want to bundle");
                   12350:         }
                   12351: 
                   12352:         if (isset($options['destination'])) {
                   12353:             if (!is_dir($options['destination'])) {
                   12354:                 System::mkdir('-p ' . $options['destination']);
                   12355:             }
                   12356:             $dest = realpath($options['destination']);
                   12357:         } else {
                   12358:             $pwd  = getcwd();
                   12359:             $dir  = $pwd . DIRECTORY_SEPARATOR . 'ext';
                   12360:             $dest = is_dir($dir) ? $dir : $pwd;
                   12361:         }
                   12362:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   12363:         $err = $downloader->setDownloadDir($dest);
                   12364:         PEAR::staticPopErrorHandling();
                   12365:         if (PEAR::isError($err)) {
                   12366:             return PEAR::raiseError('download directory "' . $dest .
                   12367:                 '" is not writeable.');
                   12368:         }
                   12369:         $result = &$downloader->download(array($params[0]));
                   12370:         if (PEAR::isError($result)) {
                   12371:             return $result;
                   12372:         }
                   12373:         if (!isset($result[0])) {
                   12374:             return $this->raiseError('unable to unpack ' . $params[0]);
                   12375:         }
                   12376:         $pkgfile = &$result[0]->getPackageFile();
                   12377:         $pkgname = $pkgfile->getName();
                   12378:         $pkgversion = $pkgfile->getVersion();
                   12379: 
                   12380:         // Unpacking -------------------------------------------------
                   12381:         $dest .= DIRECTORY_SEPARATOR . $pkgname;
                   12382:         $orig = $pkgname . '-' . $pkgversion;
                   12383: 
                   12384:         $tar = &new Archive_Tar($pkgfile->getArchiveFile());
                   12385:         if (!$tar->extractModify($dest, $orig)) {
                   12386:             return $this->raiseError('unable to unpack ' . $pkgfile->getArchiveFile());
                   12387:         }
                   12388:         $this->ui->outputData("Package ready at '$dest'");
                   12389:     // }}}
                   12390:     }
                   12391: 
                   12392:     // }}}
                   12393: 
                   12394:     function doRunScripts($command, $options, $params)
                   12395:     {
                   12396:         if (!isset($params[0])) {
                   12397:             return $this->raiseError('run-scripts expects 1 parameter: a package name');
                   12398:         }
                   12399: 
                   12400:         $reg = &$this->config->getRegistry();
                   12401:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   12402:         $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
                   12403:         PEAR::staticPopErrorHandling();
                   12404:         if (PEAR::isError($parsed)) {
                   12405:             return $this->raiseError($parsed);
                   12406:         }
                   12407: 
                   12408:         $package = &$reg->getPackage($parsed['package'], $parsed['channel']);
                   12409:         if (!is_object($package)) {
                   12410:             return $this->raiseError('Could not retrieve package "' . $params[0] . '" from registry');
                   12411:         }
                   12412: 
                   12413:         $package->setConfig($this->config);
                   12414:         $package->runPostinstallScripts();
                   12415:         $this->ui->outputData('Install scripts complete', $command);
                   12416:         return true;
                   12417:     }
                   12418: 
                   12419:     /**
                   12420:      * Given a list of packages, filter out those ones that are already up to date
                   12421:      *
                   12422:      * @param $packages: packages, in parsed array format !
                   12423:      * @return list of packages that can be upgraded
                   12424:      */
                   12425:     function _filterUptodatePackages($packages, $command)
                   12426:     {
                   12427:         $reg = &$this->config->getRegistry();
                   12428:         $latestReleases = array();
                   12429: 
                   12430:         $ret = array();
                   12431:         foreach ($packages as $package) {
                   12432:             if (isset($package['group'])) {
                   12433:                 $ret[] = $package;
                   12434:                 continue;
                   12435:             }
                   12436: 
                   12437:             $channel = $package['channel'];
                   12438:             $name    = $package['package'];
                   12439:             if (!$reg->packageExists($name, $channel)) {
                   12440:                 $ret[] = $package;
                   12441:                 continue;
                   12442:             }
                   12443: 
                   12444:             if (!isset($latestReleases[$channel])) {
                   12445:                 // fill in cache for this channel
                   12446:                 $chan = &$reg->getChannel($channel);
                   12447:                 if (PEAR::isError($chan)) {
                   12448:                     return $this->raiseError($chan);
                   12449:                 }
                   12450: 
                   12451:                 $base2 = false;
                   12452:                 $preferred_mirror = $this->config->get('preferred_mirror', null, $channel);
                   12453:                 if ($chan->supportsREST($preferred_mirror) &&
                   12454:                     (
                   12455:                        //($base2 = $chan->getBaseURL('REST1.4', $preferred_mirror)) ||
                   12456:                        ($base  = $chan->getBaseURL('REST1.0', $preferred_mirror))
                   12457:                     )
                   12458:                 ) {
                   12459:                     $dorest = true;
                   12460:                 }
                   12461: 
                   12462:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   12463:                 if (!isset($package['state'])) {
                   12464:                     $state = $this->config->get('preferred_state', null, $channel);
                   12465:                 } else {
                   12466:                     $state = $package['state'];
                   12467:                 }
                   12468: 
                   12469:                 if ($dorest) {
                   12470:                     if ($base2) {
                   12471:                         $rest = &$this->config->getREST('1.4', array());
                   12472:                         $base = $base2;
                   12473:                     } else {
                   12474:                         $rest = &$this->config->getREST('1.0', array());
                   12475:                     }
                   12476: 
                   12477:                     $installed = array_flip($reg->listPackages($channel));
                   12478:                     $latest    = $rest->listLatestUpgrades($base, $state, $installed, $channel, $reg);
                   12479:                 }
                   12480: 
                   12481:                 PEAR::staticPopErrorHandling();
                   12482:                 if (PEAR::isError($latest)) {
                   12483:                     $this->ui->outputData('Error getting channel info from ' . $channel .
                   12484:                         ': ' . $latest->getMessage());
                   12485:                     continue;
                   12486:                 }
                   12487: 
                   12488:                 $latestReleases[$channel] = array_change_key_case($latest);
                   12489:             }
                   12490: 
                   12491:             // check package for latest release
                   12492:             $name_lower = strtolower($name);
                   12493:             if (isset($latestReleases[$channel][$name_lower])) {
                   12494:                 // if not set, up to date
                   12495:                 $inst_version    = $reg->packageInfo($name, 'version', $channel);
                   12496:                 $channel_version = $latestReleases[$channel][$name_lower]['version'];
                   12497:                 if (version_compare($channel_version, $inst_version, 'le')) {
                   12498:                     // installed version is up-to-date
                   12499:                     continue;
                   12500:                 }
                   12501: 
                   12502:                 // maintain BC
                   12503:                 if ($command == 'upgrade-all') {
                   12504:                     $this->ui->outputData(array('data' => 'Will upgrade ' .
                   12505:                         $reg->parsedPackageNameToString($package)), $command);
                   12506:                 }
                   12507:                 $ret[] = $package;
                   12508:             }
                   12509:         }
                   12510: 
                   12511:         return $ret;
                   12512:     }
1.1.1.2 ! misho    12513: }PEAR-1.9.4/PEAR/Command/Mirror.xml0000644000076500000240000000115111605156614015333 0ustar  helgistaff<commands version="1.0">
1.1       misho    12514:  <download-all>
                   12515:   <summary>Downloads each available package from the default channel</summary>
                   12516:   <function>doDownloadAll</function>
                   12517:   <shortcut>da</shortcut>
                   12518:   <options>
                   12519:    <channel>
                   12520:     <shortopt>c</shortopt>
                   12521:     <doc>specify a channel other than the default channel</doc>
                   12522:     <arg>CHAN</arg>
                   12523:    </channel>
                   12524:   </options>
                   12525:   <doc>
                   12526: Requests a list of available packages from the default channel ({config default_channel})
                   12527: and downloads them to current working directory.  Note: only
                   12528: packages within preferred_state ({config preferred_state}) will be downloaded</doc>
                   12529:  </download-all>
1.1.1.2 ! misho    12530: </commands>PEAR-1.9.4/PEAR/Command/Mirror.php0000644000076500000240000001076211605156614015332 0ustar  helgistaff<?php
1.1       misho    12531: /**
                   12532:  * PEAR_Command_Mirror (download-all command)
                   12533:  *
                   12534:  * PHP versions 4 and 5
                   12535:  *
                   12536:  * @category   pear
                   12537:  * @package    PEAR
                   12538:  * @author     Alexander Merz <alexmerz@php.net>
                   12539:  * @copyright  1997-2009 The Authors
                   12540:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   12541:  * @version    CVS: $Id: Mirror.php 313023 2011-07-06 19:17:11Z dufuz $
                   12542:  * @link       http://pear.php.net/package/PEAR
                   12543:  * @since      File available since Release 1.2.0
                   12544:  */
                   12545: 
                   12546: /**
                   12547:  * base class
                   12548:  */
                   12549: require_once 'PEAR/Command/Common.php';
                   12550: 
                   12551: /**
                   12552:  * PEAR commands for providing file mirrors
                   12553:  *
                   12554:  * @category   pear
                   12555:  * @package    PEAR
                   12556:  * @author     Alexander Merz <alexmerz@php.net>
                   12557:  * @copyright  1997-2009 The Authors
                   12558:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   12559:  * @version    Release: 1.9.4
                   12560:  * @link       http://pear.php.net/package/PEAR
                   12561:  * @since      Class available since Release 1.2.0
                   12562:  */
                   12563: class PEAR_Command_Mirror extends PEAR_Command_Common
                   12564: {
                   12565:     var $commands = array(
                   12566:         'download-all' => array(
                   12567:             'summary' => 'Downloads each available package from the default channel',
                   12568:             'function' => 'doDownloadAll',
                   12569:             'shortcut' => 'da',
                   12570:             'options' => array(
                   12571:                 'channel' =>
                   12572:                     array(
                   12573:                     'shortopt' => 'c',
                   12574:                     'doc' => 'specify a channel other than the default channel',
                   12575:                     'arg' => 'CHAN',
                   12576:                     ),
                   12577:                 ),
                   12578:             'doc' => '
                   12579: Requests a list of available packages from the default channel ({config default_channel})
                   12580: and downloads them to current working directory.  Note: only
                   12581: packages within preferred_state ({config preferred_state}) will be downloaded'
                   12582:             ),
                   12583:         );
                   12584: 
                   12585:     /**
                   12586:      * PEAR_Command_Mirror constructor.
                   12587:      *
                   12588:      * @access public
                   12589:      * @param object PEAR_Frontend a reference to an frontend
                   12590:      * @param object PEAR_Config a reference to the configuration data
                   12591:      */
                   12592:     function PEAR_Command_Mirror(&$ui, &$config)
                   12593:     {
                   12594:         parent::PEAR_Command_Common($ui, $config);
                   12595:     }
                   12596: 
                   12597:     /**
                   12598:      * For unit-testing
                   12599:      */
                   12600:     function &factory($a)
                   12601:     {
                   12602:         $a = &PEAR_Command::factory($a, $this->config);
                   12603:         return $a;
                   12604:     }
                   12605: 
                   12606:     /**
                   12607:     * retrieves a list of avaible Packages from master server
                   12608:     * and downloads them
                   12609:     *
                   12610:     * @access public
                   12611:     * @param string $command the command
                   12612:     * @param array $options the command options before the command
                   12613:     * @param array $params the stuff after the command name
                   12614:     * @return bool true if succesful
                   12615:     * @throw PEAR_Error
                   12616:     */
                   12617:     function doDownloadAll($command, $options, $params)
                   12618:     {
                   12619:         $savechannel = $this->config->get('default_channel');
                   12620:         $reg = &$this->config->getRegistry();
                   12621:         $channel = isset($options['channel']) ? $options['channel'] :
                   12622:             $this->config->get('default_channel');
                   12623:         if (!$reg->channelExists($channel)) {
                   12624:             $this->config->set('default_channel', $savechannel);
                   12625:             return $this->raiseError('Channel "' . $channel . '" does not exist');
                   12626:         }
                   12627:         $this->config->set('default_channel', $channel);
                   12628: 
                   12629:         $this->ui->outputData('Using Channel ' . $this->config->get('default_channel'));
                   12630:         $chan = $reg->getChannel($channel);
                   12631:         if (PEAR::isError($chan)) {
                   12632:             return $this->raiseError($chan);
                   12633:         }
                   12634: 
                   12635:         if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
                   12636:               $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
                   12637:             $rest = &$this->config->getREST('1.0', array());
                   12638:             $remoteInfo = array_flip($rest->listPackages($base, $channel));
                   12639:         }
                   12640: 
                   12641:         if (PEAR::isError($remoteInfo)) {
                   12642:             return $remoteInfo;
                   12643:         }
                   12644: 
                   12645:         $cmd = &$this->factory("download");
                   12646:         if (PEAR::isError($cmd)) {
                   12647:             return $cmd;
                   12648:         }
                   12649: 
                   12650:         $this->ui->outputData('Using Preferred State of ' .
                   12651:             $this->config->get('preferred_state'));
                   12652:         $this->ui->outputData('Gathering release information, please wait...');
                   12653: 
                   12654:         /**
                   12655:          * Error handling not necessary, because already done by
                   12656:          * the download command
                   12657:          */
                   12658:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   12659:         $err = $cmd->run('download', array('downloadonly' => true), array_keys($remoteInfo));
                   12660:         PEAR::staticPopErrorHandling();
                   12661:         $this->config->set('default_channel', $savechannel);
                   12662:         if (PEAR::isError($err)) {
                   12663:             $this->ui->outputData($err->getMessage());
                   12664:         }
                   12665: 
                   12666:         return true;
                   12667:     }
1.1.1.2 ! misho    12668: }PEAR-1.9.4/PEAR/Command/Package.xml0000644000076500000240000001606611605156614015427 0ustar  helgistaff<commands version="1.0">
1.1       misho    12669:  <package>
                   12670:   <summary>Build Package</summary>
                   12671:   <function>doPackage</function>
                   12672:   <shortcut>p</shortcut>
                   12673:   <options>
                   12674:    <nocompress>
                   12675:     <shortopt>Z</shortopt>
                   12676:     <doc>Do not gzip the package file</doc>
                   12677:    </nocompress>
                   12678:    <showname>
                   12679:     <shortopt>n</shortopt>
                   12680:     <doc>Print the name of the packaged file.</doc>
                   12681:    </showname>
                   12682:   </options>
                   12683:   <doc>[descfile] [descfile2]
                   12684: Creates a PEAR package from its description file (usually called
                   12685: package.xml).  If a second packagefile is passed in, then
                   12686: the packager will check to make sure that one is a package.xml
                   12687: version 1.0, and the other is a package.xml version 2.0.  The
                   12688: package.xml version 1.0 will be saved as &quot;package.xml&quot; in the archive,
                   12689: and the other as &quot;package2.xml&quot; in the archive&quot;
                   12690: </doc>
                   12691:  </package>
                   12692:  <package-validate>
                   12693:   <summary>Validate Package Consistency</summary>
                   12694:   <function>doPackageValidate</function>
                   12695:   <shortcut>pv</shortcut>
                   12696:   <options />
                   12697:   <doc>
                   12698: </doc>
                   12699:  </package-validate>
                   12700:  <cvsdiff>
                   12701:   <summary>Run a &quot;cvs diff&quot; for all files in a package</summary>
                   12702:   <function>doCvsDiff</function>
                   12703:   <shortcut>cd</shortcut>
                   12704:   <options>
                   12705:    <quiet>
                   12706:     <shortopt>q</shortopt>
                   12707:     <doc>Be quiet</doc>
                   12708:    </quiet>
                   12709:    <reallyquiet>
                   12710:     <shortopt>Q</shortopt>
                   12711:     <doc>Be really quiet</doc>
                   12712:    </reallyquiet>
                   12713:    <date>
                   12714:     <shortopt>D</shortopt>
                   12715:     <doc>Diff against revision of DATE</doc>
                   12716:     <arg>DATE</arg>
                   12717:    </date>
                   12718:    <release>
                   12719:     <shortopt>R</shortopt>
                   12720:     <doc>Diff against tag for package release REL</doc>
                   12721:     <arg>REL</arg>
                   12722:    </release>
                   12723:    <revision>
                   12724:     <shortopt>r</shortopt>
                   12725:     <doc>Diff against revision REV</doc>
                   12726:     <arg>REV</arg>
                   12727:    </revision>
                   12728:    <context>
                   12729:     <shortopt>c</shortopt>
                   12730:     <doc>Generate context diff</doc>
                   12731:    </context>
                   12732:    <unified>
                   12733:     <shortopt>u</shortopt>
                   12734:     <doc>Generate unified diff</doc>
                   12735:    </unified>
                   12736:    <ignore-case>
                   12737:     <shortopt>i</shortopt>
                   12738:     <doc>Ignore case, consider upper- and lower-case letters equivalent</doc>
                   12739:    </ignore-case>
                   12740:    <ignore-whitespace>
                   12741:     <shortopt>b</shortopt>
                   12742:     <doc>Ignore changes in amount of white space</doc>
                   12743:    </ignore-whitespace>
                   12744:    <ignore-blank-lines>
                   12745:     <shortopt>B</shortopt>
                   12746:     <doc>Ignore changes that insert or delete blank lines</doc>
                   12747:    </ignore-blank-lines>
                   12748:    <brief>
                   12749:     <shortopt></shortopt>
                   12750:     <doc>Report only whether the files differ, no details</doc>
                   12751:    </brief>
                   12752:    <dry-run>
                   12753:     <shortopt>n</shortopt>
                   12754:     <doc>Don&#039;t do anything, just pretend</doc>
                   12755:    </dry-run>
                   12756:   </options>
                   12757:   <doc>&lt;package.xml&gt;
                   12758: Compares all the files in a package.  Without any options, this
                   12759: command will compare the current code with the last checked-in code.
                   12760: Using the -r or -R option you may compare the current code with that
                   12761: of a specific release.
                   12762: </doc>
                   12763:  </cvsdiff>
                   12764:  <svntag>
                   12765:   <summary>Set SVN Release Tag</summary>
                   12766:   <function>doSvnTag</function>
                   12767:   <shortcut>sv</shortcut>
                   12768:   <options>
                   12769:    <quiet>
                   12770:     <shortopt>q</shortopt>
                   12771:     <doc>Be quiet</doc>
                   12772:    </quiet>
                   12773:    <slide>
                   12774:     <shortopt>F</shortopt>
                   12775:     <doc>Move (slide) tag if it exists</doc>
                   12776:    </slide>
                   12777:    <delete>
                   12778:     <shortopt>d</shortopt>
                   12779:     <doc>Remove tag</doc>
                   12780:    </delete>
                   12781:    <dry-run>
                   12782:     <shortopt>n</shortopt>
                   12783:     <doc>Don&#039;t do anything, just pretend</doc>
                   12784:    </dry-run>
                   12785:   </options>
                   12786:   <doc>&lt;package.xml&gt; [files...]
                   12787:  Sets a SVN tag on all files in a package.  Use this command after you have
                   12788:  packaged a distribution tarball with the &quot;package&quot; command to tag what
                   12789:  revisions of what files were in that release.  If need to fix something
                   12790:  after running svntag once, but before the tarball is released to the public,
                   12791:  use the &quot;slide&quot; option to move the release tag.
                   12792: 
                   12793:  to include files (such as a second package.xml, or tests not included in the
                   12794:  release), pass them as additional parameters.
                   12795:  </doc>
                   12796:  </svntag>
                   12797:  <cvstag>
                   12798:   <summary>Set CVS Release Tag</summary>
                   12799:   <function>doCvsTag</function>
                   12800:   <shortcut>ct</shortcut>
                   12801:   <options>
                   12802:    <quiet>
                   12803:     <shortopt>q</shortopt>
                   12804:     <doc>Be quiet</doc>
                   12805:    </quiet>
                   12806:    <reallyquiet>
                   12807:     <shortopt>Q</shortopt>
                   12808:     <doc>Be really quiet</doc>
                   12809:    </reallyquiet>
                   12810:    <slide>
                   12811:     <shortopt>F</shortopt>
                   12812:     <doc>Move (slide) tag if it exists</doc>
                   12813:    </slide>
                   12814:    <delete>
                   12815:     <shortopt>d</shortopt>
                   12816:     <doc>Remove tag</doc>
                   12817:    </delete>
                   12818:    <dry-run>
                   12819:     <shortopt>n</shortopt>
                   12820:     <doc>Don&#039;t do anything, just pretend</doc>
                   12821:    </dry-run>
                   12822:   </options>
                   12823:   <doc>&lt;package.xml&gt; [files...]
                   12824: Sets a CVS tag on all files in a package.  Use this command after you have
                   12825: packaged a distribution tarball with the &quot;package&quot; command to tag what
                   12826: revisions of what files were in that release.  If need to fix something
                   12827: after running cvstag once, but before the tarball is released to the public,
                   12828: use the &quot;slide&quot; option to move the release tag.
                   12829: 
                   12830: to include files (such as a second package.xml, or tests not included in the
                   12831: release), pass them as additional parameters.
                   12832: </doc>
                   12833:  </cvstag>
                   12834:  <package-dependencies>
                   12835:   <summary>Show package dependencies</summary>
                   12836:   <function>doPackageDependencies</function>
                   12837:   <shortcut>pd</shortcut>
                   12838:   <options />
                   12839:   <doc>&lt;package-file&gt; or &lt;package.xml&gt; or &lt;install-package-name&gt;
                   12840: List all dependencies the package has.
                   12841: Can take a tgz / tar file, package.xml or a package name of an installed package.</doc>
                   12842:  </package-dependencies>
                   12843:  <sign>
                   12844:   <summary>Sign a package distribution file</summary>
                   12845:   <function>doSign</function>
                   12846:   <shortcut>si</shortcut>
                   12847:   <options>
                   12848:    <verbose>
                   12849:     <shortopt>v</shortopt>
                   12850:     <doc>Display GnuPG output</doc>
                   12851:    </verbose>
                   12852:   </options>
                   12853:   <doc>&lt;package-file&gt;
                   12854: Signs a package distribution (.tar or .tgz) file with GnuPG.</doc>
                   12855:  </sign>
                   12856:  <makerpm>
                   12857:   <summary>Builds an RPM spec file from a PEAR package</summary>
                   12858:   <function>doMakeRPM</function>
                   12859:   <shortcut>rpm</shortcut>
                   12860:   <options>
                   12861:    <spec-template>
                   12862:     <shortopt>t</shortopt>
                   12863:     <doc>Use FILE as RPM spec file template</doc>
                   12864:     <arg>FILE</arg>
                   12865:    </spec-template>
                   12866:    <rpm-pkgname>
                   12867:     <shortopt>p</shortopt>
                   12868:     <doc>Use FORMAT as format string for RPM package name, %s is replaced
                   12869: by the PEAR package name, defaults to &quot;PEAR::%s&quot;.</doc>
                   12870:     <arg>FORMAT</arg>
                   12871:    </rpm-pkgname>
                   12872:   </options>
                   12873:   <doc>&lt;package-file&gt;
                   12874: 
                   12875: Creates an RPM .spec file for wrapping a PEAR package inside an RPM
                   12876: package.  Intended to be used from the SPECS directory, with the PEAR
                   12877: package tarball in the SOURCES directory:
                   12878: 
                   12879: $ pear makerpm ../SOURCES/Net_Socket-1.0.tgz
                   12880: Wrote RPM spec file PEAR::Net_Geo-1.0.spec
                   12881: $ rpm -bb PEAR::Net_Socket-1.0.spec
                   12882: ...
                   12883: Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
                   12884: </doc>
                   12885:  </makerpm>
                   12886:  <convert>
                   12887:   <summary>Convert a package.xml 1.0 to package.xml 2.0 format</summary>
                   12888:   <function>doConvert</function>
                   12889:   <shortcut>c2</shortcut>
                   12890:   <options>
                   12891:    <flat>
                   12892:     <shortopt>f</shortopt>
                   12893:     <doc>do not beautify the filelist.</doc>
                   12894:    </flat>
                   12895:   </options>
                   12896:   <doc>[descfile] [descfile2]
                   12897: Converts a package.xml in 1.0 format into a package.xml
                   12898: in 2.0 format.  The new file will be named package2.xml by default,
                   12899: and package.xml will be used as the old file by default.
                   12900: This is not the most intelligent conversion, and should only be
                   12901: used for automated conversion or learning the format.
                   12902: </doc>
                   12903:  </convert>
1.1.1.2 ! misho    12904: </commands>PEAR-1.9.4/PEAR/Command/Package.php0000644000076500000240000011652311605156614015415 0ustar  helgistaff<?php
1.1       misho    12905: /**
                   12906:  * PEAR_Command_Package (package, package-validate, cvsdiff, cvstag, package-dependencies,
                   12907:  * sign, makerpm, convert commands)
                   12908:  *
                   12909:  * PHP versions 4 and 5
                   12910:  *
                   12911:  * @category   pear
                   12912:  * @package    PEAR
                   12913:  * @author     Stig Bakken <ssb@php.net>
                   12914:  * @author     Martin Jansen <mj@php.net>
                   12915:  * @author     Greg Beaver <cellog@php.net>
                   12916:  * @copyright  1997-2009 The Authors
                   12917:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   12918:  * @version    CVS: $Id: Package.php 313024 2011-07-06 19:51:24Z dufuz $
                   12919:  * @link       http://pear.php.net/package/PEAR
                   12920:  * @since      File available since Release 0.1
                   12921:  */
                   12922: 
                   12923: /**
                   12924:  * base class
                   12925:  */
                   12926: require_once 'PEAR/Command/Common.php';
                   12927: 
                   12928: /**
                   12929:  * PEAR commands for login/logout
                   12930:  *
                   12931:  * @category   pear
                   12932:  * @package    PEAR
                   12933:  * @author     Stig Bakken <ssb@php.net>
                   12934:  * @author     Martin Jansen <mj@php.net>
                   12935:  * @author     Greg Beaver <cellog@php.net>
                   12936:  * @copyright  1997-2009 The Authors
                   12937:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   12938:  * @version    Release: @package_version@
                   12939:  * @link       http://pear.php.net/package/PEAR
                   12940:  * @since      Class available since Release 0.1
                   12941:  */
                   12942: 
                   12943: class PEAR_Command_Package extends PEAR_Command_Common
                   12944: {
                   12945:     var $commands = array(
                   12946:         'package' => array(
                   12947:             'summary' => 'Build Package',
                   12948:             'function' => 'doPackage',
                   12949:             'shortcut' => 'p',
                   12950:             'options' => array(
                   12951:                 'nocompress' => array(
                   12952:                     'shortopt' => 'Z',
                   12953:                     'doc' => 'Do not gzip the package file'
                   12954:                     ),
                   12955:                 'showname' => array(
                   12956:                     'shortopt' => 'n',
                   12957:                     'doc' => 'Print the name of the packaged file.',
                   12958:                     ),
                   12959:                 ),
                   12960:             'doc' => '[descfile] [descfile2]
                   12961: Creates a PEAR package from its description file (usually called
                   12962: package.xml).  If a second packagefile is passed in, then
                   12963: the packager will check to make sure that one is a package.xml
                   12964: version 1.0, and the other is a package.xml version 2.0.  The
                   12965: package.xml version 1.0 will be saved as "package.xml" in the archive,
                   12966: and the other as "package2.xml" in the archive"
                   12967: '
                   12968:             ),
                   12969:         'package-validate' => array(
                   12970:             'summary' => 'Validate Package Consistency',
                   12971:             'function' => 'doPackageValidate',
                   12972:             'shortcut' => 'pv',
                   12973:             'options' => array(),
                   12974:             'doc' => '
                   12975: ',
                   12976:             ),
                   12977:         'cvsdiff' => array(
                   12978:             'summary' => 'Run a "cvs diff" for all files in a package',
                   12979:             'function' => 'doCvsDiff',
                   12980:             'shortcut' => 'cd',
                   12981:             'options' => array(
                   12982:                 'quiet' => array(
                   12983:                     'shortopt' => 'q',
                   12984:                     'doc' => 'Be quiet',
                   12985:                     ),
                   12986:                 'reallyquiet' => array(
                   12987:                     'shortopt' => 'Q',
                   12988:                     'doc' => 'Be really quiet',
                   12989:                     ),
                   12990:                 'date' => array(
                   12991:                     'shortopt' => 'D',
                   12992:                     'doc' => 'Diff against revision of DATE',
                   12993:                     'arg' => 'DATE',
                   12994:                     ),
                   12995:                 'release' => array(
                   12996:                     'shortopt' => 'R',
                   12997:                     'doc' => 'Diff against tag for package release REL',
                   12998:                     'arg' => 'REL',
                   12999:                     ),
                   13000:                 'revision' => array(
                   13001:                     'shortopt' => 'r',
                   13002:                     'doc' => 'Diff against revision REV',
                   13003:                     'arg' => 'REV',
                   13004:                     ),
                   13005:                 'context' => array(
                   13006:                     'shortopt' => 'c',
                   13007:                     'doc' => 'Generate context diff',
                   13008:                     ),
                   13009:                 'unified' => array(
                   13010:                     'shortopt' => 'u',
                   13011:                     'doc' => 'Generate unified diff',
                   13012:                     ),
                   13013:                 'ignore-case' => array(
                   13014:                     'shortopt' => 'i',
                   13015:                     'doc' => 'Ignore case, consider upper- and lower-case letters equivalent',
                   13016:                     ),
                   13017:                 'ignore-whitespace' => array(
                   13018:                     'shortopt' => 'b',
                   13019:                     'doc' => 'Ignore changes in amount of white space',
                   13020:                     ),
                   13021:                 'ignore-blank-lines' => array(
                   13022:                     'shortopt' => 'B',
                   13023:                     'doc' => 'Ignore changes that insert or delete blank lines',
                   13024:                     ),
                   13025:                 'brief' => array(
                   13026:                     'doc' => 'Report only whether the files differ, no details',
                   13027:                     ),
                   13028:                 'dry-run' => array(
                   13029:                     'shortopt' => 'n',
                   13030:                     'doc' => 'Don\'t do anything, just pretend',
                   13031:                     ),
                   13032:                 ),
                   13033:             'doc' => '<package.xml>
                   13034: Compares all the files in a package.  Without any options, this
                   13035: command will compare the current code with the last checked-in code.
                   13036: Using the -r or -R option you may compare the current code with that
                   13037: of a specific release.
                   13038: ',
                   13039:             ),
                   13040:          'svntag' => array(
                   13041:              'summary' => 'Set SVN Release Tag',
                   13042:              'function' => 'doSvnTag',
                   13043:              'shortcut' => 'sv',
                   13044:              'options' => array(
                   13045:                  'quiet' => array(
                   13046:                      'shortopt' => 'q',
                   13047:                      'doc' => 'Be quiet',
                   13048:                      ),
                   13049:                  'slide' => array(
                   13050:                      'shortopt' => 'F',
                   13051:                      'doc' => 'Move (slide) tag if it exists',
                   13052:                      ),
                   13053:                  'delete' => array(
                   13054:                      'shortopt' => 'd',
                   13055:                      'doc' => 'Remove tag',
                   13056:                      ),
                   13057:                  'dry-run' => array(
                   13058:                      'shortopt' => 'n',
                   13059:                      'doc' => 'Don\'t do anything, just pretend',
                   13060:                      ),
                   13061:                  ),
                   13062:              'doc' => '<package.xml> [files...]
                   13063:  Sets a SVN tag on all files in a package.  Use this command after you have
                   13064:  packaged a distribution tarball with the "package" command to tag what
                   13065:  revisions of what files were in that release.  If need to fix something
                   13066:  after running svntag once, but before the tarball is released to the public,
                   13067:  use the "slide" option to move the release tag.
                   13068: 
                   13069:  to include files (such as a second package.xml, or tests not included in the
                   13070:  release), pass them as additional parameters.
                   13071:  ',
                   13072:              ),
                   13073:         'cvstag' => array(
                   13074:             'summary' => 'Set CVS Release Tag',
                   13075:             'function' => 'doCvsTag',
                   13076:             'shortcut' => 'ct',
                   13077:             'options' => array(
                   13078:                 'quiet' => array(
                   13079:                     'shortopt' => 'q',
                   13080:                     'doc' => 'Be quiet',
                   13081:                     ),
                   13082:                 'reallyquiet' => array(
                   13083:                     'shortopt' => 'Q',
                   13084:                     'doc' => 'Be really quiet',
                   13085:                     ),
                   13086:                 'slide' => array(
                   13087:                     'shortopt' => 'F',
                   13088:                     'doc' => 'Move (slide) tag if it exists',
                   13089:                     ),
                   13090:                 'delete' => array(
                   13091:                     'shortopt' => 'd',
                   13092:                     'doc' => 'Remove tag',
                   13093:                     ),
                   13094:                 'dry-run' => array(
                   13095:                     'shortopt' => 'n',
                   13096:                     'doc' => 'Don\'t do anything, just pretend',
                   13097:                     ),
                   13098:                 ),
                   13099:             'doc' => '<package.xml> [files...]
                   13100: Sets a CVS tag on all files in a package.  Use this command after you have
                   13101: packaged a distribution tarball with the "package" command to tag what
                   13102: revisions of what files were in that release.  If need to fix something
                   13103: after running cvstag once, but before the tarball is released to the public,
                   13104: use the "slide" option to move the release tag.
                   13105: 
                   13106: to include files (such as a second package.xml, or tests not included in the
                   13107: release), pass them as additional parameters.
                   13108: ',
                   13109:             ),
                   13110:         'package-dependencies' => array(
                   13111:             'summary' => 'Show package dependencies',
                   13112:             'function' => 'doPackageDependencies',
                   13113:             'shortcut' => 'pd',
                   13114:             'options' => array(),
                   13115:             'doc' => '<package-file> or <package.xml> or <install-package-name>
                   13116: List all dependencies the package has.
                   13117: Can take a tgz / tar file, package.xml or a package name of an installed package.'
                   13118:             ),
                   13119:         'sign' => array(
                   13120:             'summary' => 'Sign a package distribution file',
                   13121:             'function' => 'doSign',
                   13122:             'shortcut' => 'si',
                   13123:             'options' => array(
                   13124:                 'verbose' => array(
                   13125:                     'shortopt' => 'v',
                   13126:                     'doc' => 'Display GnuPG output',
                   13127:                     ),
                   13128:             ),
                   13129:             'doc' => '<package-file>
                   13130: Signs a package distribution (.tar or .tgz) file with GnuPG.',
                   13131:             ),
                   13132:         'makerpm' => array(
                   13133:             'summary' => 'Builds an RPM spec file from a PEAR package',
                   13134:             'function' => 'doMakeRPM',
                   13135:             'shortcut' => 'rpm',
                   13136:             'options' => array(
                   13137:                 'spec-template' => array(
                   13138:                     'shortopt' => 't',
                   13139:                     'arg' => 'FILE',
                   13140:                     'doc' => 'Use FILE as RPM spec file template'
                   13141:                     ),
                   13142:                 'rpm-pkgname' => array(
                   13143:                     'shortopt' => 'p',
                   13144:                     'arg' => 'FORMAT',
                   13145:                     'doc' => 'Use FORMAT as format string for RPM package name, %s is replaced
                   13146: by the PEAR package name, defaults to "PEAR::%s".',
                   13147:                     ),
                   13148:                 ),
                   13149:             'doc' => '<package-file>
                   13150: 
                   13151: Creates an RPM .spec file for wrapping a PEAR package inside an RPM
                   13152: package.  Intended to be used from the SPECS directory, with the PEAR
                   13153: package tarball in the SOURCES directory:
                   13154: 
                   13155: $ pear makerpm ../SOURCES/Net_Socket-1.0.tgz
                   13156: Wrote RPM spec file PEAR::Net_Geo-1.0.spec
                   13157: $ rpm -bb PEAR::Net_Socket-1.0.spec
                   13158: ...
                   13159: Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
                   13160: ',
                   13161:             ),
                   13162:         'convert' => array(
                   13163:             'summary' => 'Convert a package.xml 1.0 to package.xml 2.0 format',
                   13164:             'function' => 'doConvert',
                   13165:             'shortcut' => 'c2',
                   13166:             'options' => array(
                   13167:                 'flat' => array(
                   13168:                     'shortopt' => 'f',
                   13169:                     'doc' => 'do not beautify the filelist.',
                   13170:                     ),
                   13171:                 ),
                   13172:             'doc' => '[descfile] [descfile2]
                   13173: Converts a package.xml in 1.0 format into a package.xml
                   13174: in 2.0 format.  The new file will be named package2.xml by default,
                   13175: and package.xml will be used as the old file by default.
                   13176: This is not the most intelligent conversion, and should only be
                   13177: used for automated conversion or learning the format.
                   13178: '
                   13179:             ),
                   13180:         );
                   13181: 
                   13182:     var $output;
                   13183: 
                   13184:     /**
                   13185:      * PEAR_Command_Package constructor.
                   13186:      *
                   13187:      * @access public
                   13188:      */
                   13189:     function PEAR_Command_Package(&$ui, &$config)
                   13190:     {
                   13191:         parent::PEAR_Command_Common($ui, $config);
                   13192:     }
                   13193: 
                   13194:     function _displayValidationResults($err, $warn, $strict = false)
                   13195:     {
                   13196:         foreach ($err as $e) {
                   13197:             $this->output .= "Error: $e\n";
                   13198:         }
                   13199:         foreach ($warn as $w) {
                   13200:             $this->output .= "Warning: $w\n";
                   13201:         }
                   13202:         $this->output .= sprintf('Validation: %d error(s), %d warning(s)'."\n",
                   13203:                                        sizeof($err), sizeof($warn));
                   13204:         if ($strict && count($err) > 0) {
                   13205:             $this->output .= "Fix these errors and try again.";
                   13206:             return false;
                   13207:         }
                   13208:         return true;
                   13209:     }
                   13210: 
                   13211:     function &getPackager()
                   13212:     {
                   13213:         if (!class_exists('PEAR_Packager')) {
                   13214:             require_once 'PEAR/Packager.php';
                   13215:         }
                   13216:         $a = &new PEAR_Packager;
                   13217:         return $a;
                   13218:     }
                   13219: 
                   13220:     function &getPackageFile($config, $debug = false)
                   13221:     {
                   13222:         if (!class_exists('PEAR_Common')) {
                   13223:             require_once 'PEAR/Common.php';
                   13224:         }
                   13225:         if (!class_exists('PEAR_PackageFile')) {
                   13226:             require_once 'PEAR/PackageFile.php';
                   13227:         }
                   13228:         $a = &new PEAR_PackageFile($config, $debug);
                   13229:         $common = new PEAR_Common;
                   13230:         $common->ui = $this->ui;
                   13231:         $a->setLogger($common);
                   13232:         return $a;
                   13233:     }
                   13234: 
                   13235:     function doPackage($command, $options, $params)
                   13236:     {
                   13237:         $this->output = '';
                   13238:         $pkginfofile = isset($params[0]) ? $params[0] : 'package.xml';
                   13239:         $pkg2 = isset($params[1]) ? $params[1] : null;
                   13240:         if (!$pkg2 && !isset($params[0]) && file_exists('package2.xml')) {
                   13241:             $pkg2 = 'package2.xml';
                   13242:         }
                   13243: 
                   13244:         $packager = &$this->getPackager();
                   13245:         $compress = empty($options['nocompress']) ? true : false;
                   13246:         $result   = $packager->package($pkginfofile, $compress, $pkg2);
                   13247:         if (PEAR::isError($result)) {
                   13248:             return $this->raiseError($result);
                   13249:         }
                   13250: 
                   13251:         // Don't want output, only the package file name just created
                   13252:         if (isset($options['showname'])) {
                   13253:             $this->output = $result;
                   13254:         }
                   13255: 
                   13256:         if ($this->output) {
                   13257:             $this->ui->outputData($this->output, $command);
                   13258:         }
                   13259: 
                   13260:         return true;
                   13261:     }
                   13262: 
                   13263:     function doPackageValidate($command, $options, $params)
                   13264:     {
                   13265:         $this->output = '';
                   13266:         if (count($params) < 1) {
                   13267:             $params[0] = 'package.xml';
                   13268:         }
                   13269: 
                   13270:         $obj = &$this->getPackageFile($this->config, $this->_debug);
                   13271:         $obj->rawReturn();
                   13272:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   13273:         $info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL);
                   13274:         if (PEAR::isError($info)) {
                   13275:             $info = $obj->fromPackageFile($params[0], PEAR_VALIDATE_NORMAL);
                   13276:         } else {
                   13277:             $archive = $info->getArchiveFile();
                   13278:             $tar = &new Archive_Tar($archive);
                   13279:             $tar->extract(dirname($info->getPackageFile()));
                   13280:             $info->setPackageFile(dirname($info->getPackageFile()) . DIRECTORY_SEPARATOR .
                   13281:                 $info->getPackage() . '-' . $info->getVersion() . DIRECTORY_SEPARATOR .
                   13282:                 basename($info->getPackageFile()));
                   13283:         }
                   13284: 
                   13285:         PEAR::staticPopErrorHandling();
                   13286:         if (PEAR::isError($info)) {
                   13287:             return $this->raiseError($info);
                   13288:         }
                   13289: 
                   13290:         $valid = false;
                   13291:         if ($info->getPackagexmlVersion() == '2.0') {
                   13292:             if ($valid = $info->validate(PEAR_VALIDATE_NORMAL)) {
                   13293:                 $info->flattenFileList();
                   13294:                 $valid = $info->validate(PEAR_VALIDATE_PACKAGING);
                   13295:             }
                   13296:         } else {
                   13297:             $valid = $info->validate(PEAR_VALIDATE_PACKAGING);
                   13298:         }
                   13299: 
                   13300:         $err = $warn = array();
                   13301:         if ($errors = $info->getValidationWarnings()) {
                   13302:             foreach ($errors as $error) {
                   13303:                 if ($error['level'] == 'warning') {
                   13304:                     $warn[] = $error['message'];
                   13305:                 } else {
                   13306:                     $err[] = $error['message'];
                   13307:                 }
                   13308:             }
                   13309:         }
                   13310: 
                   13311:         $this->_displayValidationResults($err, $warn);
                   13312:         $this->ui->outputData($this->output, $command);
                   13313:         return true;
                   13314:     }
                   13315: 
                   13316:     function doSvnTag($command, $options, $params)
                   13317:     {
                   13318:         $this->output = '';
                   13319:         $_cmd = $command;
                   13320:         if (count($params) < 1) {
                   13321:             $help = $this->getHelp($command);
                   13322:             return $this->raiseError("$command: missing parameter: $help[0]");
                   13323:         }
                   13324: 
                   13325:         $packageFile = realpath($params[0]);
                   13326:         $dir = dirname($packageFile);
                   13327:         $dir = substr($dir, strrpos($dir, DIRECTORY_SEPARATOR) + 1);
                   13328:         $obj  = &$this->getPackageFile($this->config, $this->_debug);
                   13329:         $info = $obj->fromAnyFile($packageFile, PEAR_VALIDATE_NORMAL);
                   13330:         if (PEAR::isError($info)) {
                   13331:             return $this->raiseError($info);
                   13332:         }
                   13333: 
                   13334:         $err = $warn = array();
                   13335:         if (!$info->validate()) {
                   13336:             foreach ($info->getValidationWarnings() as $error) {
                   13337:                 if ($error['level'] == 'warning') {
                   13338:                     $warn[] = $error['message'];
                   13339:                 } else {
                   13340:                     $err[] = $error['message'];
                   13341:                 }
                   13342:             }
                   13343:         }
                   13344: 
                   13345:         if (!$this->_displayValidationResults($err, $warn, true)) {
                   13346:             $this->ui->outputData($this->output, $command);
                   13347:             return $this->raiseError('SVN tag failed');
                   13348:         }
                   13349: 
                   13350:         $version    = $info->getVersion();
                   13351:         $package    = $info->getName();
                   13352:         $svntag     = "$package-$version";
                   13353: 
                   13354:         if (isset($options['delete'])) {
                   13355:             return $this->_svnRemoveTag($version, $package, $svntag, $packageFile, $options);
                   13356:         }
                   13357: 
                   13358:         $path = $this->_svnFindPath($packageFile);
                   13359: 
                   13360:         // Check if there are any modified files
                   13361:         $fp = popen('svn st --xml ' . dirname($packageFile), "r");
                   13362:         $out = '';
                   13363:         while ($line = fgets($fp, 1024)) {
                   13364:             $out .= rtrim($line)."\n";
                   13365:         }
                   13366:         pclose($fp);
                   13367: 
                   13368:         if (!isset($options['quiet']) && strpos($out, 'item="modified"')) {
                   13369:             $params = array(array(
                   13370:                 'name' => 'modified',
                   13371:                 'type' => 'yesno',
                   13372:                 'default' => 'no',
                   13373:                 'prompt' => 'You have files in your SVN checkout (' . $path['from']  . ') that have been modified but not commited, do you still want to tag ' . $version . '?',
                   13374:             ));
                   13375:             $answers = $this->ui->confirmDialog($params);
                   13376: 
                   13377:             if (!in_array($answers['modified'], array('y', 'yes', 'on', '1'))) {
                   13378:                 return true;
                   13379:             }
                   13380:         }
                   13381: 
                   13382:         if (isset($options['slide'])) {
                   13383:             $this->_svnRemoveTag($version, $package, $svntag, $packageFile, $options);
                   13384:         }
                   13385: 
                   13386:         // Check if tag already exists
                   13387:         $releaseTag = $path['local']['base'] . 'tags' . DIRECTORY_SEPARATOR . $svntag;
                   13388:         $existsCommand = 'svn ls ' . $path['base'] . 'tags/';
                   13389: 
                   13390:         $fp = popen($existsCommand, "r");
                   13391:         $out = '';
                   13392:         while ($line = fgets($fp, 1024)) {
                   13393:             $out .= rtrim($line)."\n";
                   13394:         }
                   13395:         pclose($fp);
                   13396: 
                   13397:         if (in_array($svntag . DIRECTORY_SEPARATOR, explode("\n", $out))) {
                   13398:             $this->ui->outputData($this->output, $command);
                   13399:             return $this->raiseError('SVN tag ' . $svntag . ' for ' . $package . ' already exists.');
                   13400:         } elseif (file_exists($path['local']['base'] . 'tags') === false) {
                   13401:             return $this->raiseError('Can not locate the tags directory at ' . $path['local']['base'] . 'tags');
                   13402:         } elseif (is_writeable($path['local']['base'] . 'tags') === false) {
                   13403:             return $this->raiseError('Can not write to the tag directory at ' . $path['local']['base'] . 'tags');
                   13404:         } else {
                   13405:             $makeCommand = 'svn mkdir ' . $releaseTag;
                   13406:             $this->output .= "+ $makeCommand\n";
                   13407:             if (empty($options['dry-run'])) {
                   13408:                 // We need to create the tag dir.
                   13409:                 $fp = popen($makeCommand, "r");
                   13410:                 $out = '';
                   13411:                 while ($line = fgets($fp, 1024)) {
                   13412:                     $out .= rtrim($line)."\n";
                   13413:                 }
                   13414:                 pclose($fp);
                   13415:                 $this->output .= "$out\n";
                   13416:             }
                   13417:         }
                   13418: 
                   13419:         $command = 'svn';
                   13420:         if (isset($options['quiet'])) {
                   13421:             $command .= ' -q';
                   13422:         }
                   13423: 
                   13424:         $command .= ' copy --parents ';
                   13425: 
                   13426:         $dir   = dirname($packageFile);
                   13427:         $dir   = substr($dir, strrpos($dir, DIRECTORY_SEPARATOR) + 1);
                   13428:         $files = array_keys($info->getFilelist());
                   13429:         if (!in_array(basename($packageFile), $files)) {
                   13430:             $files[] = basename($packageFile);
                   13431:         }
                   13432: 
                   13433:         array_shift($params);
                   13434:         if (count($params)) {
                   13435:             // add in additional files to be tagged (package files and such)
                   13436:             $files = array_merge($files, $params);
                   13437:         }
                   13438: 
                   13439:         $commands = array();
                   13440:         foreach ($files as $file) {
                   13441:             if (!file_exists($file)) {
                   13442:                 $file = $dir . DIRECTORY_SEPARATOR . $file;
                   13443:             }
                   13444:             $commands[] = $command . ' ' . escapeshellarg($file) . ' ' .
                   13445:                           escapeshellarg($releaseTag . DIRECTORY_SEPARATOR . $file);
                   13446:         }
                   13447: 
                   13448:         $this->output .= implode("\n", $commands) . "\n";
                   13449:         if (empty($options['dry-run'])) {
                   13450:             foreach ($commands as $command) {
                   13451:                 $fp = popen($command, "r");
                   13452:                 while ($line = fgets($fp, 1024)) {
                   13453:                     $this->output .= rtrim($line)."\n";
                   13454:                 }
                   13455:                 pclose($fp);
                   13456:             }
                   13457:         }
                   13458: 
                   13459:         $command = 'svn ci -m "Tagging the ' . $version  . ' release" ' . $releaseTag . "\n";
                   13460:         $this->output .= "+ $command\n";
                   13461:         if (empty($options['dry-run'])) {
                   13462:             $fp = popen($command, "r");
                   13463:             while ($line = fgets($fp, 1024)) {
                   13464:                 $this->output .= rtrim($line)."\n";
                   13465:             }
                   13466:             pclose($fp);
                   13467:         }
                   13468: 
                   13469:         $this->ui->outputData($this->output, $_cmd);
                   13470:         return true;
                   13471:     }
                   13472: 
                   13473:     function _svnFindPath($file)
                   13474:     {
                   13475:         $xml = '';
                   13476:         $command = "svn info --xml $file";
                   13477:         $fp = popen($command, "r");
                   13478:         while ($line = fgets($fp, 1024)) {
                   13479:             $xml .= rtrim($line)."\n";
                   13480:         }
                   13481:         pclose($fp);
                   13482:         $url_tag = strpos($xml, '<url>');
                   13483:         $url = substr($xml, $url_tag + 5, strpos($xml, '</url>', $url_tag + 5) - ($url_tag + 5));
                   13484: 
                   13485:         $path = array();
                   13486:         $path['from'] = substr($url, 0, strrpos($url, '/'));
                   13487:         $path['base'] = substr($path['from'], 0, strrpos($path['from'], '/') + 1);
                   13488: 
                   13489:         // Figure out the local paths - see http://pear.php.net/bugs/17463
                   13490:         $pos = strpos($file, DIRECTORY_SEPARATOR . 'trunk' . DIRECTORY_SEPARATOR);
                   13491:         if ($pos === false) {
                   13492:             $pos = strpos($file, DIRECTORY_SEPARATOR . 'branches' . DIRECTORY_SEPARATOR);
                   13493:         }
                   13494:         $path['local']['base'] = substr($file, 0, $pos + 1);
                   13495: 
                   13496:         return $path;
                   13497:     }
                   13498: 
                   13499:     function _svnRemoveTag($version, $package, $tag, $packageFile, $options)
                   13500:     {
                   13501:         $command = 'svn';
                   13502: 
                   13503:         if (isset($options['quiet'])) {
                   13504:             $command .= ' -q';
                   13505:         }
                   13506: 
                   13507:         $command .= ' remove';
                   13508:         $command .= ' -m "Removing tag for the ' . $version  . ' release."';
                   13509: 
                   13510:         $path = $this->_svnFindPath($packageFile);
                   13511:         $command .= ' ' . $path['base'] . 'tags/' . $tag;
                   13512: 
                   13513: 
                   13514:         if ($this->config->get('verbose') > 1) {
                   13515:             $this->output .= "+ $command\n";
                   13516:         }
                   13517: 
                   13518:         $this->output .= "+ $command\n";
                   13519:         if (empty($options['dry-run'])) {
                   13520:             $fp = popen($command, "r");
                   13521:             while ($line = fgets($fp, 1024)) {
                   13522:                 $this->output .= rtrim($line)."\n";
                   13523:             }
                   13524:             pclose($fp);
                   13525:         }
                   13526: 
                   13527:         $this->ui->outputData($this->output, $command);
                   13528:         return true;
                   13529:     }
                   13530: 
                   13531:     function doCvsTag($command, $options, $params)
                   13532:     {
                   13533:         $this->output = '';
                   13534:         $_cmd = $command;
                   13535:         if (count($params) < 1) {
                   13536:             $help = $this->getHelp($command);
                   13537:             return $this->raiseError("$command: missing parameter: $help[0]");
                   13538:         }
                   13539: 
                   13540:         $packageFile = realpath($params[0]);
                   13541:         $obj  = &$this->getPackageFile($this->config, $this->_debug);
                   13542:         $info = $obj->fromAnyFile($packageFile, PEAR_VALIDATE_NORMAL);
                   13543:         if (PEAR::isError($info)) {
                   13544:             return $this->raiseError($info);
                   13545:         }
                   13546: 
                   13547:         $err = $warn = array();
                   13548:         if (!$info->validate()) {
                   13549:             foreach ($info->getValidationWarnings() as $error) {
                   13550:                 if ($error['level'] == 'warning') {
                   13551:                     $warn[] = $error['message'];
                   13552:                 } else {
                   13553:                     $err[] = $error['message'];
                   13554:                 }
                   13555:             }
                   13556:         }
                   13557: 
                   13558:         if (!$this->_displayValidationResults($err, $warn, true)) {
                   13559:             $this->ui->outputData($this->output, $command);
                   13560:             return $this->raiseError('CVS tag failed');
                   13561:         }
                   13562: 
                   13563:         $version    = $info->getVersion();
                   13564:         $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $version);
                   13565:         $cvstag     = "RELEASE_$cvsversion";
                   13566:         $files      = array_keys($info->getFilelist());
                   13567:         $command = 'cvs';
                   13568:         if (isset($options['quiet'])) {
                   13569:             $command .= ' -q';
                   13570:         }
                   13571: 
                   13572:         if (isset($options['reallyquiet'])) {
                   13573:             $command .= ' -Q';
                   13574:         }
                   13575: 
                   13576:         $command .= ' tag';
                   13577:         if (isset($options['slide'])) {
                   13578:             $command .= ' -F';
                   13579:         }
                   13580: 
                   13581:         if (isset($options['delete'])) {
                   13582:             $command .= ' -d';
                   13583:         }
                   13584: 
                   13585:         $command .= ' ' . $cvstag . ' ' . escapeshellarg($params[0]);
                   13586:         array_shift($params);
                   13587:         if (count($params)) {
                   13588:             // add in additional files to be tagged
                   13589:             $files = array_merge($files, $params);
                   13590:         }
                   13591: 
                   13592:         $dir = dirname($packageFile);
                   13593:         $dir = substr($dir, strrpos($dir, '/') + 1);
                   13594:         foreach ($files as $file) {
                   13595:             if (!file_exists($file)) {
                   13596:                 $file = $dir . DIRECTORY_SEPARATOR . $file;
                   13597:             }
                   13598:             $command .= ' ' . escapeshellarg($file);
                   13599:         }
                   13600: 
                   13601:         if ($this->config->get('verbose') > 1) {
                   13602:             $this->output .= "+ $command\n";
                   13603:         }
                   13604: 
                   13605:         $this->output .= "+ $command\n";
                   13606:         if (empty($options['dry-run'])) {
                   13607:             $fp = popen($command, "r");
                   13608:             while ($line = fgets($fp, 1024)) {
                   13609:                 $this->output .= rtrim($line)."\n";
                   13610:             }
                   13611:             pclose($fp);
                   13612:         }
                   13613: 
                   13614:         $this->ui->outputData($this->output, $_cmd);
                   13615:         return true;
                   13616:     }
                   13617: 
                   13618:     function doCvsDiff($command, $options, $params)
                   13619:     {
                   13620:         $this->output = '';
                   13621:         if (sizeof($params) < 1) {
                   13622:             $help = $this->getHelp($command);
                   13623:             return $this->raiseError("$command: missing parameter: $help[0]");
                   13624:         }
                   13625: 
                   13626:         $file = realpath($params[0]);
                   13627:         $obj  = &$this->getPackageFile($this->config, $this->_debug);
                   13628:         $info = $obj->fromAnyFile($file, PEAR_VALIDATE_NORMAL);
                   13629:         if (PEAR::isError($info)) {
                   13630:             return $this->raiseError($info);
                   13631:         }
                   13632: 
                   13633:         $err = $warn = array();
                   13634:         if (!$info->validate()) {
                   13635:             foreach ($info->getValidationWarnings() as $error) {
                   13636:                 if ($error['level'] == 'warning') {
                   13637:                     $warn[] = $error['message'];
                   13638:                 } else {
                   13639:                     $err[] = $error['message'];
                   13640:                 }
                   13641:             }
                   13642:         }
                   13643: 
                   13644:         if (!$this->_displayValidationResults($err, $warn, true)) {
                   13645:             $this->ui->outputData($this->output, $command);
                   13646:             return $this->raiseError('CVS diff failed');
                   13647:         }
                   13648: 
                   13649:         $info1 = $info->getFilelist();
                   13650:         $files = $info1;
                   13651:         $cmd = "cvs";
                   13652:         if (isset($options['quiet'])) {
                   13653:             $cmd .= ' -q';
                   13654:             unset($options['quiet']);
                   13655:         }
                   13656: 
                   13657:         if (isset($options['reallyquiet'])) {
                   13658:             $cmd .= ' -Q';
                   13659:             unset($options['reallyquiet']);
                   13660:         }
                   13661: 
                   13662:         if (isset($options['release'])) {
                   13663:             $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $options['release']);
                   13664:             $cvstag = "RELEASE_$cvsversion";
                   13665:             $options['revision'] = $cvstag;
                   13666:             unset($options['release']);
                   13667:         }
                   13668: 
                   13669:         $execute = true;
                   13670:         if (isset($options['dry-run'])) {
                   13671:             $execute = false;
                   13672:             unset($options['dry-run']);
                   13673:         }
                   13674: 
                   13675:         $cmd .= ' diff';
                   13676:         // the rest of the options are passed right on to "cvs diff"
                   13677:         foreach ($options as $option => $optarg) {
                   13678:             $arg = $short = false;
                   13679:             if (isset($this->commands[$command]['options'][$option])) {
                   13680:                 $arg = $this->commands[$command]['options'][$option]['arg'];
                   13681:                 $short = $this->commands[$command]['options'][$option]['shortopt'];
                   13682:             }
                   13683:             $cmd .= $short ? " -$short" : " --$option";
                   13684:             if ($arg && $optarg) {
                   13685:                 $cmd .= ($short ? '' : '=') . escapeshellarg($optarg);
                   13686:             }
                   13687:         }
                   13688: 
                   13689:         foreach ($files as $file) {
                   13690:             $cmd .= ' ' . escapeshellarg($file['name']);
                   13691:         }
                   13692: 
                   13693:         if ($this->config->get('verbose') > 1) {
                   13694:             $this->output .= "+ $cmd\n";
                   13695:         }
                   13696: 
                   13697:         if ($execute) {
                   13698:             $fp = popen($cmd, "r");
                   13699:             while ($line = fgets($fp, 1024)) {
                   13700:                 $this->output .= rtrim($line)."\n";
                   13701:             }
                   13702:             pclose($fp);
                   13703:         }
                   13704: 
                   13705:         $this->ui->outputData($this->output, $command);
                   13706:         return true;
                   13707:     }
                   13708: 
                   13709:     function doPackageDependencies($command, $options, $params)
                   13710:     {
                   13711:         // $params[0] -> the PEAR package to list its information
                   13712:         if (count($params) !== 1) {
                   13713:             return $this->raiseError("bad parameter(s), try \"help $command\"");
                   13714:         }
                   13715: 
                   13716:         $obj = &$this->getPackageFile($this->config, $this->_debug);
                   13717:         if (is_file($params[0]) || strpos($params[0], '.xml') > 0) {
                   13718:            $info = $obj->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
                   13719:         } else {
                   13720:             $reg  = $this->config->getRegistry();
                   13721:             $info = $obj->fromArray($reg->packageInfo($params[0]));
                   13722:         }
                   13723: 
                   13724:         if (PEAR::isError($info)) {
                   13725:             return $this->raiseError($info);
                   13726:         }
                   13727: 
                   13728:         $deps = $info->getDeps();
                   13729:         if (is_array($deps)) {
                   13730:             if ($info->getPackagexmlVersion() == '1.0') {
                   13731:                 $data = array(
                   13732:                     'caption' => 'Dependencies for pear/' . $info->getPackage(),
                   13733:                     'border' => true,
                   13734:                     'headline' => array("Required?", "Type", "Name", "Relation", "Version"),
                   13735:                     );
                   13736: 
                   13737:                 foreach ($deps as $d) {
                   13738:                     if (isset($d['optional'])) {
                   13739:                         if ($d['optional'] == 'yes') {
                   13740:                             $req = 'No';
                   13741:                         } else {
                   13742:                             $req = 'Yes';
                   13743:                         }
                   13744:                     } else {
                   13745:                         $req = 'Yes';
                   13746:                     }
                   13747: 
                   13748:                     if (isset($this->_deps_rel_trans[$d['rel']])) {
                   13749:                         $rel = $this->_deps_rel_trans[$d['rel']];
                   13750:                     } else {
                   13751:                         $rel = $d['rel'];
                   13752:                     }
                   13753: 
                   13754:                     if (isset($this->_deps_type_trans[$d['type']])) {
                   13755:                         $type = ucfirst($this->_deps_type_trans[$d['type']]);
                   13756:                     } else {
                   13757:                         $type = $d['type'];
                   13758:                     }
                   13759: 
                   13760:                     if (isset($d['name'])) {
                   13761:                         $name = $d['name'];
                   13762:                     } else {
                   13763:                         $name = '';
                   13764:                     }
                   13765: 
                   13766:                     if (isset($d['version'])) {
                   13767:                         $version = $d['version'];
                   13768:                     } else {
                   13769:                         $version = '';
                   13770:                     }
                   13771: 
                   13772:                     $data['data'][] = array($req, $type, $name, $rel, $version);
                   13773:                 }
                   13774:             } else { // package.xml 2.0 dependencies display
                   13775:                 require_once 'PEAR/Dependency2.php';
                   13776:                 $deps = $info->getDependencies();
                   13777:                 $reg = &$this->config->getRegistry();
                   13778:                 if (is_array($deps)) {
                   13779:                     $d = new PEAR_Dependency2($this->config, array(), '');
                   13780:                     $data = array(
                   13781:                         'caption' => 'Dependencies for ' . $info->getPackage(),
                   13782:                         'border' => true,
                   13783:                         'headline' => array("Required?", "Type", "Name", 'Versioning', 'Group'),
                   13784:                         );
                   13785:                     foreach ($deps as $type => $subd) {
                   13786:                         $req = ($type == 'required') ? 'Yes' : 'No';
                   13787:                         if ($type == 'group') {
                   13788:                             $group = $subd['attribs']['name'];
                   13789:                         } else {
                   13790:                             $group = '';
                   13791:                         }
                   13792: 
                   13793:                         if (!isset($subd[0])) {
                   13794:                             $subd = array($subd);
                   13795:                         }
                   13796: 
                   13797:                         foreach ($subd as $groupa) {
                   13798:                             foreach ($groupa as $deptype => $depinfo) {
                   13799:                                 if ($deptype == 'attribs') {
                   13800:                                     continue;
                   13801:                                 }
                   13802: 
                   13803:                                 if ($deptype == 'pearinstaller') {
                   13804:                                     $deptype = 'pear Installer';
                   13805:                                 }
                   13806: 
                   13807:                                 if (!isset($depinfo[0])) {
                   13808:                                     $depinfo = array($depinfo);
                   13809:                                 }
                   13810: 
                   13811:                                 foreach ($depinfo as $inf) {
                   13812:                                     $name = '';
                   13813:                                     if (isset($inf['channel'])) {
                   13814:                                         $alias = $reg->channelAlias($inf['channel']);
                   13815:                                         if (!$alias) {
                   13816:                                             $alias = '(channel?) ' .$inf['channel'];
                   13817:                                         }
                   13818:                                         $name = $alias . '/';
                   13819: 
                   13820:                                     }
                   13821:                                     if (isset($inf['name'])) {
                   13822:                                         $name .= $inf['name'];
                   13823:                                     } elseif (isset($inf['pattern'])) {
                   13824:                                         $name .= $inf['pattern'];
                   13825:                                     } else {
                   13826:                                         $name .= '';
                   13827:                                     }
                   13828: 
                   13829:                                     if (isset($inf['uri'])) {
                   13830:                                         $name .= ' [' . $inf['uri'] .  ']';
                   13831:                                     }
                   13832: 
                   13833:                                     if (isset($inf['conflicts'])) {
                   13834:                                         $ver = 'conflicts';
                   13835:                                     } else {
                   13836:                                         $ver = $d->_getExtraString($inf);
                   13837:                                     }
                   13838: 
                   13839:                                     $data['data'][] = array($req, ucfirst($deptype), $name,
                   13840:                                         $ver, $group);
                   13841:                                 }
                   13842:                             }
                   13843:                         }
                   13844:                     }
                   13845:                 }
                   13846:             }
                   13847: 
                   13848:             $this->ui->outputData($data, $command);
                   13849:             return true;
                   13850:         }
                   13851: 
                   13852:         // Fallback
                   13853:         $this->ui->outputData("This package does not have any dependencies.", $command);
                   13854:     }
                   13855: 
                   13856:     function doSign($command, $options, $params)
                   13857:     {
                   13858:         // should move most of this code into PEAR_Packager
                   13859:         // so it'll be easy to implement "pear package --sign"
                   13860:         if (count($params) !== 1) {
                   13861:             return $this->raiseError("bad parameter(s), try \"help $command\"");
                   13862:         }
                   13863: 
                   13864:         require_once 'System.php';
                   13865:         require_once 'Archive/Tar.php';
                   13866: 
                   13867:         if (!file_exists($params[0])) {
                   13868:             return $this->raiseError("file does not exist: $params[0]");
                   13869:         }
                   13870: 
                   13871:         $obj = $this->getPackageFile($this->config, $this->_debug);
                   13872:         $info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL);
                   13873:         if (PEAR::isError($info)) {
                   13874:             return $this->raiseError($info);
                   13875:         }
                   13876: 
                   13877:         $tar = new Archive_Tar($params[0]);
                   13878: 
                   13879:         $tmpdir = $this->config->get('temp_dir');
                   13880:         $tmpdir = System::mktemp(' -t "' . $tmpdir . '" -d pearsign');
                   13881:         if (!$tar->extractList('package2.xml package.xml package.sig', $tmpdir)) {
                   13882:             return $this->raiseError("failed to extract tar file");
                   13883:         }
                   13884: 
                   13885:         if (file_exists("$tmpdir/package.sig")) {
                   13886:             return $this->raiseError("package already signed");
                   13887:         }
                   13888: 
                   13889:         $packagexml = 'package.xml';
                   13890:         if (file_exists("$tmpdir/package2.xml")) {
                   13891:             $packagexml = 'package2.xml';
                   13892:         }
                   13893: 
                   13894:         if (file_exists("$tmpdir/package.sig")) {
                   13895:             unlink("$tmpdir/package.sig");
                   13896:         }
                   13897: 
                   13898:         if (!file_exists("$tmpdir/$packagexml")) {
                   13899:             return $this->raiseError("Extracted file $tmpdir/$packagexml not found.");
                   13900:         }
                   13901: 
                   13902:         $input = $this->ui->userDialog($command,
                   13903:                                        array('GnuPG Passphrase'),
                   13904:                                        array('password'));
                   13905:         if (!isset($input[0])) {
                   13906:             //use empty passphrase
                   13907:             $input[0] = '';
                   13908:         }
                   13909: 
                   13910:         $devnull = (isset($options['verbose'])) ? '' : ' 2>/dev/null';
                   13911:         $gpg = popen("gpg --batch --passphrase-fd 0 --armor --detach-sign --output $tmpdir/package.sig $tmpdir/$packagexml" . $devnull, "w");
                   13912:         if (!$gpg) {
                   13913:             return $this->raiseError("gpg command failed");
                   13914:         }
                   13915: 
                   13916:         fwrite($gpg, "$input[0]\n");
                   13917:         if (pclose($gpg) || !file_exists("$tmpdir/package.sig")) {
                   13918:             return $this->raiseError("gpg sign failed");
                   13919:         }
                   13920: 
                   13921:         if (!$tar->addModify("$tmpdir/package.sig", '', $tmpdir)) {
                   13922:             return $this->raiseError('failed adding signature to file');
                   13923:         }
                   13924: 
                   13925:         $this->ui->outputData("Package signed.", $command);
                   13926:         return true;
                   13927:     }
                   13928: 
                   13929:     /**
                   13930:      * For unit testing purposes
                   13931:      */
                   13932:     function &getInstaller(&$ui)
                   13933:     {
                   13934:         if (!class_exists('PEAR_Installer')) {
                   13935:             require_once 'PEAR/Installer.php';
                   13936:         }
                   13937:         $a = &new PEAR_Installer($ui);
                   13938:         return $a;
                   13939:     }
                   13940: 
                   13941:     /**
                   13942:      * For unit testing purposes
                   13943:      */
                   13944:     function &getCommandPackaging(&$ui, &$config)
                   13945:     {
                   13946:         if (!class_exists('PEAR_Command_Packaging')) {
                   13947:             if ($fp = @fopen('PEAR/Command/Packaging.php', 'r', true)) {
                   13948:                 fclose($fp);
                   13949:                 include_once 'PEAR/Command/Packaging.php';
                   13950:             }
                   13951:         }
                   13952: 
                   13953:         if (class_exists('PEAR_Command_Packaging')) {
                   13954:             $a = &new PEAR_Command_Packaging($ui, $config);
                   13955:         } else {
                   13956:             $a = null;
                   13957:         }
                   13958: 
                   13959:         return $a;
                   13960:     }
                   13961: 
                   13962:     function doMakeRPM($command, $options, $params)
                   13963:     {
                   13964: 
                   13965:         // Check to see if PEAR_Command_Packaging is installed, and
                   13966:         // transparently switch to use the "make-rpm-spec" command from it
                   13967:         // instead, if it does. Otherwise, continue to use the old version
                   13968:         // of "makerpm" supplied with this package (PEAR).
                   13969:         $packaging_cmd = $this->getCommandPackaging($this->ui, $this->config);
                   13970:         if ($packaging_cmd !== null) {
                   13971:             $this->ui->outputData('PEAR_Command_Packaging is installed; using '.
                   13972:                 'newer "make-rpm-spec" command instead');
                   13973:             return $packaging_cmd->run('make-rpm-spec', $options, $params);
                   13974:         }
                   13975: 
                   13976:         $this->ui->outputData('WARNING: "pear makerpm" is no longer available; an '.
                   13977:           'improved version is available via "pear make-rpm-spec", which '.
                   13978:           'is available by installing PEAR_Command_Packaging');
                   13979:         return true;
                   13980:     }
                   13981: 
                   13982:     function doConvert($command, $options, $params)
                   13983:     {
                   13984:         $packagexml    = isset($params[0]) ? $params[0] : 'package.xml';
                   13985:         $newpackagexml = isset($params[1]) ? $params[1] : dirname($packagexml) .
                   13986:             DIRECTORY_SEPARATOR . 'package2.xml';
                   13987:         $pkg = &$this->getPackageFile($this->config, $this->_debug);
                   13988:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   13989:         $pf = $pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL);
                   13990:         PEAR::staticPopErrorHandling();
                   13991:         if (PEAR::isError($pf)) {
                   13992:             if (is_array($pf->getUserInfo())) {
                   13993:                 foreach ($pf->getUserInfo() as $warning) {
                   13994:                     $this->ui->outputData($warning['message']);
                   13995:                 }
                   13996:             }
                   13997:             return $this->raiseError($pf);
                   13998:         }
                   13999: 
                   14000:         if (is_a($pf, 'PEAR_PackageFile_v2')) {
                   14001:             $this->ui->outputData($packagexml . ' is already a package.xml version 2.0');
                   14002:             return true;
                   14003:         }
                   14004: 
                   14005:         $gen   = &$pf->getDefaultGenerator();
                   14006:         $newpf = &$gen->toV2();
                   14007:         $newpf->setPackagefile($newpackagexml);
                   14008:         $gen = &$newpf->getDefaultGenerator();
                   14009:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   14010:         $state = (isset($options['flat']) ? PEAR_VALIDATE_PACKAGING : PEAR_VALIDATE_NORMAL);
                   14011:         $saved = $gen->toPackageFile(dirname($newpackagexml), $state, basename($newpackagexml));
                   14012:         PEAR::staticPopErrorHandling();
                   14013:         if (PEAR::isError($saved)) {
                   14014:             if (is_array($saved->getUserInfo())) {
                   14015:                 foreach ($saved->getUserInfo() as $warning) {
                   14016:                     $this->ui->outputData($warning['message']);
                   14017:                 }
                   14018:             }
                   14019: 
                   14020:             $this->ui->outputData($saved->getMessage());
                   14021:             return true;
                   14022:         }
                   14023: 
                   14024:         $this->ui->outputData('Wrote new version 2.0 package.xml to "' . $saved . '"');
                   14025:         return true;
                   14026:     }
1.1.1.2 ! misho    14027: }PEAR-1.9.4/PEAR/Command/Pickle.xml0000644000076500000240000000223311605156614015272 0ustar  helgistaff<commands version="1.0">
1.1       misho    14028:  <pickle>
                   14029:   <summary>Build PECL Package</summary>
                   14030:   <function>doPackage</function>
                   14031:   <shortcut>pi</shortcut>
                   14032:   <options>
                   14033:    <nocompress>
                   14034:     <shortopt>Z</shortopt>
                   14035:     <doc>Do not gzip the package file</doc>
                   14036:    </nocompress>
                   14037:    <showname>
                   14038:     <shortopt>n</shortopt>
                   14039:     <doc>Print the name of the packaged file.</doc>
                   14040:    </showname>
                   14041:   </options>
                   14042:   <doc>[descfile]
                   14043: Creates a PECL package from its package2.xml file.
                   14044: 
                   14045: An automatic conversion will be made to a package.xml 1.0 and written out to
                   14046: disk in the current directory as &quot;package.xml&quot;.  Note that
                   14047: only simple package.xml 2.0 will be converted.  package.xml 2.0 with:
                   14048: 
                   14049:  - dependency types other than required/optional PECL package/ext/php/pearinstaller
                   14050:  - more than one extsrcrelease or zendextsrcrelease
                   14051:  - zendextbinrelease, extbinrelease, phprelease, or bundle release type
                   14052:  - dependency groups
                   14053:  - ignore tags in release filelist
                   14054:  - tasks other than replace
                   14055:  - custom roles
                   14056: 
                   14057: will cause pickle to fail, and output an error message.  If your package2.xml
                   14058: uses any of these features, you are best off using PEAR_PackageFileManager to
                   14059: generate both package.xml.
                   14060: </doc>
                   14061:  </pickle>
1.1.1.2 ! misho    14062: </commands>PEAR-1.9.4/PEAR/Command/Pickle.php0000644000076500000240000003715611605156614015275 0ustar  helgistaff<?php
1.1       misho    14063: /**
                   14064:  * PEAR_Command_Pickle (pickle command)
                   14065:  *
                   14066:  * PHP versions 4 and 5
                   14067:  *
                   14068:  * @category   pear
                   14069:  * @package    PEAR
                   14070:  * @author     Greg Beaver <cellog@php.net>
                   14071:  * @copyright  2005-2009 The Authors
                   14072:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   14073:  * @version    CVS: $Id: Pickle.php 313023 2011-07-06 19:17:11Z dufuz $
                   14074:  * @link       http://pear.php.net/package/PEAR
                   14075:  * @since      File available since Release 1.4.1
                   14076:  */
                   14077: 
                   14078: /**
                   14079:  * base class
                   14080:  */
                   14081: require_once 'PEAR/Command/Common.php';
                   14082: 
                   14083: /**
                   14084:  * PEAR commands for login/logout
                   14085:  *
                   14086:  * @category   pear
                   14087:  * @package    PEAR
                   14088:  * @author     Greg Beaver <cellog@php.net>
                   14089:  * @copyright  2005-2009 The Authors
                   14090:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   14091:  * @version    Release: 1.9.4
                   14092:  * @link       http://pear.php.net/package/PEAR
                   14093:  * @since      Class available since Release 1.4.1
                   14094:  */
                   14095: 
                   14096: class PEAR_Command_Pickle extends PEAR_Command_Common
                   14097: {
                   14098:     var $commands = array(
                   14099:         'pickle' => array(
                   14100:             'summary' => 'Build PECL Package',
                   14101:             'function' => 'doPackage',
                   14102:             'shortcut' => 'pi',
                   14103:             'options' => array(
                   14104:                 'nocompress' => array(
                   14105:                     'shortopt' => 'Z',
                   14106:                     'doc' => 'Do not gzip the package file'
                   14107:                     ),
                   14108:                 'showname' => array(
                   14109:                     'shortopt' => 'n',
                   14110:                     'doc' => 'Print the name of the packaged file.',
                   14111:                     ),
                   14112:                 ),
                   14113:             'doc' => '[descfile]
                   14114: Creates a PECL package from its package2.xml file.
                   14115: 
                   14116: An automatic conversion will be made to a package.xml 1.0 and written out to
                   14117: disk in the current directory as "package.xml".  Note that
                   14118: only simple package.xml 2.0 will be converted.  package.xml 2.0 with:
                   14119: 
                   14120:  - dependency types other than required/optional PECL package/ext/php/pearinstaller
                   14121:  - more than one extsrcrelease or zendextsrcrelease
                   14122:  - zendextbinrelease, extbinrelease, phprelease, or bundle release type
                   14123:  - dependency groups
                   14124:  - ignore tags in release filelist
                   14125:  - tasks other than replace
                   14126:  - custom roles
                   14127: 
                   14128: will cause pickle to fail, and output an error message.  If your package2.xml
                   14129: uses any of these features, you are best off using PEAR_PackageFileManager to
                   14130: generate both package.xml.
                   14131: '
                   14132:             ),
                   14133:         );
                   14134: 
                   14135:     /**
                   14136:      * PEAR_Command_Package constructor.
                   14137:      *
                   14138:      * @access public
                   14139:      */
                   14140:     function PEAR_Command_Pickle(&$ui, &$config)
                   14141:     {
                   14142:         parent::PEAR_Command_Common($ui, $config);
                   14143:     }
                   14144: 
                   14145:     /**
                   14146:      * For unit-testing ease
                   14147:      *
                   14148:      * @return PEAR_Packager
                   14149:      */
                   14150:     function &getPackager()
                   14151:     {
                   14152:         if (!class_exists('PEAR_Packager')) {
                   14153:             require_once 'PEAR/Packager.php';
                   14154:         }
                   14155: 
                   14156:         $a = &new PEAR_Packager;
                   14157:         return $a;
                   14158:     }
                   14159: 
                   14160:     /**
                   14161:      * For unit-testing ease
                   14162:      *
                   14163:      * @param PEAR_Config $config
                   14164:      * @param bool $debug
                   14165:      * @param string|null $tmpdir
                   14166:      * @return PEAR_PackageFile
                   14167:      */
                   14168:     function &getPackageFile($config, $debug = false)
                   14169:     {
                   14170:         if (!class_exists('PEAR_Common')) {
                   14171:             require_once 'PEAR/Common.php';
                   14172:         }
                   14173: 
                   14174:         if (!class_exists('PEAR_PackageFile')) {
                   14175:             require_once 'PEAR/PackageFile.php';
                   14176:         }
                   14177: 
                   14178:         $a = &new PEAR_PackageFile($config, $debug);
                   14179:         $common = new PEAR_Common;
                   14180:         $common->ui = $this->ui;
                   14181:         $a->setLogger($common);
                   14182:         return $a;
                   14183:     }
                   14184: 
                   14185:     function doPackage($command, $options, $params)
                   14186:     {
                   14187:         $this->output = '';
                   14188:         $pkginfofile = isset($params[0]) ? $params[0] : 'package2.xml';
                   14189:         $packager = &$this->getPackager();
                   14190:         if (PEAR::isError($err = $this->_convertPackage($pkginfofile))) {
                   14191:             return $err;
                   14192:         }
                   14193: 
                   14194:         $compress = empty($options['nocompress']) ? true : false;
                   14195:         $result = $packager->package($pkginfofile, $compress, 'package.xml');
                   14196:         if (PEAR::isError($result)) {
                   14197:             return $this->raiseError($result);
                   14198:         }
                   14199: 
                   14200:         // Don't want output, only the package file name just created
                   14201:         if (isset($options['showname'])) {
                   14202:             $this->ui->outputData($result, $command);
                   14203:         }
                   14204: 
                   14205:         return true;
                   14206:     }
                   14207: 
                   14208:     function _convertPackage($packagexml)
                   14209:     {
                   14210:         $pkg = &$this->getPackageFile($this->config);
                   14211:         $pf2 = &$pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL);
                   14212:         if (!is_a($pf2, 'PEAR_PackageFile_v2')) {
                   14213:             return $this->raiseError('Cannot process "' .
                   14214:                 $packagexml . '", is not a package.xml 2.0');
                   14215:         }
                   14216: 
                   14217:         require_once 'PEAR/PackageFile/v1.php';
                   14218:         $pf = new PEAR_PackageFile_v1;
                   14219:         $pf->setConfig($this->config);
                   14220:         if ($pf2->getPackageType() != 'extsrc' && $pf2->getPackageType() != 'zendextsrc') {
                   14221:             return $this->raiseError('Cannot safely convert "' . $packagexml .
                   14222:             '", is not an extension source package.  Using a PEAR_PackageFileManager-based ' .
                   14223:             'script is an option');
                   14224:         }
                   14225: 
                   14226:         if (is_array($pf2->getUsesRole())) {
                   14227:             return $this->raiseError('Cannot safely convert "' . $packagexml .
                   14228:             '", contains custom roles.  Using a PEAR_PackageFileManager-based script or ' .
                   14229:             'the convert command is an option');
                   14230:         }
                   14231: 
                   14232:         if (is_array($pf2->getUsesTask())) {
                   14233:             return $this->raiseError('Cannot safely convert "' . $packagexml .
                   14234:             '", contains custom tasks.  Using a PEAR_PackageFileManager-based script or ' .
                   14235:             'the convert command is an option');
                   14236:         }
                   14237: 
                   14238:         $deps = $pf2->getDependencies();
                   14239:         if (isset($deps['group'])) {
                   14240:             return $this->raiseError('Cannot safely convert "' . $packagexml .
                   14241:             '", contains dependency groups.  Using a PEAR_PackageFileManager-based script ' .
                   14242:             'or the convert command is an option');
                   14243:         }
                   14244: 
                   14245:         if (isset($deps['required']['subpackage']) ||
                   14246:               isset($deps['optional']['subpackage'])) {
                   14247:             return $this->raiseError('Cannot safely convert "' . $packagexml .
                   14248:             '", contains subpackage dependencies.  Using a PEAR_PackageFileManager-based  '.
                   14249:             'script is an option');
                   14250:         }
                   14251: 
                   14252:         if (isset($deps['required']['os'])) {
                   14253:             return $this->raiseError('Cannot safely convert "' . $packagexml .
                   14254:             '", contains os dependencies.  Using a PEAR_PackageFileManager-based  '.
                   14255:             'script is an option');
                   14256:         }
                   14257: 
                   14258:         if (isset($deps['required']['arch'])) {
                   14259:             return $this->raiseError('Cannot safely convert "' . $packagexml .
                   14260:             '", contains arch dependencies.  Using a PEAR_PackageFileManager-based  '.
                   14261:             'script is an option');
                   14262:         }
                   14263: 
                   14264:         $pf->setPackage($pf2->getPackage());
                   14265:         $pf->setSummary($pf2->getSummary());
                   14266:         $pf->setDescription($pf2->getDescription());
                   14267:         foreach ($pf2->getMaintainers() as $maintainer) {
                   14268:             $pf->addMaintainer($maintainer['role'], $maintainer['handle'],
                   14269:                 $maintainer['name'], $maintainer['email']);
                   14270:         }
                   14271: 
                   14272:         $pf->setVersion($pf2->getVersion());
                   14273:         $pf->setDate($pf2->getDate());
                   14274:         $pf->setLicense($pf2->getLicense());
                   14275:         $pf->setState($pf2->getState());
                   14276:         $pf->setNotes($pf2->getNotes());
                   14277:         $pf->addPhpDep($deps['required']['php']['min'], 'ge');
                   14278:         if (isset($deps['required']['php']['max'])) {
                   14279:             $pf->addPhpDep($deps['required']['php']['max'], 'le');
                   14280:         }
                   14281: 
                   14282:         if (isset($deps['required']['package'])) {
                   14283:             if (!isset($deps['required']['package'][0])) {
                   14284:                 $deps['required']['package'] = array($deps['required']['package']);
                   14285:             }
                   14286: 
                   14287:             foreach ($deps['required']['package'] as $dep) {
                   14288:                 if (!isset($dep['channel'])) {
                   14289:                     return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
                   14290:                     ' contains uri-based dependency on a package.  Using a ' .
                   14291:                     'PEAR_PackageFileManager-based script is an option');
                   14292:                 }
                   14293: 
                   14294:                 if ($dep['channel'] != 'pear.php.net'
                   14295:                     && $dep['channel'] != 'pecl.php.net'
                   14296:                     && $dep['channel'] != 'doc.php.net') {
                   14297:                     return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
                   14298:                     ' contains dependency on a non-standard channel package.  Using a ' .
                   14299:                     'PEAR_PackageFileManager-based script is an option');
                   14300:                 }
                   14301: 
                   14302:                 if (isset($dep['conflicts'])) {
                   14303:                     return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
                   14304:                     ' contains conflicts dependency.  Using a ' .
                   14305:                     'PEAR_PackageFileManager-based script is an option');
                   14306:                 }
                   14307: 
                   14308:                 if (isset($dep['exclude'])) {
                   14309:                     $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
                   14310:                 }
                   14311: 
                   14312:                 if (isset($dep['min'])) {
                   14313:                     $pf->addPackageDep($dep['name'], $dep['min'], 'ge');
                   14314:                 }
                   14315: 
                   14316:                 if (isset($dep['max'])) {
                   14317:                     $pf->addPackageDep($dep['name'], $dep['max'], 'le');
                   14318:                 }
                   14319:             }
                   14320:         }
                   14321: 
                   14322:         if (isset($deps['required']['extension'])) {
                   14323:             if (!isset($deps['required']['extension'][0])) {
                   14324:                 $deps['required']['extension'] = array($deps['required']['extension']);
                   14325:             }
                   14326: 
                   14327:             foreach ($deps['required']['extension'] as $dep) {
                   14328:                 if (isset($dep['conflicts'])) {
                   14329:                     return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
                   14330:                     ' contains conflicts dependency.  Using a ' .
                   14331:                     'PEAR_PackageFileManager-based script is an option');
                   14332:                 }
                   14333: 
                   14334:                 if (isset($dep['exclude'])) {
                   14335:                     $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
                   14336:                 }
                   14337: 
                   14338:                 if (isset($dep['min'])) {
                   14339:                     $pf->addExtensionDep($dep['name'], $dep['min'], 'ge');
                   14340:                 }
                   14341: 
                   14342:                 if (isset($dep['max'])) {
                   14343:                     $pf->addExtensionDep($dep['name'], $dep['max'], 'le');
                   14344:                 }
                   14345:             }
                   14346:         }
                   14347: 
                   14348:         if (isset($deps['optional']['package'])) {
                   14349:             if (!isset($deps['optional']['package'][0])) {
                   14350:                 $deps['optional']['package'] = array($deps['optional']['package']);
                   14351:             }
                   14352: 
                   14353:             foreach ($deps['optional']['package'] as $dep) {
                   14354:                 if (!isset($dep['channel'])) {
                   14355:                     return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
                   14356:                     ' contains uri-based dependency on a package.  Using a ' .
                   14357:                     'PEAR_PackageFileManager-based script is an option');
                   14358:                 }
                   14359: 
                   14360:                 if ($dep['channel'] != 'pear.php.net'
                   14361:                     && $dep['channel'] != 'pecl.php.net'
                   14362:                     && $dep['channel'] != 'doc.php.net') {
                   14363:                     return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
                   14364:                     ' contains dependency on a non-standard channel package.  Using a ' .
                   14365:                     'PEAR_PackageFileManager-based script is an option');
                   14366:                 }
                   14367: 
                   14368:                 if (isset($dep['exclude'])) {
                   14369:                     $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
                   14370:                 }
                   14371: 
                   14372:                 if (isset($dep['min'])) {
                   14373:                     $pf->addPackageDep($dep['name'], $dep['min'], 'ge', 'yes');
                   14374:                 }
                   14375: 
                   14376:                 if (isset($dep['max'])) {
                   14377:                     $pf->addPackageDep($dep['name'], $dep['max'], 'le', 'yes');
                   14378:                 }
                   14379:             }
                   14380:         }
                   14381: 
                   14382:         if (isset($deps['optional']['extension'])) {
                   14383:             if (!isset($deps['optional']['extension'][0])) {
                   14384:                 $deps['optional']['extension'] = array($deps['optional']['extension']);
                   14385:             }
                   14386: 
                   14387:             foreach ($deps['optional']['extension'] as $dep) {
                   14388:                 if (isset($dep['exclude'])) {
                   14389:                     $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
                   14390:                 }
                   14391: 
                   14392:                 if (isset($dep['min'])) {
                   14393:                     $pf->addExtensionDep($dep['name'], $dep['min'], 'ge', 'yes');
                   14394:                 }
                   14395: 
                   14396:                 if (isset($dep['max'])) {
                   14397:                     $pf->addExtensionDep($dep['name'], $dep['max'], 'le', 'yes');
                   14398:                 }
                   14399:             }
                   14400:         }
                   14401: 
                   14402:         $contents = $pf2->getContents();
                   14403:         $release  = $pf2->getReleases();
                   14404:         if (isset($releases[0])) {
                   14405:             return $this->raiseError('Cannot safely process "' . $packagexml . '" contains '
                   14406:             . 'multiple extsrcrelease/zendextsrcrelease tags.  Using a PEAR_PackageFileManager-based script ' .
                   14407:             'or the convert command is an option');
                   14408:         }
                   14409: 
                   14410:         if ($configoptions = $pf2->getConfigureOptions()) {
                   14411:             foreach ($configoptions as $option) {
                   14412:                 $default = isset($option['default']) ? $option['default'] : false;
                   14413:                 $pf->addConfigureOption($option['name'], $option['prompt'], $default);
                   14414:             }
                   14415:         }
                   14416: 
                   14417:         if (isset($release['filelist']['ignore'])) {
                   14418:             return $this->raiseError('Cannot safely process "' . $packagexml . '" contains '
                   14419:             . 'ignore tags.  Using a PEAR_PackageFileManager-based script or the convert' .
                   14420:             ' command is an option');
                   14421:         }
                   14422: 
                   14423:         if (isset($release['filelist']['install']) &&
                   14424:               !isset($release['filelist']['install'][0])) {
                   14425:             $release['filelist']['install'] = array($release['filelist']['install']);
                   14426:         }
                   14427: 
                   14428:         if (isset($contents['dir']['attribs']['baseinstalldir'])) {
                   14429:             $baseinstalldir = $contents['dir']['attribs']['baseinstalldir'];
                   14430:         } else {
                   14431:             $baseinstalldir = false;
                   14432:         }
                   14433: 
                   14434:         if (!isset($contents['dir']['file'][0])) {
                   14435:             $contents['dir']['file'] = array($contents['dir']['file']);
                   14436:         }
                   14437: 
                   14438:         foreach ($contents['dir']['file'] as $file) {
                   14439:             if ($baseinstalldir && !isset($file['attribs']['baseinstalldir'])) {
                   14440:                 $file['attribs']['baseinstalldir'] = $baseinstalldir;
                   14441:             }
                   14442: 
                   14443:             $processFile = $file;
                   14444:             unset($processFile['attribs']);
                   14445:             if (count($processFile)) {
                   14446:                 foreach ($processFile as $name => $task) {
                   14447:                     if ($name != $pf2->getTasksNs() . ':replace') {
                   14448:                         return $this->raiseError('Cannot safely process "' . $packagexml .
                   14449:                         '" contains tasks other than replace.  Using a ' .
                   14450:                         'PEAR_PackageFileManager-based script is an option.');
                   14451:                     }
                   14452:                     $file['attribs']['replace'][] = $task;
                   14453:                 }
                   14454:             }
                   14455: 
                   14456:             if (!in_array($file['attribs']['role'], PEAR_Common::getFileRoles())) {
                   14457:                 return $this->raiseError('Cannot safely convert "' . $packagexml .
                   14458:                 '", contains custom roles.  Using a PEAR_PackageFileManager-based script ' .
                   14459:                 'or the convert command is an option');
                   14460:             }
                   14461: 
                   14462:             if (isset($release['filelist']['install'])) {
                   14463:                 foreach ($release['filelist']['install'] as $installas) {
                   14464:                     if ($installas['attribs']['name'] == $file['attribs']['name']) {
                   14465:                         $file['attribs']['install-as'] = $installas['attribs']['as'];
                   14466:                     }
                   14467:                 }
                   14468:             }
                   14469: 
                   14470:             $pf->addFile('/', $file['attribs']['name'], $file['attribs']);
                   14471:         }
                   14472: 
                   14473:         if ($pf2->getChangeLog()) {
                   14474:             $this->ui->outputData('WARNING: changelog is not translated to package.xml ' .
                   14475:                 '1.0, use PEAR_PackageFileManager-based script if you need changelog-' .
                   14476:                 'translation for package.xml 1.0');
                   14477:         }
                   14478: 
                   14479:         $gen = &$pf->getDefaultGenerator();
                   14480:         $gen->toPackageFile('.');
                   14481:     }
1.1.1.2 ! misho    14482: }PEAR-1.9.4/PEAR/Command/Registry.xml0000644000076500000240000000337611605156614015704 0ustar  helgistaff<commands version="1.0">
1.1       misho    14483:  <list>
                   14484:   <summary>List Installed Packages In The Default Channel</summary>
                   14485:   <function>doList</function>
                   14486:   <shortcut>l</shortcut>
                   14487:   <options>
                   14488:    <channel>
                   14489:     <shortopt>c</shortopt>
                   14490:     <doc>list installed packages from this channel</doc>
                   14491:     <arg>CHAN</arg>
                   14492:    </channel>
                   14493:    <allchannels>
                   14494:     <shortopt>a</shortopt>
                   14495:     <doc>list installed packages from all channels</doc>
                   14496:    </allchannels>
                   14497:    <channelinfo>
                   14498:     <shortopt>i</shortopt>
                   14499:     <doc>output fully channel-aware data, even on failure</doc>
                   14500:    </channelinfo>
                   14501:   </options>
                   14502:   <doc>&lt;package&gt;
                   14503: If invoked without parameters, this command lists the PEAR packages
                   14504: installed in your php_dir ({config php_dir}).  With a parameter, it
                   14505: lists the files in a package.
                   14506: </doc>
                   14507:  </list>
                   14508:  <list-files>
                   14509:   <summary>List Files In Installed Package</summary>
                   14510:   <function>doFileList</function>
                   14511:   <shortcut>fl</shortcut>
                   14512:   <options />
                   14513:   <doc>&lt;package&gt;
                   14514: List the files in an installed package.
                   14515: </doc>
                   14516:  </list-files>
                   14517:  <shell-test>
                   14518:   <summary>Shell Script Test</summary>
                   14519:   <function>doShellTest</function>
                   14520:   <shortcut>st</shortcut>
                   14521:   <options />
                   14522:   <doc>&lt;package&gt; [[relation] version]
                   14523: Tests if a package is installed in the system. Will exit(1) if it is not.
                   14524:    &lt;relation&gt;   The version comparison operator. One of:
                   14525:                 &lt;, lt, &lt;=, le, &gt;, gt, &gt;=, ge, ==, =, eq, !=, &lt;&gt;, ne
                   14526:    &lt;version&gt;    The version to compare with
                   14527: </doc>
                   14528:  </shell-test>
                   14529:  <info>
                   14530:   <summary>Display information about a package</summary>
                   14531:   <function>doInfo</function>
                   14532:   <shortcut>in</shortcut>
                   14533:   <options />
                   14534:   <doc>&lt;package&gt;
                   14535: Displays information about a package. The package argument may be a
                   14536: local package file, an URL to a package file, or the name of an
                   14537: installed package.</doc>
                   14538:  </info>
1.1.1.2 ! misho    14539: </commands>PEAR-1.9.4/PEAR/Command/Registry.php0000644000076500000240000013241611605156614015671 0ustar  helgistaff<?php
1.1       misho    14540: /**
                   14541:  * PEAR_Command_Registry (list, list-files, shell-test, info commands)
                   14542:  *
                   14543:  * PHP versions 4 and 5
                   14544:  *
                   14545:  * @category   pear
                   14546:  * @package    PEAR
                   14547:  * @author     Stig Bakken <ssb@php.net>
                   14548:  * @author     Greg Beaver <cellog@php.net>
                   14549:  * @copyright  1997-2009 The Authors
                   14550:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   14551:  * @version    CVS: $Id: Registry.php 313023 2011-07-06 19:17:11Z dufuz $
                   14552:  * @link       http://pear.php.net/package/PEAR
                   14553:  * @since      File available since Release 0.1
                   14554:  */
                   14555: 
                   14556: /**
                   14557:  * base class
                   14558:  */
                   14559: require_once 'PEAR/Command/Common.php';
                   14560: 
                   14561: /**
                   14562:  * PEAR commands for registry manipulation
                   14563:  *
                   14564:  * @category   pear
                   14565:  * @package    PEAR
                   14566:  * @author     Stig Bakken <ssb@php.net>
                   14567:  * @author     Greg Beaver <cellog@php.net>
                   14568:  * @copyright  1997-2009 The Authors
                   14569:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   14570:  * @version    Release: 1.9.4
                   14571:  * @link       http://pear.php.net/package/PEAR
                   14572:  * @since      Class available since Release 0.1
                   14573:  */
                   14574: class PEAR_Command_Registry extends PEAR_Command_Common
                   14575: {
                   14576:     var $commands = array(
                   14577:         'list' => array(
                   14578:             'summary' => 'List Installed Packages In The Default Channel',
                   14579:             'function' => 'doList',
                   14580:             'shortcut' => 'l',
                   14581:             'options' => array(
                   14582:                 'channel' => array(
                   14583:                     'shortopt' => 'c',
                   14584:                     'doc' => 'list installed packages from this channel',
                   14585:                     'arg' => 'CHAN',
                   14586:                     ),
                   14587:                 'allchannels' => array(
                   14588:                     'shortopt' => 'a',
                   14589:                     'doc' => 'list installed packages from all channels',
                   14590:                     ),
                   14591:                 'channelinfo' => array(
                   14592:                     'shortopt' => 'i',
                   14593:                     'doc' => 'output fully channel-aware data, even on failure',
                   14594:                     ),
                   14595:                 ),
                   14596:             'doc' => '<package>
                   14597: If invoked without parameters, this command lists the PEAR packages
                   14598: installed in your php_dir ({config php_dir}).  With a parameter, it
                   14599: lists the files in a package.
                   14600: ',
                   14601:             ),
                   14602:         'list-files' => array(
                   14603:             'summary' => 'List Files In Installed Package',
                   14604:             'function' => 'doFileList',
                   14605:             'shortcut' => 'fl',
                   14606:             'options' => array(),
                   14607:             'doc' => '<package>
                   14608: List the files in an installed package.
                   14609: '
                   14610:             ),
                   14611:         'shell-test' => array(
                   14612:             'summary' => 'Shell Script Test',
                   14613:             'function' => 'doShellTest',
                   14614:             'shortcut' => 'st',
                   14615:             'options' => array(),
                   14616:             'doc' => '<package> [[relation] version]
                   14617: Tests if a package is installed in the system. Will exit(1) if it is not.
                   14618:    <relation>   The version comparison operator. One of:
                   14619:                 <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne
                   14620:    <version>    The version to compare with
                   14621: '),
                   14622:         'info' => array(
                   14623:             'summary'  => 'Display information about a package',
                   14624:             'function' => 'doInfo',
                   14625:             'shortcut' => 'in',
                   14626:             'options'  => array(),
                   14627:             'doc'      => '<package>
                   14628: Displays information about a package. The package argument may be a
                   14629: local package file, an URL to a package file, or the name of an
                   14630: installed package.'
                   14631:             )
                   14632:         );
                   14633: 
                   14634:     /**
                   14635:      * PEAR_Command_Registry constructor.
                   14636:      *
                   14637:      * @access public
                   14638:      */
                   14639:     function PEAR_Command_Registry(&$ui, &$config)
                   14640:     {
                   14641:         parent::PEAR_Command_Common($ui, $config);
                   14642:     }
                   14643: 
                   14644:     function _sortinfo($a, $b)
                   14645:     {
                   14646:         $apackage = isset($a['package']) ? $a['package'] : $a['name'];
                   14647:         $bpackage = isset($b['package']) ? $b['package'] : $b['name'];
                   14648:         return strcmp($apackage, $bpackage);
                   14649:     }
                   14650: 
                   14651:     function doList($command, $options, $params)
                   14652:     {
                   14653:         $reg = &$this->config->getRegistry();
                   14654:         $channelinfo = isset($options['channelinfo']);
                   14655:         if (isset($options['allchannels']) && !$channelinfo) {
                   14656:             return $this->doListAll($command, array(), $params);
                   14657:         }
                   14658: 
                   14659:         if (isset($options['allchannels']) && $channelinfo) {
                   14660:             // allchannels with $channelinfo
                   14661:             unset($options['allchannels']);
                   14662:             $channels = $reg->getChannels();
                   14663:             $errors = array();
                   14664:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   14665:             foreach ($channels as $channel) {
                   14666:                 $options['channel'] = $channel->getName();
                   14667:                 $ret = $this->doList($command, $options, $params);
                   14668: 
                   14669:                 if (PEAR::isError($ret)) {
                   14670:                     $errors[] = $ret;
                   14671:                 }
                   14672:             }
                   14673: 
                   14674:             PEAR::staticPopErrorHandling();
                   14675:             if (count($errors)) {
                   14676:                 // for now, only give first error
                   14677:                 return PEAR::raiseError($errors[0]);
                   14678:             }
                   14679: 
                   14680:             return true;
                   14681:         }
                   14682: 
                   14683:         if (count($params) === 1) {
                   14684:             return $this->doFileList($command, $options, $params);
                   14685:         }
                   14686: 
                   14687:         if (isset($options['channel'])) {
                   14688:             if (!$reg->channelExists($options['channel'])) {
                   14689:                 return $this->raiseError('Channel "' . $options['channel'] .'" does not exist');
                   14690:             }
                   14691: 
                   14692:             $channel = $reg->channelName($options['channel']);
                   14693:         } else {
                   14694:             $channel = $this->config->get('default_channel');
                   14695:         }
                   14696: 
                   14697:         $installed = $reg->packageInfo(null, null, $channel);
                   14698:         usort($installed, array(&$this, '_sortinfo'));
                   14699: 
                   14700:         $data = array(
                   14701:             'caption' => 'Installed packages, channel ' .
                   14702:                 $channel . ':',
                   14703:             'border' => true,
                   14704:             'headline' => array('Package', 'Version', 'State'),
                   14705:             'channel' => $channel,
                   14706:             );
                   14707:         if ($channelinfo) {
                   14708:             $data['headline'] = array('Channel', 'Package', 'Version', 'State');
                   14709:         }
                   14710: 
                   14711:         if (count($installed) && !isset($data['data'])) {
                   14712:             $data['data'] = array();
                   14713:         }
                   14714: 
                   14715:         foreach ($installed as $package) {
                   14716:             $pobj = $reg->getPackage(isset($package['package']) ?
                   14717:                                         $package['package'] : $package['name'], $channel);
                   14718:             if ($channelinfo) {
                   14719:                 $packageinfo = array($pobj->getChannel(), $pobj->getPackage(), $pobj->getVersion(),
                   14720:                                     $pobj->getState() ? $pobj->getState() : null);
                   14721:             } else {
                   14722:                 $packageinfo = array($pobj->getPackage(), $pobj->getVersion(),
                   14723:                                     $pobj->getState() ? $pobj->getState() : null);
                   14724:             }
                   14725:             $data['data'][] = $packageinfo;
                   14726:         }
                   14727: 
                   14728:         if (count($installed) === 0) {
                   14729:             if (!$channelinfo) {
                   14730:                 $data = '(no packages installed from channel ' . $channel . ')';
                   14731:             } else {
                   14732:                 $data = array(
                   14733:                     'caption' => 'Installed packages, channel ' .
                   14734:                         $channel . ':',
                   14735:                     'border' => true,
                   14736:                     'channel' => $channel,
                   14737:                     'data' => array(array('(no packages installed)')),
                   14738:                 );
                   14739:             }
                   14740:         }
                   14741: 
                   14742:         $this->ui->outputData($data, $command);
                   14743:         return true;
                   14744:     }
                   14745: 
                   14746:     function doListAll($command, $options, $params)
                   14747:     {
                   14748:         // This duplicate code is deprecated over
                   14749:         // list --channelinfo, which gives identical
                   14750:         // output for list and list --allchannels.
                   14751:         $reg = &$this->config->getRegistry();
                   14752:         $installed = $reg->packageInfo(null, null, null);
                   14753:         foreach ($installed as $channel => $packages) {
                   14754:             usort($packages, array($this, '_sortinfo'));
                   14755:             $data = array(
                   14756:                 'caption'  => 'Installed packages, channel ' . $channel . ':',
                   14757:                 'border'   => true,
                   14758:                 'headline' => array('Package', 'Version', 'State'),
                   14759:                 'channel'  => $channel
                   14760:             );
                   14761: 
                   14762:             foreach ($packages as $package) {
                   14763:                 $p = isset($package['package']) ? $package['package'] : $package['name'];
                   14764:                 $pobj = $reg->getPackage($p, $channel);
                   14765:                 $data['data'][] = array($pobj->getPackage(), $pobj->getVersion(),
                   14766:                                         $pobj->getState() ? $pobj->getState() : null);
                   14767:             }
                   14768: 
                   14769:             // Adds a blank line after each section
                   14770:             $data['data'][] = array();
                   14771: 
                   14772:             if (count($packages) === 0) {
                   14773:                 $data = array(
                   14774:                     'caption' => 'Installed packages, channel ' . $channel . ':',
                   14775:                     'border' => true,
                   14776:                     'data' => array(array('(no packages installed)'), array()),
                   14777:                     'channel' => $channel
                   14778:                     );
                   14779:             }
                   14780:             $this->ui->outputData($data, $command);
                   14781:         }
                   14782:         return true;
                   14783:     }
                   14784: 
                   14785:     function doFileList($command, $options, $params)
                   14786:     {
                   14787:         if (count($params) !== 1) {
                   14788:             return $this->raiseError('list-files expects 1 parameter');
                   14789:         }
                   14790: 
                   14791:         $reg = &$this->config->getRegistry();
                   14792:         $fp = false;
                   14793:         if (!is_dir($params[0]) && (file_exists($params[0]) || $fp = @fopen($params[0], 'r'))) {
                   14794:             if ($fp) {
                   14795:                 fclose($fp);
                   14796:             }
                   14797: 
                   14798:             if (!class_exists('PEAR_PackageFile')) {
                   14799:                 require_once 'PEAR/PackageFile.php';
                   14800:             }
                   14801: 
                   14802:             $pkg = &new PEAR_PackageFile($this->config, $this->_debug);
                   14803:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   14804:             $info = &$pkg->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
                   14805:             PEAR::staticPopErrorHandling();
                   14806:             $headings = array('Package File', 'Install Path');
                   14807:             $installed = false;
                   14808:         } else {
                   14809:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   14810:             $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
                   14811:             PEAR::staticPopErrorHandling();
                   14812:             if (PEAR::isError($parsed)) {
                   14813:                 return $this->raiseError($parsed);
                   14814:             }
                   14815: 
                   14816:             $info = &$reg->getPackage($parsed['package'], $parsed['channel']);
                   14817:             $headings = array('Type', 'Install Path');
                   14818:             $installed = true;
                   14819:         }
                   14820: 
                   14821:         if (PEAR::isError($info)) {
                   14822:             return $this->raiseError($info);
                   14823:         }
                   14824: 
                   14825:         if ($info === null) {
                   14826:             return $this->raiseError("`$params[0]' not installed");
                   14827:         }
                   14828: 
                   14829:         $list = ($info->getPackagexmlVersion() == '1.0' || $installed) ?
                   14830:             $info->getFilelist() : $info->getContents();
                   14831:         if ($installed) {
                   14832:             $caption = 'Installed Files For ' . $params[0];
                   14833:         } else {
                   14834:             $caption = 'Contents of ' . basename($params[0]);
                   14835:         }
                   14836: 
                   14837:         $data = array(
                   14838:             'caption' => $caption,
                   14839:             'border' => true,
                   14840:             'headline' => $headings);
                   14841:         if ($info->getPackagexmlVersion() == '1.0' || $installed) {
                   14842:             foreach ($list as $file => $att) {
                   14843:                 if ($installed) {
                   14844:                     if (empty($att['installed_as'])) {
                   14845:                         continue;
                   14846:                     }
                   14847:                     $data['data'][] = array($att['role'], $att['installed_as']);
                   14848:                 } else {
                   14849:                     if (isset($att['baseinstalldir']) && !in_array($att['role'],
                   14850:                           array('test', 'data', 'doc'))) {
                   14851:                         $dest = $att['baseinstalldir'] . DIRECTORY_SEPARATOR .
                   14852:                             $file;
                   14853:                     } else {
                   14854:                         $dest = $file;
                   14855:                     }
                   14856:                     switch ($att['role']) {
                   14857:                         case 'test':
                   14858:                         case 'data':
                   14859:                         case 'doc':
                   14860:                             $role = $att['role'];
                   14861:                             if ($role == 'test') {
                   14862:                                 $role .= 's';
                   14863:                             }
                   14864:                             $dest = $this->config->get($role . '_dir') . DIRECTORY_SEPARATOR .
                   14865:                                 $info->getPackage() . DIRECTORY_SEPARATOR . $dest;
                   14866:                             break;
                   14867:                         case 'php':
                   14868:                         default:
                   14869:                             $dest = $this->config->get('php_dir') . DIRECTORY_SEPARATOR .
                   14870:                                 $dest;
                   14871:                     }
                   14872:                     $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
                   14873:                     $dest = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"),
                   14874:                                                     array(DIRECTORY_SEPARATOR,
                   14875:                                                           DIRECTORY_SEPARATOR,
                   14876:                                                           DIRECTORY_SEPARATOR),
                   14877:                                                     $dest);
                   14878:                     $file = preg_replace('!/+!', '/', $file);
                   14879:                     $data['data'][] = array($file, $dest);
                   14880:                 }
                   14881:             }
                   14882:         } else { // package.xml 2.0, not installed
                   14883:             if (!isset($list['dir']['file'][0])) {
                   14884:                 $list['dir']['file'] = array($list['dir']['file']);
                   14885:             }
                   14886: 
                   14887:             foreach ($list['dir']['file'] as $att) {
                   14888:                 $att = $att['attribs'];
                   14889:                 $file = $att['name'];
                   14890:                 $role = &PEAR_Installer_Role::factory($info, $att['role'], $this->config);
                   14891:                 $role->setup($this, $info, $att, $file);
                   14892:                 if (!$role->isInstallable()) {
                   14893:                     $dest = '(not installable)';
                   14894:                 } else {
                   14895:                     $dest = $role->processInstallation($info, $att, $file, '');
                   14896:                     if (PEAR::isError($dest)) {
                   14897:                         $dest = '(Unknown role "' . $att['role'] . ')';
                   14898:                     } else {
                   14899:                         list(,, $dest) = $dest;
                   14900:                     }
                   14901:                 }
                   14902:                 $data['data'][] = array($file, $dest);
                   14903:             }
                   14904:         }
                   14905: 
                   14906:         $this->ui->outputData($data, $command);
                   14907:         return true;
                   14908:     }
                   14909: 
                   14910:     function doShellTest($command, $options, $params)
                   14911:     {
                   14912:         if (count($params) < 1) {
                   14913:             return PEAR::raiseError('ERROR, usage: pear shell-test packagename [[relation] version]');
                   14914:         }
                   14915: 
                   14916:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   14917:         $reg = &$this->config->getRegistry();
                   14918:         $info = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
                   14919:         if (PEAR::isError($info)) {
                   14920:             exit(1); // invalid package name
                   14921:         }
                   14922: 
                   14923:         $package = $info['package'];
                   14924:         $channel = $info['channel'];
                   14925:         // "pear shell-test Foo"
                   14926:         if (!$reg->packageExists($package, $channel)) {
                   14927:             if ($channel == 'pecl.php.net') {
                   14928:                 if ($reg->packageExists($package, 'pear.php.net')) {
                   14929:                     $channel = 'pear.php.net'; // magically change channels for extensions
                   14930:                 }
                   14931:             }
                   14932:         }
                   14933: 
                   14934:         if (count($params) === 1) {
                   14935:             if (!$reg->packageExists($package, $channel)) {
                   14936:                 exit(1);
                   14937:             }
                   14938:             // "pear shell-test Foo 1.0"
                   14939:         } elseif (count($params) === 2) {
                   14940:             $v = $reg->packageInfo($package, 'version', $channel);
                   14941:             if (!$v || !version_compare("$v", "{$params[1]}", "ge")) {
                   14942:                 exit(1);
                   14943:             }
                   14944:             // "pear shell-test Foo ge 1.0"
                   14945:         } elseif (count($params) === 3) {
                   14946:             $v = $reg->packageInfo($package, 'version', $channel);
                   14947:             if (!$v || !version_compare("$v", "{$params[2]}", $params[1])) {
                   14948:                 exit(1);
                   14949:             }
                   14950:         } else {
                   14951:             PEAR::staticPopErrorHandling();
                   14952:             $this->raiseError("$command: expects 1 to 3 parameters");
                   14953:             exit(1);
                   14954:         }
                   14955:     }
                   14956: 
                   14957:     function doInfo($command, $options, $params)
                   14958:     {
                   14959:         if (count($params) !== 1) {
                   14960:             return $this->raiseError('pear info expects 1 parameter');
                   14961:         }
                   14962: 
                   14963:         $info = $fp = false;
                   14964:         $reg = &$this->config->getRegistry();
                   14965:         if (is_file($params[0]) && !is_dir($params[0]) &&
                   14966:             (file_exists($params[0]) || $fp = @fopen($params[0], 'r'))
                   14967:         ) {
                   14968:             if ($fp) {
                   14969:                 fclose($fp);
                   14970:             }
                   14971: 
                   14972:             if (!class_exists('PEAR_PackageFile')) {
                   14973:                 require_once 'PEAR/PackageFile.php';
                   14974:             }
                   14975: 
                   14976:             $pkg = &new PEAR_PackageFile($this->config, $this->_debug);
                   14977:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   14978:             $obj = &$pkg->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
                   14979:             PEAR::staticPopErrorHandling();
                   14980:             if (PEAR::isError($obj)) {
                   14981:                 $uinfo = $obj->getUserInfo();
                   14982:                 if (is_array($uinfo)) {
                   14983:                     foreach ($uinfo as $message) {
                   14984:                         if (is_array($message)) {
                   14985:                             $message = $message['message'];
                   14986:                         }
                   14987:                         $this->ui->outputData($message);
                   14988:                     }
                   14989:                 }
                   14990: 
                   14991:                 return $this->raiseError($obj);
                   14992:             }
                   14993: 
                   14994:             if ($obj->getPackagexmlVersion() != '1.0') {
                   14995:                 return $this->_doInfo2($command, $options, $params, $obj, false);
                   14996:             }
                   14997: 
                   14998:             $info = $obj->toArray();
                   14999:         } else {
                   15000:             $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
                   15001:             if (PEAR::isError($parsed)) {
                   15002:                 return $this->raiseError($parsed);
                   15003:             }
                   15004: 
                   15005:             $package = $parsed['package'];
                   15006:             $channel = $parsed['channel'];
                   15007:             $info = $reg->packageInfo($package, null, $channel);
                   15008:             if (isset($info['old'])) {
                   15009:                 $obj = $reg->getPackage($package, $channel);
                   15010:                 return $this->_doInfo2($command, $options, $params, $obj, true);
                   15011:             }
                   15012:         }
                   15013: 
                   15014:         if (PEAR::isError($info)) {
                   15015:             return $info;
                   15016:         }
                   15017: 
                   15018:         if (empty($info)) {
                   15019:             $this->raiseError("No information found for `$params[0]'");
                   15020:             return;
                   15021:         }
                   15022: 
                   15023:         unset($info['filelist']);
                   15024:         unset($info['dirtree']);
                   15025:         unset($info['changelog']);
                   15026:         if (isset($info['xsdversion'])) {
                   15027:             $info['package.xml version'] = $info['xsdversion'];
                   15028:             unset($info['xsdversion']);
                   15029:         }
                   15030: 
                   15031:         if (isset($info['packagerversion'])) {
                   15032:             $info['packaged with PEAR version'] = $info['packagerversion'];
                   15033:             unset($info['packagerversion']);
                   15034:         }
                   15035: 
                   15036:         $keys = array_keys($info);
                   15037:         $longtext = array('description', 'summary');
                   15038:         foreach ($keys as $key) {
                   15039:             if (is_array($info[$key])) {
                   15040:                 switch ($key) {
                   15041:                     case 'maintainers': {
                   15042:                         $i = 0;
                   15043:                         $mstr = '';
                   15044:                         foreach ($info[$key] as $m) {
                   15045:                             if ($i++ > 0) {
                   15046:                                 $mstr .= "\n";
                   15047:                             }
                   15048:                             $mstr .= $m['name'] . " <";
                   15049:                             if (isset($m['email'])) {
                   15050:                                 $mstr .= $m['email'];
                   15051:                             } else {
                   15052:                                 $mstr .= $m['handle'] . '@php.net';
                   15053:                             }
                   15054:                             $mstr .= "> ($m[role])";
                   15055:                         }
                   15056:                         $info[$key] = $mstr;
                   15057:                         break;
                   15058:                     }
                   15059:                     case 'release_deps': {
                   15060:                         $i = 0;
                   15061:                         $dstr = '';
                   15062:                         foreach ($info[$key] as $d) {
                   15063:                             if (isset($this->_deps_rel_trans[$d['rel']])) {
                   15064:                                 $rel = $this->_deps_rel_trans[$d['rel']];
                   15065:                             } else {
                   15066:                                 $rel = $d['rel'];
                   15067:                             }
                   15068:                             if (isset($this->_deps_type_trans[$d['type']])) {
                   15069:                                 $type = ucfirst($this->_deps_type_trans[$d['type']]);
                   15070:                             } else {
                   15071:                                 $type = $d['type'];
                   15072:                             }
                   15073:                             if (isset($d['name'])) {
                   15074:                                 $name = $d['name'] . ' ';
                   15075:                             } else {
                   15076:                                 $name = '';
                   15077:                             }
                   15078:                             if (isset($d['version'])) {
                   15079:                                 $version = $d['version'] . ' ';
                   15080:                             } else {
                   15081:                                 $version = '';
                   15082:                             }
                   15083:                             if (isset($d['optional']) && $d['optional'] == 'yes') {
                   15084:                                 $optional = ' (optional)';
                   15085:                             } else {
                   15086:                                 $optional = '';
                   15087:                             }
                   15088:                             $dstr .= "$type $name$rel $version$optional\n";
                   15089:                         }
                   15090:                         $info[$key] = $dstr;
                   15091:                         break;
                   15092:                     }
                   15093:                     case 'provides' : {
                   15094:                         $debug = $this->config->get('verbose');
                   15095:                         if ($debug < 2) {
                   15096:                             $pstr = 'Classes: ';
                   15097:                         } else {
                   15098:                             $pstr = '';
                   15099:                         }
                   15100:                         $i = 0;
                   15101:                         foreach ($info[$key] as $p) {
                   15102:                             if ($debug < 2 && $p['type'] != "class") {
                   15103:                                 continue;
                   15104:                             }
                   15105:                             // Only print classes when verbosity mode is < 2
                   15106:                             if ($debug < 2) {
                   15107:                                 if ($i++ > 0) {
                   15108:                                     $pstr .= ", ";
                   15109:                                 }
                   15110:                                 $pstr .= $p['name'];
                   15111:                             } else {
                   15112:                                 if ($i++ > 0) {
                   15113:                                     $pstr .= "\n";
                   15114:                                 }
                   15115:                                 $pstr .= ucfirst($p['type']) . " " . $p['name'];
                   15116:                                 if (isset($p['explicit']) && $p['explicit'] == 1) {
                   15117:                                     $pstr .= " (explicit)";
                   15118:                                 }
                   15119:                             }
                   15120:                         }
                   15121:                         $info[$key] = $pstr;
                   15122:                         break;
                   15123:                     }
                   15124:                     case 'configure_options' : {
                   15125:                         foreach ($info[$key] as $i => $p) {
                   15126:                             $info[$key][$i] = array_map(null, array_keys($p), array_values($p));
                   15127:                             $info[$key][$i] = array_map(create_function('$a',
                   15128:                                 'return join(" = ",$a);'), $info[$key][$i]);
                   15129:                             $info[$key][$i] = implode(', ', $info[$key][$i]);
                   15130:                         }
                   15131:                         $info[$key] = implode("\n", $info[$key]);
                   15132:                         break;
                   15133:                     }
                   15134:                     default: {
                   15135:                         $info[$key] = implode(", ", $info[$key]);
                   15136:                         break;
                   15137:                     }
                   15138:                 }
                   15139:             }
                   15140: 
                   15141:             if ($key == '_lastmodified') {
                   15142:                 $hdate = date('Y-m-d', $info[$key]);
                   15143:                 unset($info[$key]);
                   15144:                 $info['Last Modified'] = $hdate;
                   15145:             } elseif ($key == '_lastversion') {
                   15146:                 $info['Previous Installed Version'] = $info[$key] ? $info[$key] : '- None -';
                   15147:                 unset($info[$key]);
                   15148:             } else {
                   15149:                 $info[$key] = trim($info[$key]);
                   15150:                 if (in_array($key, $longtext)) {
                   15151:                     $info[$key] = preg_replace('/  +/', ' ', $info[$key]);
                   15152:                 }
                   15153:             }
                   15154:         }
                   15155: 
                   15156:         $caption = 'About ' . $info['package'] . '-' . $info['version'];
                   15157:         $data = array(
                   15158:             'caption' => $caption,
                   15159:             'border' => true);
                   15160:         foreach ($info as $key => $value) {
                   15161:             $key = ucwords(trim(str_replace('_', ' ', $key)));
                   15162:             $data['data'][] = array($key, $value);
                   15163:         }
                   15164:         $data['raw'] = $info;
                   15165: 
                   15166:         $this->ui->outputData($data, 'package-info');
                   15167:     }
                   15168: 
                   15169:     /**
                   15170:      * @access private
                   15171:      */
                   15172:     function _doInfo2($command, $options, $params, &$obj, $installed)
                   15173:     {
                   15174:         $reg = &$this->config->getRegistry();
                   15175:         $caption = 'About ' . $obj->getChannel() . '/' .$obj->getPackage() . '-' .
                   15176:             $obj->getVersion();
                   15177:         $data = array(
                   15178:             'caption' => $caption,
                   15179:             'border' => true);
                   15180:         switch ($obj->getPackageType()) {
                   15181:             case 'php' :
                   15182:                 $release = 'PEAR-style PHP-based Package';
                   15183:             break;
                   15184:             case 'extsrc' :
                   15185:                 $release = 'PECL-style PHP extension (source code)';
                   15186:             break;
                   15187:             case 'zendextsrc' :
                   15188:                 $release = 'PECL-style Zend extension (source code)';
                   15189:             break;
                   15190:             case 'extbin' :
                   15191:                 $release = 'PECL-style PHP extension (binary)';
                   15192:             break;
                   15193:             case 'zendextbin' :
                   15194:                 $release = 'PECL-style Zend extension (binary)';
                   15195:             break;
                   15196:             case 'bundle' :
                   15197:                 $release = 'Package bundle (collection of packages)';
                   15198:             break;
                   15199:         }
                   15200:         $extends = $obj->getExtends();
                   15201:         $extends = $extends ?
                   15202:             $obj->getPackage() . ' (extends ' . $extends . ')' : $obj->getPackage();
                   15203:         if ($src = $obj->getSourcePackage()) {
                   15204:             $extends .= ' (source package ' . $src['channel'] . '/' . $src['package'] . ')';
                   15205:         }
                   15206: 
                   15207:         $info = array(
                   15208:             'Release Type' => $release,
                   15209:             'Name' => $extends,
                   15210:             'Channel' => $obj->getChannel(),
                   15211:             'Summary' => preg_replace('/  +/', ' ', $obj->getSummary()),
                   15212:             'Description' => preg_replace('/  +/', ' ', $obj->getDescription()),
                   15213:             );
                   15214:         $info['Maintainers'] = '';
                   15215:         foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
                   15216:             $leads = $obj->{"get{$role}s"}();
                   15217:             if (!$leads) {
                   15218:                 continue;
                   15219:             }
                   15220: 
                   15221:             if (isset($leads['active'])) {
                   15222:                 $leads = array($leads);
                   15223:             }
                   15224: 
                   15225:             foreach ($leads as $lead) {
                   15226:                 if (!empty($info['Maintainers'])) {
                   15227:                     $info['Maintainers'] .= "\n";
                   15228:                 }
                   15229: 
                   15230:                 $active = $lead['active'] == 'no' ? ', inactive' : '';
                   15231:                 $info['Maintainers'] .= $lead['name'] . ' <';
                   15232:                 $info['Maintainers'] .= $lead['email'] . "> ($role$active)";
                   15233:             }
                   15234:         }
                   15235: 
                   15236:         $info['Release Date'] = $obj->getDate();
                   15237:         if ($time = $obj->getTime()) {
                   15238:             $info['Release Date'] .= ' ' . $time;
                   15239:         }
                   15240: 
                   15241:         $info['Release Version'] = $obj->getVersion() . ' (' . $obj->getState() . ')';
                   15242:         $info['API Version'] = $obj->getVersion('api') . ' (' . $obj->getState('api') . ')';
                   15243:         $info['License'] = $obj->getLicense();
                   15244:         $uri = $obj->getLicenseLocation();
                   15245:         if ($uri) {
                   15246:             if (isset($uri['uri'])) {
                   15247:                 $info['License'] .= ' (' . $uri['uri'] . ')';
                   15248:             } else {
                   15249:                 $extra = $obj->getInstalledLocation($info['filesource']);
                   15250:                 if ($extra) {
                   15251:                     $info['License'] .= ' (' . $uri['filesource'] . ')';
                   15252:                 }
                   15253:             }
                   15254:         }
                   15255: 
                   15256:         $info['Release Notes'] = $obj->getNotes();
                   15257:         if ($compat = $obj->getCompatible()) {
                   15258:             if (!isset($compat[0])) {
                   15259:                 $compat = array($compat);
                   15260:             }
                   15261: 
                   15262:             $info['Compatible with'] = '';
                   15263:             foreach ($compat as $package) {
                   15264:                 $info['Compatible with'] .= $package['channel'] . '/' . $package['name'] .
                   15265:                     "\nVersions >= " . $package['min'] . ', <= ' . $package['max'];
                   15266:                 if (isset($package['exclude'])) {
                   15267:                     if (is_array($package['exclude'])) {
                   15268:                         $package['exclude'] = implode(', ', $package['exclude']);
                   15269:                     }
                   15270: 
                   15271:                     if (!isset($info['Not Compatible with'])) {
                   15272:                         $info['Not Compatible with'] = '';
                   15273:                     } else {
                   15274:                         $info['Not Compatible with'] .= "\n";
                   15275:                     }
                   15276:                     $info['Not Compatible with'] .= $package['channel'] . '/' .
                   15277:                         $package['name'] . "\nVersions " . $package['exclude'];
                   15278:                 }
                   15279:             }
                   15280:         }
                   15281: 
                   15282:         $usesrole = $obj->getUsesrole();
                   15283:         if ($usesrole) {
                   15284:             if (!isset($usesrole[0])) {
                   15285:                 $usesrole = array($usesrole);
                   15286:             }
                   15287: 
                   15288:             foreach ($usesrole as $roledata) {
                   15289:                 if (isset($info['Uses Custom Roles'])) {
                   15290:                     $info['Uses Custom Roles'] .= "\n";
                   15291:                 } else {
                   15292:                     $info['Uses Custom Roles'] = '';
                   15293:                 }
                   15294: 
                   15295:                 if (isset($roledata['package'])) {
                   15296:                     $rolepackage = $reg->parsedPackageNameToString($roledata, true);
                   15297:                 } else {
                   15298:                     $rolepackage = $roledata['uri'];
                   15299:                 }
                   15300:                 $info['Uses Custom Roles'] .= $roledata['role'] . ' (' . $rolepackage . ')';
                   15301:             }
                   15302:         }
                   15303: 
                   15304:         $usestask = $obj->getUsestask();
                   15305:         if ($usestask) {
                   15306:             if (!isset($usestask[0])) {
                   15307:                 $usestask = array($usestask);
                   15308:             }
                   15309: 
                   15310:             foreach ($usestask as $taskdata) {
                   15311:                 if (isset($info['Uses Custom Tasks'])) {
                   15312:                     $info['Uses Custom Tasks'] .= "\n";
                   15313:                 } else {
                   15314:                     $info['Uses Custom Tasks'] = '';
                   15315:                 }
                   15316: 
                   15317:                 if (isset($taskdata['package'])) {
                   15318:                     $taskpackage = $reg->parsedPackageNameToString($taskdata, true);
                   15319:                 } else {
                   15320:                     $taskpackage = $taskdata['uri'];
                   15321:                 }
                   15322:                 $info['Uses Custom Tasks'] .= $taskdata['task'] . ' (' . $taskpackage . ')';
                   15323:             }
                   15324:         }
                   15325: 
                   15326:         $deps = $obj->getDependencies();
                   15327:         $info['Required Dependencies'] = 'PHP version ' . $deps['required']['php']['min'];
                   15328:         if (isset($deps['required']['php']['max'])) {
                   15329:             $info['Required Dependencies'] .= '-' . $deps['required']['php']['max'] . "\n";
                   15330:         } else {
                   15331:             $info['Required Dependencies'] .= "\n";
                   15332:         }
                   15333: 
                   15334:         if (isset($deps['required']['php']['exclude'])) {
                   15335:             if (!isset($info['Not Compatible with'])) {
                   15336:                 $info['Not Compatible with'] = '';
                   15337:             } else {
                   15338:                 $info['Not Compatible with'] .= "\n";
                   15339:             }
                   15340: 
                   15341:             if (is_array($deps['required']['php']['exclude'])) {
                   15342:                 $deps['required']['php']['exclude'] =
                   15343:                     implode(', ', $deps['required']['php']['exclude']);
                   15344:             }
                   15345:             $info['Not Compatible with'] .= "PHP versions\n  " .
                   15346:                 $deps['required']['php']['exclude'];
                   15347:         }
                   15348: 
                   15349:         $info['Required Dependencies'] .= 'PEAR installer version';
                   15350:         if (isset($deps['required']['pearinstaller']['max'])) {
                   15351:             $info['Required Dependencies'] .= 's ' .
                   15352:                 $deps['required']['pearinstaller']['min'] . '-' .
                   15353:                 $deps['required']['pearinstaller']['max'];
                   15354:         } else {
                   15355:             $info['Required Dependencies'] .= ' ' .
                   15356:                 $deps['required']['pearinstaller']['min'] . ' or newer';
                   15357:         }
                   15358: 
                   15359:         if (isset($deps['required']['pearinstaller']['exclude'])) {
                   15360:             if (!isset($info['Not Compatible with'])) {
                   15361:                 $info['Not Compatible with'] = '';
                   15362:             } else {
                   15363:                 $info['Not Compatible with'] .= "\n";
                   15364:             }
                   15365: 
                   15366:             if (is_array($deps['required']['pearinstaller']['exclude'])) {
                   15367:                 $deps['required']['pearinstaller']['exclude'] =
                   15368:                     implode(', ', $deps['required']['pearinstaller']['exclude']);
                   15369:             }
                   15370:             $info['Not Compatible with'] .= "PEAR installer\n  Versions " .
                   15371:                 $deps['required']['pearinstaller']['exclude'];
                   15372:         }
                   15373: 
                   15374:         foreach (array('Package', 'Extension') as $type) {
                   15375:             $index = strtolower($type);
                   15376:             if (isset($deps['required'][$index])) {
                   15377:                 if (isset($deps['required'][$index]['name'])) {
                   15378:                     $deps['required'][$index] = array($deps['required'][$index]);
                   15379:                 }
                   15380: 
                   15381:                 foreach ($deps['required'][$index] as $package) {
                   15382:                     if (isset($package['conflicts'])) {
                   15383:                         $infoindex = 'Not Compatible with';
                   15384:                         if (!isset($info['Not Compatible with'])) {
                   15385:                             $info['Not Compatible with'] = '';
                   15386:                         } else {
                   15387:                             $info['Not Compatible with'] .= "\n";
                   15388:                         }
                   15389:                     } else {
                   15390:                         $infoindex = 'Required Dependencies';
                   15391:                         $info[$infoindex] .= "\n";
                   15392:                     }
                   15393: 
                   15394:                     if ($index == 'extension') {
                   15395:                         $name = $package['name'];
                   15396:                     } else {
                   15397:                         if (isset($package['channel'])) {
                   15398:                             $name = $package['channel'] . '/' . $package['name'];
                   15399:                         } else {
                   15400:                             $name = '__uri/' . $package['name'] . ' (static URI)';
                   15401:                         }
                   15402:                     }
                   15403: 
                   15404:                     $info[$infoindex] .= "$type $name";
                   15405:                     if (isset($package['uri'])) {
                   15406:                         $info[$infoindex] .= "\n  Download URI: $package[uri]";
                   15407:                         continue;
                   15408:                     }
                   15409: 
                   15410:                     if (isset($package['max']) && isset($package['min'])) {
                   15411:                         $info[$infoindex] .= " \n  Versions " .
                   15412:                             $package['min'] . '-' . $package['max'];
                   15413:                     } elseif (isset($package['min'])) {
                   15414:                         $info[$infoindex] .= " \n  Version " .
                   15415:                             $package['min'] . ' or newer';
                   15416:                     } elseif (isset($package['max'])) {
                   15417:                         $info[$infoindex] .= " \n  Version " .
                   15418:                             $package['max'] . ' or older';
                   15419:                     }
                   15420: 
                   15421:                     if (isset($package['recommended'])) {
                   15422:                         $info[$infoindex] .= "\n  Recommended version: $package[recommended]";
                   15423:                     }
                   15424: 
                   15425:                     if (isset($package['exclude'])) {
                   15426:                         if (!isset($info['Not Compatible with'])) {
                   15427:                             $info['Not Compatible with'] = '';
                   15428:                         } else {
                   15429:                             $info['Not Compatible with'] .= "\n";
                   15430:                         }
                   15431: 
                   15432:                         if (is_array($package['exclude'])) {
                   15433:                             $package['exclude'] = implode(', ', $package['exclude']);
                   15434:                         }
                   15435: 
                   15436:                         $package['package'] = $package['name']; // for parsedPackageNameToString
                   15437:                          if (isset($package['conflicts'])) {
                   15438:                             $info['Not Compatible with'] .= '=> except ';
                   15439:                         }
                   15440:                        $info['Not Compatible with'] .= 'Package ' .
                   15441:                             $reg->parsedPackageNameToString($package, true);
                   15442:                         $info['Not Compatible with'] .= "\n  Versions " . $package['exclude'];
                   15443:                     }
                   15444:                 }
                   15445:             }
                   15446:         }
                   15447: 
                   15448:         if (isset($deps['required']['os'])) {
                   15449:             if (isset($deps['required']['os']['name'])) {
                   15450:                 $dep['required']['os']['name'] = array($dep['required']['os']['name']);
                   15451:             }
                   15452: 
                   15453:             foreach ($dep['required']['os'] as $os) {
                   15454:                 if (isset($os['conflicts']) && $os['conflicts'] == 'yes') {
                   15455:                     if (!isset($info['Not Compatible with'])) {
                   15456:                         $info['Not Compatible with'] = '';
                   15457:                     } else {
                   15458:                         $info['Not Compatible with'] .= "\n";
                   15459:                     }
                   15460:                     $info['Not Compatible with'] .= "$os[name] Operating System";
                   15461:                 } else {
                   15462:                     $info['Required Dependencies'] .= "\n";
                   15463:                     $info['Required Dependencies'] .= "$os[name] Operating System";
                   15464:                 }
                   15465:             }
                   15466:         }
                   15467: 
                   15468:         if (isset($deps['required']['arch'])) {
                   15469:             if (isset($deps['required']['arch']['pattern'])) {
                   15470:                 $dep['required']['arch']['pattern'] = array($dep['required']['os']['pattern']);
                   15471:             }
                   15472: 
                   15473:             foreach ($dep['required']['arch'] as $os) {
                   15474:                 if (isset($os['conflicts']) && $os['conflicts'] == 'yes') {
                   15475:                     if (!isset($info['Not Compatible with'])) {
                   15476:                         $info['Not Compatible with'] = '';
                   15477:                     } else {
                   15478:                         $info['Not Compatible with'] .= "\n";
                   15479:                     }
                   15480:                     $info['Not Compatible with'] .= "OS/Arch matching pattern '/$os[pattern]/'";
                   15481:                 } else {
                   15482:                     $info['Required Dependencies'] .= "\n";
                   15483:                     $info['Required Dependencies'] .= "OS/Arch matching pattern '/$os[pattern]/'";
                   15484:                 }
                   15485:             }
                   15486:         }
                   15487: 
                   15488:         if (isset($deps['optional'])) {
                   15489:             foreach (array('Package', 'Extension') as $type) {
                   15490:                 $index = strtolower($type);
                   15491:                 if (isset($deps['optional'][$index])) {
                   15492:                     if (isset($deps['optional'][$index]['name'])) {
                   15493:                         $deps['optional'][$index] = array($deps['optional'][$index]);
                   15494:                     }
                   15495: 
                   15496:                     foreach ($deps['optional'][$index] as $package) {
                   15497:                         if (isset($package['conflicts']) && $package['conflicts'] == 'yes') {
                   15498:                             $infoindex = 'Not Compatible with';
                   15499:                             if (!isset($info['Not Compatible with'])) {
                   15500:                                 $info['Not Compatible with'] = '';
                   15501:                             } else {
                   15502:                                 $info['Not Compatible with'] .= "\n";
                   15503:                             }
                   15504:                         } else {
                   15505:                             $infoindex = 'Optional Dependencies';
                   15506:                             if (!isset($info['Optional Dependencies'])) {
                   15507:                                 $info['Optional Dependencies'] = '';
                   15508:                             } else {
                   15509:                                 $info['Optional Dependencies'] .= "\n";
                   15510:                             }
                   15511:                         }
                   15512: 
                   15513:                         if ($index == 'extension') {
                   15514:                             $name = $package['name'];
                   15515:                         } else {
                   15516:                             if (isset($package['channel'])) {
                   15517:                                 $name = $package['channel'] . '/' . $package['name'];
                   15518:                             } else {
                   15519:                                 $name = '__uri/' . $package['name'] . ' (static URI)';
                   15520:                             }
                   15521:                         }
                   15522: 
                   15523:                         $info[$infoindex] .= "$type $name";
                   15524:                         if (isset($package['uri'])) {
                   15525:                             $info[$infoindex] .= "\n  Download URI: $package[uri]";
                   15526:                             continue;
                   15527:                         }
                   15528: 
                   15529:                         if ($infoindex == 'Not Compatible with') {
                   15530:                             // conflicts is only used to say that all versions conflict
                   15531:                             continue;
                   15532:                         }
                   15533: 
                   15534:                         if (isset($package['max']) && isset($package['min'])) {
                   15535:                             $info[$infoindex] .= " \n  Versions " .
                   15536:                                 $package['min'] . '-' . $package['max'];
                   15537:                         } elseif (isset($package['min'])) {
                   15538:                             $info[$infoindex] .= " \n  Version " .
                   15539:                                 $package['min'] . ' or newer';
                   15540:                         } elseif (isset($package['max'])) {
                   15541:                             $info[$infoindex] .= " \n  Version " .
                   15542:                                 $package['min'] . ' or older';
                   15543:                         }
                   15544: 
                   15545:                         if (isset($package['recommended'])) {
                   15546:                             $info[$infoindex] .= "\n  Recommended version: $package[recommended]";
                   15547:                         }
                   15548: 
                   15549:                         if (isset($package['exclude'])) {
                   15550:                             if (!isset($info['Not Compatible with'])) {
                   15551:                                 $info['Not Compatible with'] = '';
                   15552:                             } else {
                   15553:                                 $info['Not Compatible with'] .= "\n";
                   15554:                             }
                   15555: 
                   15556:                             if (is_array($package['exclude'])) {
                   15557:                                 $package['exclude'] = implode(', ', $package['exclude']);
                   15558:                             }
                   15559: 
                   15560:                             $info['Not Compatible with'] .= "Package $package\n  Versions " .
                   15561:                                 $package['exclude'];
                   15562:                         }
                   15563:                     }
                   15564:                 }
                   15565:             }
                   15566:         }
                   15567: 
                   15568:         if (isset($deps['group'])) {
                   15569:             if (!isset($deps['group'][0])) {
                   15570:                 $deps['group'] = array($deps['group']);
                   15571:             }
                   15572: 
                   15573:             foreach ($deps['group'] as $group) {
                   15574:                 $info['Dependency Group ' . $group['attribs']['name']] = $group['attribs']['hint'];
                   15575:                 $groupindex = $group['attribs']['name'] . ' Contents';
                   15576:                 $info[$groupindex] = '';
                   15577:                 foreach (array('Package', 'Extension') as $type) {
                   15578:                     $index = strtolower($type);
                   15579:                     if (isset($group[$index])) {
                   15580:                         if (isset($group[$index]['name'])) {
                   15581:                             $group[$index] = array($group[$index]);
                   15582:                         }
                   15583: 
                   15584:                         foreach ($group[$index] as $package) {
                   15585:                             if (!empty($info[$groupindex])) {
                   15586:                                 $info[$groupindex] .= "\n";
                   15587:                             }
                   15588: 
                   15589:                             if ($index == 'extension') {
                   15590:                                 $name = $package['name'];
                   15591:                             } else {
                   15592:                                 if (isset($package['channel'])) {
                   15593:                                     $name = $package['channel'] . '/' . $package['name'];
                   15594:                                 } else {
                   15595:                                     $name = '__uri/' . $package['name'] . ' (static URI)';
                   15596:                                 }
                   15597:                             }
                   15598: 
                   15599:                             if (isset($package['uri'])) {
                   15600:                                 if (isset($package['conflicts']) && $package['conflicts'] == 'yes') {
                   15601:                                     $info[$groupindex] .= "Not Compatible with $type $name";
                   15602:                                 } else {
                   15603:                                     $info[$groupindex] .= "$type $name";
                   15604:                                 }
                   15605: 
                   15606:                                 $info[$groupindex] .= "\n  Download URI: $package[uri]";
                   15607:                                 continue;
                   15608:                             }
                   15609: 
                   15610:                             if (isset($package['conflicts']) && $package['conflicts'] == 'yes') {
                   15611:                                 $info[$groupindex] .= "Not Compatible with $type $name";
                   15612:                                 continue;
                   15613:                             }
                   15614: 
                   15615:                             $info[$groupindex] .= "$type $name";
                   15616:                             if (isset($package['max']) && isset($package['min'])) {
                   15617:                                 $info[$groupindex] .= " \n  Versions " .
                   15618:                                     $package['min'] . '-' . $package['max'];
                   15619:                             } elseif (isset($package['min'])) {
                   15620:                                 $info[$groupindex] .= " \n  Version " .
                   15621:                                     $package['min'] . ' or newer';
                   15622:                             } elseif (isset($package['max'])) {
                   15623:                                 $info[$groupindex] .= " \n  Version " .
                   15624:                                     $package['min'] . ' or older';
                   15625:                             }
                   15626: 
                   15627:                             if (isset($package['recommended'])) {
                   15628:                                 $info[$groupindex] .= "\n  Recommended version: $package[recommended]";
                   15629:                             }
                   15630: 
                   15631:                             if (isset($package['exclude'])) {
                   15632:                                 if (!isset($info['Not Compatible with'])) {
                   15633:                                     $info['Not Compatible with'] = '';
                   15634:                                 } else {
                   15635:                                     $info[$groupindex] .= "Not Compatible with\n";
                   15636:                                 }
                   15637: 
                   15638:                                 if (is_array($package['exclude'])) {
                   15639:                                     $package['exclude'] = implode(', ', $package['exclude']);
                   15640:                                 }
                   15641:                                 $info[$groupindex] .= "  Package $package\n  Versions " .
                   15642:                                     $package['exclude'];
                   15643:                             }
                   15644:                         }
                   15645:                     }
                   15646:                 }
                   15647:             }
                   15648:         }
                   15649: 
                   15650:         if ($obj->getPackageType() == 'bundle') {
                   15651:             $info['Bundled Packages'] = '';
                   15652:             foreach ($obj->getBundledPackages() as $package) {
                   15653:                 if (!empty($info['Bundled Packages'])) {
                   15654:                     $info['Bundled Packages'] .= "\n";
                   15655:                 }
                   15656: 
                   15657:                 if (isset($package['uri'])) {
                   15658:                     $info['Bundled Packages'] .= '__uri/' . $package['name'];
                   15659:                     $info['Bundled Packages'] .= "\n  (URI: $package[uri]";
                   15660:                 } else {
                   15661:                     $info['Bundled Packages'] .= $package['channel'] . '/' . $package['name'];
                   15662:                 }
                   15663:             }
                   15664:         }
                   15665: 
                   15666:         $info['package.xml version'] = '2.0';
                   15667:         if ($installed) {
                   15668:             if ($obj->getLastModified()) {
                   15669:                 $info['Last Modified'] = date('Y-m-d H:i', $obj->getLastModified());
                   15670:             }
                   15671: 
                   15672:             $v = $obj->getLastInstalledVersion();
                   15673:             $info['Previous Installed Version'] = $v ? $v : '- None -';
                   15674:         }
                   15675: 
                   15676:         foreach ($info as $key => $value) {
                   15677:             $data['data'][] = array($key, $value);
                   15678:         }
                   15679: 
                   15680:         $data['raw'] = $obj->getArray(); // no validation needed
                   15681:         $this->ui->outputData($data, 'package-info');
                   15682:     }
1.1.1.2 ! misho    15683: }PEAR-1.9.4/PEAR/Command/Remote.xml0000644000076500000240000000635711605156614015331 0ustar  helgistaff<commands version="1.0">
1.1       misho    15684:  <remote-info>
                   15685:   <summary>Information About Remote Packages</summary>
                   15686:   <function>doRemoteInfo</function>
                   15687:   <shortcut>ri</shortcut>
                   15688:   <options />
                   15689:   <doc>&lt;package&gt;
                   15690: Get details on a package from the server.</doc>
                   15691:  </remote-info>
                   15692:  <list-upgrades>
                   15693:   <summary>List Available Upgrades</summary>
                   15694:   <function>doListUpgrades</function>
                   15695:   <shortcut>lu</shortcut>
                   15696:   <options>
                   15697:    <channelinfo>
                   15698:     <shortopt>i</shortopt>
                   15699:     <doc>output fully channel-aware data, even on failure</doc>
                   15700:    </channelinfo>
                   15701:   </options>
                   15702:   <doc>[preferred_state]
                   15703: List releases on the server of packages you have installed where
                   15704: a newer version is available with the same release state (stable etc.)
                   15705: or the state passed as the second parameter.</doc>
                   15706:  </list-upgrades>
                   15707:  <remote-list>
                   15708:   <summary>List Remote Packages</summary>
                   15709:   <function>doRemoteList</function>
                   15710:   <shortcut>rl</shortcut>
                   15711:   <options>
                   15712:    <channel>
                   15713:     <shortopt>c</shortopt>
                   15714:     <doc>specify a channel other than the default channel</doc>
                   15715:     <arg>CHAN</arg>
                   15716:    </channel>
                   15717:   </options>
                   15718:   <doc>
                   15719: Lists the packages available on the configured server along with the
                   15720: latest stable release of each package.</doc>
                   15721:  </remote-list>
                   15722:  <search>
                   15723:   <summary>Search remote package database</summary>
                   15724:   <function>doSearch</function>
                   15725:   <shortcut>sp</shortcut>
                   15726:   <options>
                   15727:    <channel>
                   15728:     <shortopt>c</shortopt>
                   15729:     <doc>specify a channel other than the default channel</doc>
                   15730:     <arg>CHAN</arg>
                   15731:    </channel>
                   15732:    <allchannels>
                   15733:     <shortopt>a</shortopt>
                   15734:     <doc>search packages from all known channels</doc>
                   15735:    </allchannels>
                   15736:    <channelinfo>
                   15737:     <shortopt>i</shortopt>
                   15738:     <doc>output fully channel-aware data, even on failure</doc>
                   15739:    </channelinfo>
                   15740:   </options>
                   15741:   <doc>[packagename] [packageinfo]
                   15742: Lists all packages which match the search parameters.  The first
                   15743: parameter is a fragment of a packagename.  The default channel
                   15744: will be used unless explicitly overridden.  The second parameter
                   15745: will be used to match any portion of the summary/description</doc>
                   15746:  </search>
                   15747:  <list-all>
                   15748:   <summary>List All Packages</summary>
                   15749:   <function>doListAll</function>
                   15750:   <shortcut>la</shortcut>
                   15751:   <options>
                   15752:    <channel>
                   15753:     <shortopt>c</shortopt>
                   15754:     <doc>specify a channel other than the default channel</doc>
                   15755:     <arg>CHAN</arg>
                   15756:    </channel>
                   15757:    <channelinfo>
                   15758:     <shortopt>i</shortopt>
                   15759:     <doc>output fully channel-aware data, even on failure</doc>
                   15760:    </channelinfo>
                   15761:   </options>
                   15762:   <doc>
                   15763: Lists the packages available on the configured server along with the
                   15764: latest stable release of each package.</doc>
                   15765:  </list-all>
                   15766:  <download>
                   15767:   <summary>Download Package</summary>
                   15768:   <function>doDownload</function>
                   15769:   <shortcut>d</shortcut>
                   15770:   <options>
                   15771:    <nocompress>
                   15772:     <shortopt>Z</shortopt>
                   15773:     <doc>download an uncompressed (.tar) file</doc>
                   15774:    </nocompress>
                   15775:   </options>
                   15776:   <doc>&lt;package&gt;...
                   15777: Download package tarballs.  The files will be named as suggested by the
                   15778: server, for example if you download the DB package and the latest stable
                   15779: version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.</doc>
                   15780:  </download>
                   15781:  <clear-cache>
                   15782:   <summary>Clear Web Services Cache</summary>
                   15783:   <function>doClearCache</function>
                   15784:   <shortcut>cc</shortcut>
                   15785:   <options />
                   15786:   <doc>
                   15787: Clear the XML-RPC/REST cache.  See also the cache_ttl configuration
                   15788: parameter.
                   15789: </doc>
                   15790:  </clear-cache>
1.1.1.2 ! misho    15791: </commands>PEAR-1.9.4/PEAR/Command/Remote.php0000644000076500000240000007256611605156614015325 0ustar  helgistaff<?php
1.1       misho    15792: /**
                   15793:  * PEAR_Command_Remote (remote-info, list-upgrades, remote-list, search, list-all, download,
                   15794:  * clear-cache commands)
                   15795:  *
                   15796:  * PHP versions 4 and 5
                   15797:  *
                   15798:  * @category   pear
                   15799:  * @package    PEAR
                   15800:  * @author     Stig Bakken <ssb@php.net>
                   15801:  * @author     Greg Beaver <cellog@php.net>
                   15802:  * @copyright  1997-2009 The Authors
                   15803:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   15804:  * @version    CVS: $Id: Remote.php 313023 2011-07-06 19:17:11Z dufuz $
                   15805:  * @link       http://pear.php.net/package/PEAR
                   15806:  * @since      File available since Release 0.1
                   15807:  */
                   15808: 
                   15809: /**
                   15810:  * base class
                   15811:  */
                   15812: require_once 'PEAR/Command/Common.php';
                   15813: require_once 'PEAR/REST.php';
                   15814: 
                   15815: /**
                   15816:  * PEAR commands for remote server querying
                   15817:  *
                   15818:  * @category   pear
                   15819:  * @package    PEAR
                   15820:  * @author     Stig Bakken <ssb@php.net>
                   15821:  * @author     Greg Beaver <cellog@php.net>
                   15822:  * @copyright  1997-2009 The Authors
                   15823:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   15824:  * @version    Release: 1.9.4
                   15825:  * @link       http://pear.php.net/package/PEAR
                   15826:  * @since      Class available since Release 0.1
                   15827:  */
                   15828: class PEAR_Command_Remote extends PEAR_Command_Common
                   15829: {
                   15830:     var $commands = array(
                   15831:         'remote-info' => array(
                   15832:             'summary' => 'Information About Remote Packages',
                   15833:             'function' => 'doRemoteInfo',
                   15834:             'shortcut' => 'ri',
                   15835:             'options' => array(),
                   15836:             'doc' => '<package>
                   15837: Get details on a package from the server.',
                   15838:             ),
                   15839:         'list-upgrades' => array(
                   15840:             'summary' => 'List Available Upgrades',
                   15841:             'function' => 'doListUpgrades',
                   15842:             'shortcut' => 'lu',
                   15843:             'options' => array(
                   15844:                 'channelinfo' => array(
                   15845:                     'shortopt' => 'i',
                   15846:                     'doc' => 'output fully channel-aware data, even on failure',
                   15847:                     ),
                   15848:             ),
                   15849:             'doc' => '[preferred_state]
                   15850: List releases on the server of packages you have installed where
                   15851: a newer version is available with the same release state (stable etc.)
                   15852: or the state passed as the second parameter.'
                   15853:             ),
                   15854:         'remote-list' => array(
                   15855:             'summary' => 'List Remote Packages',
                   15856:             'function' => 'doRemoteList',
                   15857:             'shortcut' => 'rl',
                   15858:             'options' => array(
                   15859:                 'channel' =>
                   15860:                     array(
                   15861:                     'shortopt' => 'c',
                   15862:                     'doc' => 'specify a channel other than the default channel',
                   15863:                     'arg' => 'CHAN',
                   15864:                     )
                   15865:                 ),
                   15866:             'doc' => '
                   15867: Lists the packages available on the configured server along with the
                   15868: latest stable release of each package.',
                   15869:             ),
                   15870:         'search' => array(
                   15871:             'summary' => 'Search remote package database',
                   15872:             'function' => 'doSearch',
                   15873:             'shortcut' => 'sp',
                   15874:             'options' => array(
                   15875:                 'channel' =>
                   15876:                     array(
                   15877:                     'shortopt' => 'c',
                   15878:                     'doc' => 'specify a channel other than the default channel',
                   15879:                     'arg' => 'CHAN',
                   15880:                     ),
                   15881:                 'allchannels' => array(
                   15882:                     'shortopt' => 'a',
                   15883:                     'doc' => 'search packages from all known channels',
                   15884:                     ),
                   15885:                 'channelinfo' => array(
                   15886:                     'shortopt' => 'i',
                   15887:                     'doc' => 'output fully channel-aware data, even on failure',
                   15888:                     ),
                   15889:                 ),
                   15890:             'doc' => '[packagename] [packageinfo]
                   15891: Lists all packages which match the search parameters.  The first
                   15892: parameter is a fragment of a packagename.  The default channel
                   15893: will be used unless explicitly overridden.  The second parameter
                   15894: will be used to match any portion of the summary/description',
                   15895:             ),
                   15896:         'list-all' => array(
                   15897:             'summary' => 'List All Packages',
                   15898:             'function' => 'doListAll',
                   15899:             'shortcut' => 'la',
                   15900:             'options' => array(
                   15901:                 'channel' =>
                   15902:                     array(
                   15903:                     'shortopt' => 'c',
                   15904:                     'doc' => 'specify a channel other than the default channel',
                   15905:                     'arg' => 'CHAN',
                   15906:                     ),
                   15907:                 'channelinfo' => array(
                   15908:                     'shortopt' => 'i',
                   15909:                     'doc' => 'output fully channel-aware data, even on failure',
                   15910:                     ),
                   15911:                 ),
                   15912:             'doc' => '
                   15913: Lists the packages available on the configured server along with the
                   15914: latest stable release of each package.',
                   15915:             ),
                   15916:         'download' => array(
                   15917:             'summary' => 'Download Package',
                   15918:             'function' => 'doDownload',
                   15919:             'shortcut' => 'd',
                   15920:             'options' => array(
                   15921:                 'nocompress' => array(
                   15922:                     'shortopt' => 'Z',
                   15923:                     'doc' => 'download an uncompressed (.tar) file',
                   15924:                     ),
                   15925:                 ),
                   15926:             'doc' => '<package>...
                   15927: Download package tarballs.  The files will be named as suggested by the
                   15928: server, for example if you download the DB package and the latest stable
                   15929: version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.',
                   15930:             ),
                   15931:         'clear-cache' => array(
                   15932:             'summary' => 'Clear Web Services Cache',
                   15933:             'function' => 'doClearCache',
                   15934:             'shortcut' => 'cc',
                   15935:             'options' => array(),
                   15936:             'doc' => '
                   15937: Clear the REST cache. See also the cache_ttl configuration
                   15938: parameter.
                   15939: ',
                   15940:             ),
                   15941:         );
                   15942: 
                   15943:     /**
                   15944:      * PEAR_Command_Remote constructor.
                   15945:      *
                   15946:      * @access public
                   15947:      */
                   15948:     function PEAR_Command_Remote(&$ui, &$config)
                   15949:     {
                   15950:         parent::PEAR_Command_Common($ui, $config);
                   15951:     }
                   15952: 
                   15953:     function _checkChannelForStatus($channel, $chan)
                   15954:     {
                   15955:         if (PEAR::isError($chan)) {
                   15956:             $this->raiseError($chan);
                   15957:         }
                   15958:         if (!is_a($chan, 'PEAR_ChannelFile')) {
                   15959:             return $this->raiseError('Internal corruption error: invalid channel "' .
                   15960:                 $channel . '"');
                   15961:         }
                   15962:         $rest = new PEAR_REST($this->config);
                   15963:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   15964:         $mirror = $this->config->get('preferred_mirror', null,
                   15965:                                      $channel);
                   15966:         $a = $rest->downloadHttp('http://' . $channel .
                   15967:             '/channel.xml', $chan->lastModified());
                   15968:         PEAR::staticPopErrorHandling();
                   15969:         if (!PEAR::isError($a) && $a) {
                   15970:             $this->ui->outputData('WARNING: channel "' . $channel . '" has ' .
                   15971:                 'updated its protocols, use "' . PEAR_RUNTYPE . ' channel-update ' . $channel .
                   15972:                 '" to update');
                   15973:         }
                   15974:     }
                   15975: 
                   15976:     function doRemoteInfo($command, $options, $params)
                   15977:     {
                   15978:         if (sizeof($params) != 1) {
                   15979:             return $this->raiseError("$command expects one param: the remote package name");
                   15980:         }
                   15981:         $savechannel = $channel = $this->config->get('default_channel');
                   15982:         $reg = &$this->config->getRegistry();
                   15983:         $package = $params[0];
                   15984:         $parsed = $reg->parsePackageName($package, $channel);
                   15985:         if (PEAR::isError($parsed)) {
                   15986:             return $this->raiseError('Invalid package name "' . $package . '"');
                   15987:         }
                   15988: 
                   15989:         $channel = $parsed['channel'];
                   15990:         $this->config->set('default_channel', $channel);
                   15991:         $chan = $reg->getChannel($channel);
                   15992:         if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
                   15993:             return $e;
                   15994:         }
                   15995: 
                   15996:         $mirror = $this->config->get('preferred_mirror');
                   15997:         if ($chan->supportsREST($mirror) && $base = $chan->getBaseURL('REST1.0', $mirror)) {
                   15998:             $rest = &$this->config->getREST('1.0', array());
                   15999:             $info = $rest->packageInfo($base, $parsed['package'], $channel);
                   16000:         }
                   16001: 
                   16002:         if (!isset($info)) {
                   16003:             return $this->raiseError('No supported protocol was found');
                   16004:         }
                   16005: 
                   16006:         if (PEAR::isError($info)) {
                   16007:             $this->config->set('default_channel', $savechannel);
                   16008:             return $this->raiseError($info);
                   16009:         }
                   16010: 
                   16011:         if (!isset($info['name'])) {
                   16012:             return $this->raiseError('No remote package "' . $package . '" was found');
                   16013:         }
                   16014: 
                   16015:         $installed = $reg->packageInfo($info['name'], null, $channel);
                   16016:         $info['installed'] = $installed['version'] ? $installed['version'] : '- no -';
                   16017:         if (is_array($info['installed'])) {
                   16018:             $info['installed'] = $info['installed']['release'];
                   16019:         }
                   16020: 
                   16021:         $this->ui->outputData($info, $command);
                   16022:         $this->config->set('default_channel', $savechannel);
                   16023: 
                   16024:         return true;
                   16025:     }
                   16026: 
                   16027:     function doRemoteList($command, $options, $params)
                   16028:     {
                   16029:         $savechannel = $channel = $this->config->get('default_channel');
                   16030:         $reg = &$this->config->getRegistry();
                   16031:         if (isset($options['channel'])) {
                   16032:             $channel = $options['channel'];
                   16033:             if (!$reg->channelExists($channel)) {
                   16034:                 return $this->raiseError('Channel "' . $channel . '" does not exist');
                   16035:             }
                   16036: 
                   16037:             $this->config->set('default_channel', $channel);
                   16038:         }
                   16039: 
                   16040:         $chan = $reg->getChannel($channel);
                   16041:         if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
                   16042:             return $e;
                   16043:         }
                   16044: 
                   16045:         $list_options = false;
                   16046:         if ($this->config->get('preferred_state') == 'stable') {
                   16047:             $list_options = true;
                   16048:         }
                   16049: 
                   16050:         $available = array();
                   16051:         if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
                   16052:               $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))
                   16053:         ) {
                   16054:             // use faster list-all if available
                   16055:             $rest = &$this->config->getREST('1.1', array());
                   16056:             $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName());
                   16057:         } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) &&
                   16058:               $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
                   16059:             $rest = &$this->config->getREST('1.0', array());
                   16060:             $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName());
                   16061:         }
                   16062: 
                   16063:         if (PEAR::isError($available)) {
                   16064:             $this->config->set('default_channel', $savechannel);
                   16065:             return $this->raiseError($available);
                   16066:         }
                   16067: 
                   16068:         $i = $j = 0;
                   16069:         $data = array(
                   16070:             'caption' => 'Channel ' . $channel . ' Available packages:',
                   16071:             'border' => true,
                   16072:             'headline' => array('Package', 'Version'),
                   16073:             'channel' => $channel
                   16074:             );
                   16075: 
                   16076:         if (count($available) == 0) {
                   16077:             $data = '(no packages available yet)';
                   16078:         } else {
                   16079:             foreach ($available as $name => $info) {
                   16080:                 $version = (isset($info['stable']) && $info['stable']) ? $info['stable'] : '-n/a-';
                   16081:                 $data['data'][] = array($name, $version);
                   16082:             }
                   16083:         }
                   16084:         $this->ui->outputData($data, $command);
                   16085:         $this->config->set('default_channel', $savechannel);
                   16086:         return true;
                   16087:     }
                   16088: 
                   16089:     function doListAll($command, $options, $params)
                   16090:     {
                   16091:         $savechannel = $channel = $this->config->get('default_channel');
                   16092:         $reg = &$this->config->getRegistry();
                   16093:         if (isset($options['channel'])) {
                   16094:             $channel = $options['channel'];
                   16095:             if (!$reg->channelExists($channel)) {
                   16096:                 return $this->raiseError("Channel \"$channel\" does not exist");
                   16097:             }
                   16098: 
                   16099:             $this->config->set('default_channel', $channel);
                   16100:         }
                   16101: 
                   16102:         $list_options = false;
                   16103:         if ($this->config->get('preferred_state') == 'stable') {
                   16104:             $list_options = true;
                   16105:         }
                   16106: 
                   16107:         $chan = $reg->getChannel($channel);
                   16108:         if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
                   16109:             return $e;
                   16110:         }
                   16111: 
                   16112:         if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
                   16113:               $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) {
                   16114:             // use faster list-all if available
                   16115:             $rest = &$this->config->getREST('1.1', array());
                   16116:             $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName());
                   16117:         } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) &&
                   16118:               $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
                   16119:             $rest = &$this->config->getREST('1.0', array());
                   16120:             $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName());
                   16121:         }
                   16122: 
                   16123:         if (PEAR::isError($available)) {
                   16124:             $this->config->set('default_channel', $savechannel);
                   16125:             return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "' . $available->getMessage() . '")');
                   16126:         }
                   16127: 
                   16128:         $data = array(
                   16129:             'caption' => 'All packages [Channel ' . $channel . ']:',
                   16130:             'border' => true,
                   16131:             'headline' => array('Package', 'Latest', 'Local'),
                   16132:             'channel' => $channel,
                   16133:             );
                   16134: 
                   16135:         if (isset($options['channelinfo'])) {
                   16136:             // add full channelinfo
                   16137:             $data['caption'] = 'Channel ' . $channel . ' All packages:';
                   16138:             $data['headline'] = array('Channel', 'Package', 'Latest', 'Local',
                   16139:                 'Description', 'Dependencies');
                   16140:         }
                   16141:         $local_pkgs = $reg->listPackages($channel);
                   16142: 
                   16143:         foreach ($available as $name => $info) {
                   16144:             $installed = $reg->packageInfo($name, null, $channel);
                   16145:             if (is_array($installed['version'])) {
                   16146:                 $installed['version'] = $installed['version']['release'];
                   16147:             }
                   16148:             $desc = $info['summary'];
                   16149:             if (isset($params[$name])) {
                   16150:                 $desc .= "\n\n".$info['description'];
                   16151:             }
                   16152:             if (isset($options['mode']))
                   16153:             {
                   16154:                 if ($options['mode'] == 'installed' && !isset($installed['version'])) {
                   16155:                     continue;
                   16156:                 }
                   16157:                 if ($options['mode'] == 'notinstalled' && isset($installed['version'])) {
                   16158:                     continue;
                   16159:                 }
                   16160:                 if ($options['mode'] == 'upgrades'
                   16161:                       && (!isset($installed['version']) || version_compare($installed['version'],
                   16162:                       $info['stable'], '>='))) {
                   16163:                     continue;
                   16164:                 }
                   16165:             }
                   16166:             $pos = array_search(strtolower($name), $local_pkgs);
                   16167:             if ($pos !== false) {
                   16168:                 unset($local_pkgs[$pos]);
                   16169:             }
                   16170: 
                   16171:             if (isset($info['stable']) && !$info['stable']) {
                   16172:                 $info['stable'] = null;
                   16173:             }
                   16174: 
                   16175:             if (isset($options['channelinfo'])) {
                   16176:                 // add full channelinfo
                   16177:                 if ($info['stable'] === $info['unstable']) {
                   16178:                     $state = $info['state'];
                   16179:                 } else {
                   16180:                     $state = 'stable';
                   16181:                 }
                   16182:                 $latest = $info['stable'].' ('.$state.')';
                   16183:                 $local = '';
                   16184:                 if (isset($installed['version'])) {
                   16185:                     $inst_state = $reg->packageInfo($name, 'release_state', $channel);
                   16186:                     $local = $installed['version'].' ('.$inst_state.')';
                   16187:                 }
                   16188: 
                   16189:                 $packageinfo = array(
                   16190:                     $channel,
                   16191:                     $name,
                   16192:                     $latest,
                   16193:                     $local,
                   16194:                     isset($desc) ? $desc : null,
                   16195:                     isset($info['deps']) ? $info['deps'] : null,
                   16196:                 );
                   16197:             } else {
                   16198:                 $packageinfo = array(
                   16199:                     $reg->channelAlias($channel) . '/' . $name,
                   16200:                     isset($info['stable']) ? $info['stable'] : null,
                   16201:                     isset($installed['version']) ? $installed['version'] : null,
                   16202:                     isset($desc) ? $desc : null,
                   16203:                     isset($info['deps']) ? $info['deps'] : null,
                   16204:                 );
                   16205:             }
                   16206:             $data['data'][$info['category']][] = $packageinfo;
                   16207:         }
                   16208: 
                   16209:         if (isset($options['mode']) && in_array($options['mode'], array('notinstalled', 'upgrades'))) {
                   16210:             $this->config->set('default_channel', $savechannel);
                   16211:             $this->ui->outputData($data, $command);
                   16212:             return true;
                   16213:         }
                   16214: 
                   16215:         foreach ($local_pkgs as $name) {
                   16216:             $info = &$reg->getPackage($name, $channel);
                   16217:             $data['data']['Local'][] = array(
                   16218:                 $reg->channelAlias($channel) . '/' . $info->getPackage(),
                   16219:                 '',
                   16220:                 $info->getVersion(),
                   16221:                 $info->getSummary(),
                   16222:                 $info->getDeps()
                   16223:                 );
                   16224:         }
                   16225: 
                   16226:         $this->config->set('default_channel', $savechannel);
                   16227:         $this->ui->outputData($data, $command);
                   16228:         return true;
                   16229:     }
                   16230: 
                   16231:     function doSearch($command, $options, $params)
                   16232:     {
                   16233:         if ((!isset($params[0]) || empty($params[0]))
                   16234:             && (!isset($params[1]) || empty($params[1])))
                   16235:         {
                   16236:             return $this->raiseError('no valid search string supplied');
                   16237:         }
                   16238: 
                   16239:         $channelinfo = isset($options['channelinfo']);
                   16240:         $reg = &$this->config->getRegistry();
                   16241:         if (isset($options['allchannels'])) {
                   16242:             // search all channels
                   16243:             unset($options['allchannels']);
                   16244:             $channels = $reg->getChannels();
                   16245:             $errors = array();
                   16246:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   16247:             foreach ($channels as $channel) {
                   16248:                 if ($channel->getName() != '__uri') {
                   16249:                     $options['channel'] = $channel->getName();
                   16250:                     $ret = $this->doSearch($command, $options, $params);
                   16251:                     if (PEAR::isError($ret)) {
                   16252:                         $errors[] = $ret;
                   16253:                     }
                   16254:                 }
                   16255:             }
                   16256: 
                   16257:             PEAR::staticPopErrorHandling();
                   16258:             if (count($errors) !== 0) {
                   16259:                 // for now, only give first error
                   16260:                 return PEAR::raiseError($errors[0]);
                   16261:             }
                   16262: 
                   16263:             return true;
                   16264:         }
                   16265: 
                   16266:         $savechannel = $channel = $this->config->get('default_channel');
                   16267:         $package = strtolower($params[0]);
                   16268:         $summary = isset($params[1]) ? $params[1] : false;
                   16269:         if (isset($options['channel'])) {
                   16270:             $reg = &$this->config->getRegistry();
                   16271:             $channel = $options['channel'];
                   16272:             if (!$reg->channelExists($channel)) {
                   16273:                 return $this->raiseError('Channel "' . $channel . '" does not exist');
                   16274:             }
                   16275: 
                   16276:             $this->config->set('default_channel', $channel);
                   16277:         }
                   16278: 
                   16279:         $chan = $reg->getChannel($channel);
                   16280:         if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
                   16281:             return $e;
                   16282:         }
                   16283: 
                   16284:         if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
                   16285:               $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
                   16286:             $rest = &$this->config->getREST('1.0', array());
                   16287:             $available = $rest->listAll($base, false, false, $package, $summary, $chan->getName());
                   16288:         }
                   16289: 
                   16290:         if (PEAR::isError($available)) {
                   16291:             $this->config->set('default_channel', $savechannel);
                   16292:             return $this->raiseError($available);
                   16293:         }
                   16294: 
                   16295:         if (!$available && !$channelinfo) {
                   16296:             // clean exit when not found, no error !
                   16297:             $data = 'no packages found that match pattern "' . $package . '", for channel '.$channel.'.';
                   16298:             $this->ui->outputData($data);
                   16299:             $this->config->set('default_channel', $channel);
                   16300:             return true;
                   16301:         }
                   16302: 
                   16303:         if ($channelinfo) {
                   16304:             $data = array(
                   16305:                 'caption' => 'Matched packages, channel ' . $channel . ':',
                   16306:                 'border' => true,
                   16307:                 'headline' => array('Channel', 'Package', 'Stable/(Latest)', 'Local'),
                   16308:                 'channel' => $channel
                   16309:                 );
                   16310:         } else {
                   16311:             $data = array(
                   16312:                 'caption' => 'Matched packages, channel ' . $channel . ':',
                   16313:                 'border' => true,
                   16314:                 'headline' => array('Package', 'Stable/(Latest)', 'Local'),
                   16315:                 'channel' => $channel
                   16316:                 );
                   16317:         }
                   16318: 
                   16319:         if (!$available && $channelinfo) {
                   16320:             unset($data['headline']);
                   16321:             $data['data'] = 'No packages found that match pattern "' . $package . '".';
                   16322:             $available = array();
                   16323:         }
                   16324: 
                   16325:         foreach ($available as $name => $info) {
                   16326:             $installed = $reg->packageInfo($name, null, $channel);
                   16327:             $desc = $info['summary'];
                   16328:             if (isset($params[$name]))
                   16329:                 $desc .= "\n\n".$info['description'];
                   16330: 
                   16331:             if (!isset($info['stable']) || !$info['stable']) {
                   16332:                 $version_remote = 'none';
                   16333:             } else {
                   16334:                 if ($info['unstable']) {
                   16335:                     $version_remote = $info['unstable'];
                   16336:                 } else {
                   16337:                     $version_remote = $info['stable'];
                   16338:                 }
                   16339:                 $version_remote .= ' ('.$info['state'].')';
                   16340:             }
                   16341:             $version = is_array($installed['version']) ? $installed['version']['release'] :
                   16342:                 $installed['version'];
                   16343:             if ($channelinfo) {
                   16344:                 $packageinfo = array(
                   16345:                     $channel,
                   16346:                     $name,
                   16347:                     $version_remote,
                   16348:                     $version,
                   16349:                     $desc,
                   16350:                 );
                   16351:             } else {
                   16352:                 $packageinfo = array(
                   16353:                     $name,
                   16354:                     $version_remote,
                   16355:                     $version,
                   16356:                     $desc,
                   16357:                 );
                   16358:             }
                   16359:             $data['data'][$info['category']][] = $packageinfo;
                   16360:         }
                   16361: 
                   16362:         $this->ui->outputData($data, $command);
                   16363:         $this->config->set('default_channel', $channel);
                   16364:         return true;
                   16365:     }
                   16366: 
                   16367:     function &getDownloader($options)
                   16368:     {
                   16369:         if (!class_exists('PEAR_Downloader')) {
                   16370:             require_once 'PEAR/Downloader.php';
                   16371:         }
                   16372:         $a = &new PEAR_Downloader($this->ui, $options, $this->config);
                   16373:         return $a;
                   16374:     }
                   16375: 
                   16376:     function doDownload($command, $options, $params)
                   16377:     {
                   16378:         // make certain that dependencies are ignored
                   16379:         $options['downloadonly'] = 1;
                   16380: 
                   16381:         // eliminate error messages for preferred_state-related errors
                   16382:         /* TODO: Should be an option, but until now download does respect
                   16383:            prefered state */
                   16384:         /* $options['ignorepreferred_state'] = 1; */
                   16385:         // eliminate error messages for preferred_state-related errors
                   16386: 
                   16387:         $downloader = &$this->getDownloader($options);
                   16388:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   16389:         $e = $downloader->setDownloadDir(getcwd());
                   16390:         PEAR::staticPopErrorHandling();
                   16391:         if (PEAR::isError($e)) {
                   16392:             return $this->raiseError('Current directory is not writeable, cannot download');
                   16393:         }
                   16394: 
                   16395:         $errors = array();
                   16396:         $downloaded = array();
                   16397:         $err = $downloader->download($params);
                   16398:         if (PEAR::isError($err)) {
                   16399:             return $err;
                   16400:         }
                   16401: 
                   16402:         $errors = $downloader->getErrorMsgs();
                   16403:         if (count($errors)) {
                   16404:             foreach ($errors as $error) {
                   16405:                 if ($error !== null) {
                   16406:                     $this->ui->outputData($error);
                   16407:                 }
                   16408:             }
                   16409: 
                   16410:             return $this->raiseError("$command failed");
                   16411:         }
                   16412: 
                   16413:         $downloaded = $downloader->getDownloadedPackages();
                   16414:         foreach ($downloaded as $pkg) {
                   16415:             $this->ui->outputData("File $pkg[file] downloaded", $command);
                   16416:         }
                   16417: 
                   16418:         return true;
                   16419:     }
                   16420: 
                   16421:     function downloadCallback($msg, $params = null)
                   16422:     {
                   16423:         if ($msg == 'done') {
                   16424:             $this->bytes_downloaded = $params;
                   16425:         }
                   16426:     }
                   16427: 
                   16428:     function doListUpgrades($command, $options, $params)
                   16429:     {
                   16430:         require_once 'PEAR/Common.php';
                   16431:         if (isset($params[0]) && !is_array(PEAR_Common::betterStates($params[0]))) {
                   16432:             return $this->raiseError($params[0] . ' is not a valid state (stable/beta/alpha/devel/etc.) try "pear help list-upgrades"');
                   16433:         }
                   16434: 
                   16435:         $savechannel = $channel = $this->config->get('default_channel');
                   16436:         $reg = &$this->config->getRegistry();
                   16437:         foreach ($reg->listChannels() as $channel) {
                   16438:             $inst = array_flip($reg->listPackages($channel));
                   16439:             if (!count($inst)) {
                   16440:                 continue;
                   16441:             }
                   16442: 
                   16443:             if ($channel == '__uri') {
                   16444:                 continue;
                   16445:             }
                   16446: 
                   16447:             $this->config->set('default_channel', $channel);
                   16448:             $state = empty($params[0]) ? $this->config->get('preferred_state') : $params[0];
                   16449: 
                   16450:             $caption = $channel . ' Available Upgrades';
                   16451:             $chan = $reg->getChannel($channel);
                   16452:             if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
                   16453:                 return $e;
                   16454:             }
                   16455: 
                   16456:             $latest = array();
                   16457:             $base2  = false;
                   16458:             $preferred_mirror = $this->config->get('preferred_mirror');
                   16459:             if ($chan->supportsREST($preferred_mirror) &&
                   16460:                 (
                   16461:                    //($base2 = $chan->getBaseURL('REST1.4', $preferred_mirror)) ||
                   16462:                    ($base  = $chan->getBaseURL('REST1.0', $preferred_mirror))
                   16463:                 )
                   16464: 
                   16465:             ) {
                   16466:                 if ($base2) {
                   16467:                     $rest = &$this->config->getREST('1.4', array());
                   16468:                     $base = $base2;
                   16469:                 } else {
                   16470:                     $rest = &$this->config->getREST('1.0', array());
                   16471:                 }
                   16472: 
                   16473:                 if (empty($state) || $state == 'any') {
                   16474:                     $state = false;
                   16475:                 } else {
                   16476:                     $caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')';
                   16477:                 }
                   16478: 
                   16479:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   16480:                 $latest = $rest->listLatestUpgrades($base, $state, $inst, $channel, $reg);
                   16481:                 PEAR::staticPopErrorHandling();
                   16482:             }
                   16483: 
                   16484:             if (PEAR::isError($latest)) {
                   16485:                 $this->ui->outputData($latest->getMessage());
                   16486:                 continue;
                   16487:             }
                   16488: 
                   16489:             $caption .= ':';
                   16490:             if (PEAR::isError($latest)) {
                   16491:                 $this->config->set('default_channel', $savechannel);
                   16492:                 return $latest;
                   16493:             }
                   16494: 
                   16495:             $data = array(
                   16496:                 'caption' => $caption,
                   16497:                 'border' => 1,
                   16498:                 'headline' => array('Channel', 'Package', 'Local', 'Remote', 'Size'),
                   16499:                 'channel' => $channel
                   16500:                 );
                   16501: 
                   16502:             foreach ((array)$latest as $pkg => $info) {
                   16503:                 $package = strtolower($pkg);
                   16504:                 if (!isset($inst[$package])) {
                   16505:                     // skip packages we don't have installed
                   16506:                     continue;
                   16507:                 }
                   16508: 
                   16509:                 extract($info);
                   16510:                 $inst_version = $reg->packageInfo($package, 'version', $channel);
                   16511:                 $inst_state   = $reg->packageInfo($package, 'release_state', $channel);
                   16512:                 if (version_compare("$version", "$inst_version", "le")) {
                   16513:                     // installed version is up-to-date
                   16514:                     continue;
                   16515:                 }
                   16516: 
                   16517:                 if ($filesize >= 20480) {
                   16518:                     $filesize += 1024 - ($filesize % 1024);
                   16519:                     $fs = sprintf("%dkB", $filesize / 1024);
                   16520:                 } elseif ($filesize > 0) {
                   16521:                     $filesize += 103 - ($filesize % 103);
                   16522:                     $fs = sprintf("%.1fkB", $filesize / 1024.0);
                   16523:                 } else {
                   16524:                     $fs = "  -"; // XXX center instead
                   16525:                 }
                   16526: 
                   16527:                 $data['data'][] = array($channel, $pkg, "$inst_version ($inst_state)", "$version ($state)", $fs);
                   16528:             }
                   16529: 
                   16530:             if (isset($options['channelinfo'])) {
                   16531:                 if (empty($data['data'])) {
                   16532:                     unset($data['headline']);
                   16533:                     if (count($inst) == 0) {
                   16534:                         $data['data'] = '(no packages installed)';
                   16535:                     } else {
                   16536:                         $data['data'] = '(no upgrades available)';
                   16537:                     }
                   16538:                 }
                   16539:                 $this->ui->outputData($data, $command);
                   16540:             } else {
                   16541:                 if (empty($data['data'])) {
                   16542:                     $this->ui->outputData('Channel ' . $channel . ': No upgrades available');
                   16543:                 } else {
                   16544:                     $this->ui->outputData($data, $command);
                   16545:                 }
                   16546:             }
                   16547:         }
                   16548: 
                   16549:         $this->config->set('default_channel', $savechannel);
                   16550:         return true;
                   16551:     }
                   16552: 
                   16553:     function doClearCache($command, $options, $params)
                   16554:     {
                   16555:         $cache_dir = $this->config->get('cache_dir');
                   16556:         $verbose   = $this->config->get('verbose');
                   16557:         $output = '';
                   16558:         if (!file_exists($cache_dir) || !is_dir($cache_dir)) {
                   16559:             return $this->raiseError("$cache_dir does not exist or is not a directory");
                   16560:         }
                   16561: 
                   16562:         if (!($dp = @opendir($cache_dir))) {
                   16563:             return $this->raiseError("opendir($cache_dir) failed: $php_errormsg");
                   16564:         }
                   16565: 
                   16566:         if ($verbose >= 1) {
                   16567:             $output .= "reading directory $cache_dir\n";
                   16568:         }
                   16569: 
                   16570:         $num = 0;
                   16571:         while ($ent = readdir($dp)) {
                   16572:             if (preg_match('/rest.cache(file|id)\\z/', $ent)) {
                   16573:                 $path = $cache_dir . DIRECTORY_SEPARATOR . $ent;
                   16574:                 if (file_exists($path)) {
                   16575:                     $ok = @unlink($path);
                   16576:                 } else {
                   16577:                     $ok = false;
                   16578:                     $php_errormsg = '';
                   16579:                 }
                   16580: 
                   16581:                 if ($ok) {
                   16582:                     if ($verbose >= 2) {
                   16583:                         $output .= "deleted $path\n";
                   16584:                     }
                   16585:                     $num++;
                   16586:                 } elseif ($verbose >= 1) {
                   16587:                     $output .= "failed to delete $path $php_errormsg\n";
                   16588:                 }
                   16589:             }
                   16590:         }
                   16591: 
                   16592:         closedir($dp);
                   16593:         if ($verbose >= 1) {
                   16594:             $output .= "$num cache entries cleared\n";
                   16595:         }
                   16596: 
                   16597:         $this->ui->outputData(rtrim($output), $command);
                   16598:         return $num;
                   16599:     }
1.1.1.2 ! misho    16600: }PEAR-1.9.4/PEAR/Command/Test.xml0000644000076500000240000000315111605156614015002 0ustar  helgistaff<commands version="1.0">
1.1       misho    16601:  <run-tests>
                   16602:   <summary>Run Regression Tests</summary>
                   16603:   <function>doRunTests</function>
                   16604:   <shortcut>rt</shortcut>
                   16605:   <options>
                   16606:    <recur>
                   16607:     <shortopt>r</shortopt>
                   16608:     <doc>Run tests in child directories, recursively.  4 dirs deep maximum</doc>
                   16609:    </recur>
                   16610:    <ini>
                   16611:     <shortopt>i</shortopt>
                   16612:     <doc>actual string of settings to pass to php in format &quot; -d setting=blah&quot;</doc>
                   16613:     <arg>SETTINGS</arg>
                   16614:    </ini>
                   16615:    <realtimelog>
                   16616:     <shortopt>l</shortopt>
                   16617:     <doc>Log test runs/results as they are run</doc>
                   16618:    </realtimelog>
                   16619:    <quiet>
                   16620:     <shortopt>q</shortopt>
                   16621:     <doc>Only display detail for failed tests</doc>
                   16622:    </quiet>
                   16623:    <simple>
                   16624:     <shortopt>s</shortopt>
                   16625:     <doc>Display simple output for all tests</doc>
                   16626:    </simple>
                   16627:    <package>
                   16628:     <shortopt>p</shortopt>
                   16629:     <doc>Treat parameters as installed packages from which to run tests</doc>
                   16630:    </package>
                   16631:    <phpunit>
                   16632:     <shortopt>u</shortopt>
                   16633:     <doc>Search parameters for AllTests.php, and use that to run phpunit-based tests
                   16634: If none is found, all .phpt tests will be tried instead.</doc>
                   16635:    </phpunit>
                   16636:    <tapoutput>
                   16637:     <shortopt>t</shortopt>
                   16638:     <doc>Output run-tests.log in TAP-compliant format</doc>
                   16639:    </tapoutput>
                   16640:    <cgi>
                   16641:     <shortopt>c</shortopt>
                   16642:     <doc>CGI php executable (needed for tests with POST/GET section)</doc>
                   16643:     <arg>PHPCGI</arg>
                   16644:    </cgi>
                   16645:    <coverage>
                   16646:     <shortopt>x</shortopt>
                   16647:     <doc>Generate a code coverage report (requires Xdebug 2.0.0+)</doc>
                   16648:    </coverage>
                   16649:   </options>
                   16650:   <doc>[testfile|dir ...]
                   16651: Run regression tests with PHP&#039;s regression testing script (run-tests.php).</doc>
                   16652:  </run-tests>
1.1.1.2 ! misho    16653: </commands>PEAR-1.9.4/PEAR/Command/Test.php0000644000076500000240000002726611605156614015006 0ustar  helgistaff<?php
1.1       misho    16654: /**
                   16655:  * PEAR_Command_Test (run-tests)
                   16656:  *
                   16657:  * PHP versions 4 and 5
                   16658:  *
                   16659:  * @category   pear
                   16660:  * @package    PEAR
                   16661:  * @author     Stig Bakken <ssb@php.net>
                   16662:  * @author     Martin Jansen <mj@php.net>
                   16663:  * @author     Greg Beaver <cellog@php.net>
                   16664:  * @copyright  1997-2009 The Authors
                   16665:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   16666:  * @version    CVS: $Id: Test.php 313023 2011-07-06 19:17:11Z dufuz $
                   16667:  * @link       http://pear.php.net/package/PEAR
                   16668:  * @since      File available since Release 0.1
                   16669:  */
                   16670: 
                   16671: /**
                   16672:  * base class
                   16673:  */
                   16674: require_once 'PEAR/Command/Common.php';
                   16675: 
                   16676: /**
                   16677:  * PEAR commands for login/logout
                   16678:  *
                   16679:  * @category   pear
                   16680:  * @package    PEAR
                   16681:  * @author     Stig Bakken <ssb@php.net>
                   16682:  * @author     Martin Jansen <mj@php.net>
                   16683:  * @author     Greg Beaver <cellog@php.net>
                   16684:  * @copyright  1997-2009 The Authors
                   16685:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   16686:  * @version    Release: 1.9.4
                   16687:  * @link       http://pear.php.net/package/PEAR
                   16688:  * @since      Class available since Release 0.1
                   16689:  */
                   16690: 
                   16691: class PEAR_Command_Test extends PEAR_Command_Common
                   16692: {
                   16693:     var $commands = array(
                   16694:         'run-tests' => array(
                   16695:             'summary' => 'Run Regression Tests',
                   16696:             'function' => 'doRunTests',
                   16697:             'shortcut' => 'rt',
                   16698:             'options' => array(
                   16699:                 'recur' => array(
                   16700:                     'shortopt' => 'r',
                   16701:                     'doc' => 'Run tests in child directories, recursively.  4 dirs deep maximum',
                   16702:                 ),
                   16703:                 'ini' => array(
                   16704:                     'shortopt' => 'i',
                   16705:                     'doc' => 'actual string of settings to pass to php in format " -d setting=blah"',
                   16706:                     'arg' => 'SETTINGS'
                   16707:                 ),
                   16708:                 'realtimelog' => array(
                   16709:                     'shortopt' => 'l',
                   16710:                     'doc' => 'Log test runs/results as they are run',
                   16711:                 ),
                   16712:                 'quiet' => array(
                   16713:                     'shortopt' => 'q',
                   16714:                     'doc' => 'Only display detail for failed tests',
                   16715:                 ),
                   16716:                 'simple' => array(
                   16717:                     'shortopt' => 's',
                   16718:                     'doc' => 'Display simple output for all tests',
                   16719:                 ),
                   16720:                 'package' => array(
                   16721:                     'shortopt' => 'p',
                   16722:                     'doc' => 'Treat parameters as installed packages from which to run tests',
                   16723:                 ),
                   16724:                 'phpunit' => array(
                   16725:                     'shortopt' => 'u',
                   16726:                     'doc' => 'Search parameters for AllTests.php, and use that to run phpunit-based tests
                   16727: If none is found, all .phpt tests will be tried instead.',
                   16728:                 ),
                   16729:                 'tapoutput' => array(
                   16730:                     'shortopt' => 't',
                   16731:                     'doc' => 'Output run-tests.log in TAP-compliant format',
                   16732:                 ),
                   16733:                 'cgi' => array(
                   16734:                     'shortopt' => 'c',
                   16735:                     'doc' => 'CGI php executable (needed for tests with POST/GET section)',
                   16736:                     'arg' => 'PHPCGI',
                   16737:                 ),
                   16738:                 'coverage' => array(
                   16739:                     'shortopt' => 'x',
                   16740:                     'doc'      => 'Generate a code coverage report (requires Xdebug 2.0.0+)',
                   16741:                 ),
                   16742:             ),
                   16743:             'doc' => '[testfile|dir ...]
                   16744: Run regression tests with PHP\'s regression testing script (run-tests.php).',
                   16745:             ),
                   16746:         );
                   16747: 
                   16748:     var $output;
                   16749: 
                   16750:     /**
                   16751:      * PEAR_Command_Test constructor.
                   16752:      *
                   16753:      * @access public
                   16754:      */
                   16755:     function PEAR_Command_Test(&$ui, &$config)
                   16756:     {
                   16757:         parent::PEAR_Command_Common($ui, $config);
                   16758:     }
                   16759: 
                   16760:     function doRunTests($command, $options, $params)
                   16761:     {
                   16762:         if (isset($options['phpunit']) && isset($options['tapoutput'])) {
                   16763:             return $this->raiseError('ERROR: cannot use both --phpunit and --tapoutput at the same time');
                   16764:         }
                   16765: 
                   16766:         require_once 'PEAR/Common.php';
                   16767:         require_once 'System.php';
                   16768:         $log = new PEAR_Common;
                   16769:         $log->ui = &$this->ui; // slightly hacky, but it will work
                   16770:         $tests = array();
                   16771:         $depth = isset($options['recur']) ? 14 : 1;
                   16772: 
                   16773:         if (!count($params)) {
                   16774:             $params[] = '.';
                   16775:         }
                   16776: 
                   16777:         if (isset($options['package'])) {
                   16778:             $oldparams = $params;
                   16779:             $params = array();
                   16780:             $reg = &$this->config->getRegistry();
                   16781:             foreach ($oldparams as $param) {
                   16782:                 $pname = $reg->parsePackageName($param, $this->config->get('default_channel'));
                   16783:                 if (PEAR::isError($pname)) {
                   16784:                     return $this->raiseError($pname);
                   16785:                 }
                   16786: 
                   16787:                 $package = &$reg->getPackage($pname['package'], $pname['channel']);
                   16788:                 if (!$package) {
                   16789:                     return PEAR::raiseError('Unknown package "' .
                   16790:                         $reg->parsedPackageNameToString($pname) . '"');
                   16791:                 }
                   16792: 
                   16793:                 $filelist = $package->getFilelist();
                   16794:                 foreach ($filelist as $name => $atts) {
                   16795:                     if (isset($atts['role']) && $atts['role'] != 'test') {
                   16796:                         continue;
                   16797:                     }
                   16798: 
                   16799:                     if (isset($options['phpunit']) && preg_match('/AllTests\.php\\z/i', $name)) {
                   16800:                         $params[] = $atts['installed_as'];
                   16801:                         continue;
                   16802:                     } elseif (!preg_match('/\.phpt\\z/', $name)) {
                   16803:                         continue;
                   16804:                     }
                   16805:                     $params[] = $atts['installed_as'];
                   16806:                 }
                   16807:             }
                   16808:         }
                   16809: 
                   16810:         foreach ($params as $p) {
                   16811:             if (is_dir($p)) {
                   16812:                 if (isset($options['phpunit'])) {
                   16813:                     $dir = System::find(array($p, '-type', 'f',
                   16814:                                                 '-maxdepth', $depth,
                   16815:                                                 '-name', 'AllTests.php'));
                   16816:                     if (count($dir)) {
                   16817:                         foreach ($dir as $p) {
                   16818:                             $p = realpath($p);
                   16819:                             if (!count($tests) ||
                   16820:                                   (count($tests) && strlen($p) < strlen($tests[0]))) {
                   16821:                                 // this is in a higher-level directory, use this one instead.
                   16822:                                 $tests = array($p);
                   16823:                             }
                   16824:                         }
                   16825:                     }
                   16826:                     continue;
                   16827:                 }
                   16828: 
                   16829:                 $args  = array($p, '-type', 'f', '-name', '*.phpt');
                   16830:             } else {
                   16831:                 if (isset($options['phpunit'])) {
                   16832:                     if (preg_match('/AllTests\.php\\z/i', $p)) {
                   16833:                         $p = realpath($p);
                   16834:                         if (!count($tests) ||
                   16835:                               (count($tests) && strlen($p) < strlen($tests[0]))) {
                   16836:                             // this is in a higher-level directory, use this one instead.
                   16837:                             $tests = array($p);
                   16838:                         }
                   16839:                     }
                   16840:                     continue;
                   16841:                 }
                   16842: 
                   16843:                 if (file_exists($p) && preg_match('/\.phpt$/', $p)) {
                   16844:                     $tests[] = $p;
                   16845:                     continue;
                   16846:                 }
                   16847: 
                   16848:                 if (!preg_match('/\.phpt\\z/', $p)) {
                   16849:                     $p .= '.phpt';
                   16850:                 }
                   16851: 
                   16852:                 $args  = array(dirname($p), '-type', 'f', '-name', $p);
                   16853:             }
                   16854: 
                   16855:             if (!isset($options['recur'])) {
                   16856:                 $args[] = '-maxdepth';
                   16857:                 $args[] = 1;
                   16858:             }
                   16859: 
                   16860:             $dir   = System::find($args);
                   16861:             $tests = array_merge($tests, $dir);
                   16862:         }
                   16863: 
                   16864:         $ini_settings = '';
                   16865:         if (isset($options['ini'])) {
                   16866:             $ini_settings .= $options['ini'];
                   16867:         }
                   16868: 
                   16869:         if (isset($_ENV['TEST_PHP_INCLUDE_PATH'])) {
                   16870:             $ini_settings .= " -d include_path={$_ENV['TEST_PHP_INCLUDE_PATH']}";
                   16871:         }
                   16872: 
                   16873:         if ($ini_settings) {
                   16874:             $this->ui->outputData('Using INI settings: "' . $ini_settings . '"');
                   16875:         }
                   16876: 
                   16877:         $skipped = $passed = $failed = array();
                   16878:         $tests_count = count($tests);
                   16879:         $this->ui->outputData('Running ' . $tests_count . ' tests', $command);
                   16880:         $start = time();
                   16881:         if (isset($options['realtimelog']) && file_exists('run-tests.log')) {
                   16882:             unlink('run-tests.log');
                   16883:         }
                   16884: 
                   16885:         if (isset($options['tapoutput'])) {
                   16886:             $tap = '1..' . $tests_count . "\n";
                   16887:         }
                   16888: 
                   16889:         require_once 'PEAR/RunTest.php';
                   16890:         $run = new PEAR_RunTest($log, $options);
                   16891:         $run->tests_count = $tests_count;
                   16892: 
                   16893:         if (isset($options['coverage']) && extension_loaded('xdebug')){
                   16894:             $run->xdebug_loaded = true;
                   16895:         } else {
                   16896:             $run->xdebug_loaded = false;
                   16897:         }
                   16898: 
                   16899:         $j = $i = 1;
                   16900:         foreach ($tests as $t) {
                   16901:             if (isset($options['realtimelog'])) {
                   16902:                 $fp = @fopen('run-tests.log', 'a');
                   16903:                 if ($fp) {
                   16904:                     fwrite($fp, "Running test [$i / $tests_count] $t...");
                   16905:                     fclose($fp);
                   16906:                 }
                   16907:             }
                   16908:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   16909:             if (isset($options['phpunit'])) {
                   16910:                 $result = $run->runPHPUnit($t, $ini_settings);
                   16911:             } else {
                   16912:                 $result = $run->run($t, $ini_settings, $j);
                   16913:             }
                   16914:             PEAR::staticPopErrorHandling();
                   16915:             if (PEAR::isError($result)) {
                   16916:                 $this->ui->log($result->getMessage());
                   16917:                 continue;
                   16918:             }
                   16919: 
                   16920:             if (isset($options['tapoutput'])) {
                   16921:                 $tap .= $result[0] . ' ' . $i . $result[1] . "\n";
                   16922:                 continue;
                   16923:             }
                   16924: 
                   16925:             if (isset($options['realtimelog'])) {
                   16926:                 $fp = @fopen('run-tests.log', 'a');
                   16927:                 if ($fp) {
                   16928:                     fwrite($fp, "$result\n");
                   16929:                     fclose($fp);
                   16930:                 }
                   16931:             }
                   16932: 
                   16933:             if ($result == 'FAILED') {
                   16934:                 $failed[] = $t;
                   16935:             }
                   16936:             if ($result == 'PASSED') {
                   16937:                 $passed[] = $t;
                   16938:             }
                   16939:             if ($result == 'SKIPPED') {
                   16940:                 $skipped[] = $t;
                   16941:             }
                   16942: 
                   16943:             $j++;
                   16944:         }
                   16945: 
                   16946:         $total = date('i:s', time() - $start);
                   16947:         if (isset($options['tapoutput'])) {
                   16948:             $fp = @fopen('run-tests.log', 'w');
                   16949:             if ($fp) {
                   16950:                 fwrite($fp, $tap, strlen($tap));
                   16951:                 fclose($fp);
                   16952:                 $this->ui->outputData('wrote TAP-format log to "' .realpath('run-tests.log') .
                   16953:                     '"', $command);
                   16954:             }
                   16955:         } else {
                   16956:             if (count($failed)) {
                   16957:                 $output = "TOTAL TIME: $total\n";
                   16958:                 $output .= count($passed) . " PASSED TESTS\n";
                   16959:                 $output .= count($skipped) . " SKIPPED TESTS\n";
                   16960:                 $output .= count($failed) . " FAILED TESTS:\n";
                   16961:                 foreach ($failed as $failure) {
                   16962:                     $output .= $failure . "\n";
                   16963:                 }
                   16964: 
                   16965:                 $mode = isset($options['realtimelog']) ? 'a' : 'w';
                   16966:                 $fp   = @fopen('run-tests.log', $mode);
                   16967: 
                   16968:                 if ($fp) {
                   16969:                     fwrite($fp, $output, strlen($output));
                   16970:                     fclose($fp);
                   16971:                     $this->ui->outputData('wrote log to "' . realpath('run-tests.log') . '"', $command);
                   16972:                 }
                   16973:             } elseif (file_exists('run-tests.log') && !is_dir('run-tests.log')) {
                   16974:                 @unlink('run-tests.log');
                   16975:             }
                   16976:         }
                   16977:         $this->ui->outputData('TOTAL TIME: ' . $total);
                   16978:         $this->ui->outputData(count($passed) . ' PASSED TESTS', $command);
                   16979:         $this->ui->outputData(count($skipped) . ' SKIPPED TESTS', $command);
                   16980:         if (count($failed)) {
                   16981:             $this->ui->outputData(count($failed) . ' FAILED TESTS:', $command);
                   16982:             foreach ($failed as $failure) {
                   16983:                 $this->ui->outputData($failure, $command);
                   16984:             }
                   16985:         }
                   16986: 
                   16987:         return true;
                   16988:     }
1.1.1.2 ! misho    16989: }PEAR-1.9.4/PEAR/Downloader/Package.php0000644000076500000240000022464611605156614016143 0ustar  helgistaff<?php
1.1       misho    16990: /**
                   16991:  * PEAR_Downloader_Package
                   16992:  *
                   16993:  * PHP versions 4 and 5
                   16994:  *
                   16995:  * @category   pear
                   16996:  * @package    PEAR
                   16997:  * @author     Greg Beaver <cellog@php.net>
                   16998:  * @copyright  1997-2009 The Authors
                   16999:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   17000:  * @version    CVS: $Id: Package.php 313023 2011-07-06 19:17:11Z dufuz $
                   17001:  * @link       http://pear.php.net/package/PEAR
                   17002:  * @since      File available since Release 1.4.0a1
                   17003:  */
                   17004: 
                   17005: /**
                   17006:  * Error code when parameter initialization fails because no releases
                   17007:  * exist within preferred_state, but releases do exist
                   17008:  */
                   17009: define('PEAR_DOWNLOADER_PACKAGE_STATE', -1003);
                   17010: /**
                   17011:  * Error code when parameter initialization fails because no releases
                   17012:  * exist that will work with the existing PHP version
                   17013:  */
                   17014: define('PEAR_DOWNLOADER_PACKAGE_PHPVERSION', -1004);
                   17015: 
                   17016: /**
                   17017:  * Coordinates download parameters and manages their dependencies
                   17018:  * prior to downloading them.
                   17019:  *
                   17020:  * Input can come from three sources:
                   17021:  *
                   17022:  * - local files (archives or package.xml)
                   17023:  * - remote files (downloadable urls)
                   17024:  * - abstract package names
                   17025:  *
                   17026:  * The first two elements are handled cleanly by PEAR_PackageFile, but the third requires
                   17027:  * accessing pearweb's xml-rpc interface to determine necessary dependencies, and the
                   17028:  * format returned of dependencies is slightly different from that used in package.xml.
                   17029:  *
                   17030:  * This class hides the differences between these elements, and makes automatic
                   17031:  * dependency resolution a piece of cake.  It also manages conflicts when
                   17032:  * two classes depend on incompatible dependencies, or differing versions of the same
                   17033:  * package dependency.  In addition, download will not be attempted if the php version is
                   17034:  * not supported, PEAR installer version is not supported, or non-PECL extensions are not
                   17035:  * installed.
                   17036:  * @category   pear
                   17037:  * @package    PEAR
                   17038:  * @author     Greg Beaver <cellog@php.net>
                   17039:  * @copyright  1997-2009 The Authors
                   17040:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   17041:  * @version    Release: 1.9.4
                   17042:  * @link       http://pear.php.net/package/PEAR
                   17043:  * @since      Class available since Release 1.4.0a1
                   17044:  */
                   17045: class PEAR_Downloader_Package
                   17046: {
                   17047:     /**
                   17048:      * @var PEAR_Downloader
                   17049:      */
                   17050:     var $_downloader;
                   17051:     /**
                   17052:      * @var PEAR_Config
                   17053:      */
                   17054:     var $_config;
                   17055:     /**
                   17056:      * @var PEAR_Registry
                   17057:      */
                   17058:     var $_registry;
                   17059:     /**
                   17060:      * Used to implement packagingroot properly
                   17061:      * @var PEAR_Registry
                   17062:      */
                   17063:     var $_installRegistry;
                   17064:     /**
                   17065:      * @var PEAR_PackageFile_v1|PEAR_PackageFile|v2
                   17066:      */
                   17067:     var $_packagefile;
                   17068:     /**
                   17069:      * @var array
                   17070:      */
                   17071:     var $_parsedname;
                   17072:     /**
                   17073:      * @var array
                   17074:      */
                   17075:     var $_downloadURL;
                   17076:     /**
                   17077:      * @var array
                   17078:      */
                   17079:     var $_downloadDeps = array();
                   17080:     /**
                   17081:      * @var boolean
                   17082:      */
                   17083:     var $_valid = false;
                   17084:     /**
                   17085:      * @var boolean
                   17086:      */
                   17087:     var $_analyzed = false;
                   17088:     /**
                   17089:      * if this or a parent package was invoked with Package-state, this is set to the
                   17090:      * state variable.
                   17091:      *
                   17092:      * This allows temporary reassignment of preferred_state for a parent package and all of
                   17093:      * its dependencies.
                   17094:      * @var string|false
                   17095:      */
                   17096:     var $_explicitState = false;
                   17097:     /**
                   17098:      * If this package is invoked with Package#group, this variable will be true
                   17099:      */
                   17100:     var $_explicitGroup = false;
                   17101:     /**
                   17102:      * Package type local|url
                   17103:      * @var string
                   17104:      */
                   17105:     var $_type;
                   17106:     /**
                   17107:      * Contents of package.xml, if downloaded from a remote channel
                   17108:      * @var string|false
                   17109:      * @access private
                   17110:      */
                   17111:     var $_rawpackagefile;
                   17112:     /**
                   17113:      * @var boolean
                   17114:      * @access private
                   17115:      */
                   17116:     var $_validated = false;
                   17117: 
                   17118:     /**
                   17119:      * @param PEAR_Downloader
                   17120:      */
                   17121:     function PEAR_Downloader_Package(&$downloader)
                   17122:     {
                   17123:         $this->_downloader = &$downloader;
                   17124:         $this->_config = &$this->_downloader->config;
                   17125:         $this->_registry = &$this->_config->getRegistry();
                   17126:         $options = $downloader->getOptions();
                   17127:         if (isset($options['packagingroot'])) {
                   17128:             $this->_config->setInstallRoot($options['packagingroot']);
                   17129:             $this->_installRegistry = &$this->_config->getRegistry();
                   17130:             $this->_config->setInstallRoot(false);
                   17131:         } else {
                   17132:             $this->_installRegistry = &$this->_registry;
                   17133:         }
                   17134:         $this->_valid = $this->_analyzed = false;
                   17135:     }
                   17136: 
                   17137:     /**
                   17138:      * Parse the input and determine whether this is a local file, a remote uri, or an
                   17139:      * abstract package name.
                   17140:      *
                   17141:      * This is the heart of the PEAR_Downloader_Package(), and is used in
                   17142:      * {@link PEAR_Downloader::download()}
                   17143:      * @param string
                   17144:      * @return bool|PEAR_Error
                   17145:      */
                   17146:     function initialize($param)
                   17147:     {
                   17148:         $origErr = $this->_fromFile($param);
                   17149:         if ($this->_valid) {
                   17150:             return true;
                   17151:         }
                   17152: 
                   17153:         $options = $this->_downloader->getOptions();
                   17154:         if (isset($options['offline'])) {
                   17155:             if (PEAR::isError($origErr) && !isset($options['soft'])) {
                   17156:                 foreach ($origErr->getUserInfo() as $userInfo) {
                   17157:                     if (isset($userInfo['message'])) {
                   17158:                         $this->_downloader->log(0, $userInfo['message']);
                   17159:                     }
                   17160:                 }
                   17161: 
                   17162:                 $this->_downloader->log(0, $origErr->getMessage());
                   17163:             }
                   17164: 
                   17165:             return PEAR::raiseError('Cannot download non-local package "' . $param . '"');
                   17166:         }
                   17167: 
                   17168:         $err = $this->_fromUrl($param);
                   17169:         if (PEAR::isError($err) || !$this->_valid) {
                   17170:             if ($this->_type == 'url') {
                   17171:                 if (PEAR::isError($err) && !isset($options['soft'])) {
                   17172:                     $this->_downloader->log(0, $err->getMessage());
                   17173:                 }
                   17174: 
                   17175:                 return PEAR::raiseError("Invalid or missing remote package file");
                   17176:             }
                   17177: 
                   17178:             $err = $this->_fromString($param);
                   17179:             if (PEAR::isError($err) || !$this->_valid) {
                   17180:                 if (PEAR::isError($err) && $err->getCode() == PEAR_DOWNLOADER_PACKAGE_STATE) {
                   17181:                     return false; // instruct the downloader to silently skip
                   17182:                 }
                   17183: 
                   17184:                 if (isset($this->_type) && $this->_type == 'local' && PEAR::isError($origErr)) {
                   17185:                     if (is_array($origErr->getUserInfo())) {
                   17186:                         foreach ($origErr->getUserInfo() as $err) {
                   17187:                             if (is_array($err)) {
                   17188:                                 $err = $err['message'];
                   17189:                             }
                   17190: 
                   17191:                             if (!isset($options['soft'])) {
                   17192:                                 $this->_downloader->log(0, $err);
                   17193:                             }
                   17194:                         }
                   17195:                     }
                   17196: 
                   17197:                     if (!isset($options['soft'])) {
                   17198:                         $this->_downloader->log(0, $origErr->getMessage());
                   17199:                     }
                   17200: 
                   17201:                     if (is_array($param)) {
                   17202:                         $param = $this->_registry->parsedPackageNameToString($param, true);
                   17203:                     }
                   17204: 
                   17205:                     if (!isset($options['soft'])) {
                   17206:                         $this->_downloader->log(2, "Cannot initialize '$param', invalid or missing package file");
                   17207:                     }
                   17208: 
                   17209:                     // Passing no message back - already logged above
                   17210:                     return PEAR::raiseError();
                   17211:                 }
                   17212: 
                   17213:                 if (PEAR::isError($err) && !isset($options['soft'])) {
                   17214:                     $this->_downloader->log(0, $err->getMessage());
                   17215:                 }
                   17216: 
                   17217:                 if (is_array($param)) {
                   17218:                     $param = $this->_registry->parsedPackageNameToString($param, true);
                   17219:                 }
                   17220: 
                   17221:                 if (!isset($options['soft'])) {
                   17222:                     $this->_downloader->log(2, "Cannot initialize '$param', invalid or missing package file");
                   17223:                 }
                   17224: 
                   17225:                 // Passing no message back - already logged above
                   17226:                 return PEAR::raiseError();
                   17227:             }
                   17228:         }
                   17229: 
                   17230:         return true;
                   17231:     }
                   17232: 
                   17233:     /**
                   17234:      * Retrieve any non-local packages
                   17235:      * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|PEAR_Error
                   17236:      */
                   17237:     function &download()
                   17238:     {
                   17239:         if (isset($this->_packagefile)) {
                   17240:             return $this->_packagefile;
                   17241:         }
                   17242: 
                   17243:         if (isset($this->_downloadURL['url'])) {
                   17244:             $this->_isvalid = false;
                   17245:             $info = $this->getParsedPackage();
                   17246:             foreach ($info as $i => $p) {
                   17247:                 $info[$i] = strtolower($p);
                   17248:             }
                   17249: 
                   17250:             $err = $this->_fromUrl($this->_downloadURL['url'],
                   17251:                 $this->_registry->parsedPackageNameToString($this->_parsedname, true));
                   17252:             $newinfo = $this->getParsedPackage();
                   17253:             foreach ($newinfo as $i => $p) {
                   17254:                 $newinfo[$i] = strtolower($p);
                   17255:             }
                   17256: 
                   17257:             if ($info != $newinfo) {
                   17258:                 do {
                   17259:                     if ($info['channel'] == 'pecl.php.net' && $newinfo['channel'] == 'pear.php.net') {
                   17260:                         $info['channel'] = 'pear.php.net';
                   17261:                         if ($info == $newinfo) {
                   17262:                             // skip the channel check if a pecl package says it's a PEAR package
                   17263:                             break;
                   17264:                         }
                   17265:                     }
                   17266:                     if ($info['channel'] == 'pear.php.net' && $newinfo['channel'] == 'pecl.php.net') {
                   17267:                         $info['channel'] = 'pecl.php.net';
                   17268:                         if ($info == $newinfo) {
                   17269:                             // skip the channel check if a pecl package says it's a PEAR package
                   17270:                             break;
                   17271:                         }
                   17272:                     }
                   17273: 
                   17274:                     return PEAR::raiseError('CRITICAL ERROR: We are ' .
                   17275:                         $this->_registry->parsedPackageNameToString($info) . ', but the file ' .
                   17276:                         'downloaded claims to be ' .
                   17277:                         $this->_registry->parsedPackageNameToString($this->getParsedPackage()));
                   17278:                 } while (false);
                   17279:             }
                   17280: 
                   17281:             if (PEAR::isError($err) || !$this->_valid) {
                   17282:                 return $err;
                   17283:             }
                   17284:         }
                   17285: 
                   17286:         $this->_type = 'local';
                   17287:         return $this->_packagefile;
                   17288:     }
                   17289: 
                   17290:     function &getPackageFile()
                   17291:     {
                   17292:         return $this->_packagefile;
                   17293:     }
                   17294: 
                   17295:     function &getDownloader()
                   17296:     {
                   17297:         return $this->_downloader;
                   17298:     }
                   17299: 
                   17300:     function getType()
                   17301:     {
                   17302:         return $this->_type;
                   17303:     }
                   17304: 
                   17305:     /**
                   17306:      * Like {@link initialize()}, but operates on a dependency
                   17307:      */
                   17308:     function fromDepURL($dep)
                   17309:     {
                   17310:         $this->_downloadURL = $dep;
                   17311:         if (isset($dep['uri'])) {
                   17312:             $options = $this->_downloader->getOptions();
                   17313:             if (!extension_loaded("zlib") || isset($options['nocompress'])) {
                   17314:                 $ext = '.tar';
                   17315:             } else {
                   17316:                 $ext = '.tgz';
                   17317:             }
                   17318: 
                   17319:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   17320:             $err = $this->_fromUrl($dep['uri'] . $ext);
                   17321:             PEAR::popErrorHandling();
                   17322:             if (PEAR::isError($err)) {
                   17323:                 if (!isset($options['soft'])) {
                   17324:                     $this->_downloader->log(0, $err->getMessage());
                   17325:                 }
                   17326: 
                   17327:                 return PEAR::raiseError('Invalid uri dependency "' . $dep['uri'] . $ext . '", ' .
                   17328:                     'cannot download');
                   17329:             }
                   17330:         } else {
                   17331:             $this->_parsedname =
                   17332:                 array(
                   17333:                     'package' => $dep['info']->getPackage(),
                   17334:                     'channel' => $dep['info']->getChannel(),
                   17335:                     'version' => $dep['version']
                   17336:                 );
                   17337:             if (!isset($dep['nodefault'])) {
                   17338:                 $this->_parsedname['group'] = 'default'; // download the default dependency group
                   17339:                 $this->_explicitGroup = false;
                   17340:             }
                   17341: 
                   17342:             $this->_rawpackagefile = $dep['raw'];
                   17343:         }
                   17344:     }
                   17345: 
                   17346:     function detectDependencies($params)
                   17347:     {
                   17348:         $options = $this->_downloader->getOptions();
                   17349:         if (isset($options['downloadonly'])) {
                   17350:             return;
                   17351:         }
                   17352: 
                   17353:         if (isset($options['offline'])) {
                   17354:             $this->_downloader->log(3, 'Skipping dependency download check, --offline specified');
                   17355:             return;
                   17356:         }
                   17357: 
                   17358:         $pname = $this->getParsedPackage();
                   17359:         if (!$pname) {
                   17360:             return;
                   17361:         }
                   17362: 
                   17363:         $deps = $this->getDeps();
                   17364:         if (!$deps) {
                   17365:             return;
                   17366:         }
                   17367: 
                   17368:         if (isset($deps['required'])) { // package.xml 2.0
                   17369:             return $this->_detect2($deps, $pname, $options, $params);
                   17370:         }
                   17371: 
                   17372:         return $this->_detect1($deps, $pname, $options, $params);
                   17373:     }
                   17374: 
                   17375:     function setValidated()
                   17376:     {
                   17377:         $this->_validated = true;
                   17378:     }
                   17379: 
                   17380:     function alreadyValidated()
                   17381:     {
                   17382:         return $this->_validated;
                   17383:     }
                   17384: 
                   17385:     /**
                   17386:      * Remove packages to be downloaded that are already installed
                   17387:      * @param array of PEAR_Downloader_Package objects
                   17388:      * @static
                   17389:      */
                   17390:     function removeInstalled(&$params)
                   17391:     {
                   17392:         if (!isset($params[0])) {
                   17393:             return;
                   17394:         }
                   17395: 
                   17396:         $options = $params[0]->_downloader->getOptions();
                   17397:         if (!isset($options['downloadonly'])) {
                   17398:             foreach ($params as $i => $param) {
                   17399:                 $package = $param->getPackage();
                   17400:                 $channel = $param->getChannel();
                   17401:                 // remove self if already installed with this version
                   17402:                 // this does not need any pecl magic - we only remove exact matches
                   17403:                 if ($param->_installRegistry->packageExists($package, $channel)) {
                   17404:                     $packageVersion = $param->_installRegistry->packageInfo($package, 'version', $channel);
                   17405:                     if (version_compare($packageVersion, $param->getVersion(), '==')) {
                   17406:                         if (!isset($options['force'])) {
                   17407:                             $info = $param->getParsedPackage();
                   17408:                             unset($info['version']);
                   17409:                             unset($info['state']);
                   17410:                             if (!isset($options['soft'])) {
                   17411:                                 $param->_downloader->log(1, 'Skipping package "' .
                   17412:                                     $param->getShortName() .
                   17413:                                     '", already installed as version ' . $packageVersion);
                   17414:                             }
                   17415:                             $params[$i] = false;
                   17416:                         }
                   17417:                     } elseif (!isset($options['force']) && !isset($options['upgrade']) &&
                   17418:                           !isset($options['soft'])) {
                   17419:                         $info = $param->getParsedPackage();
                   17420:                         $param->_downloader->log(1, 'Skipping package "' .
                   17421:                             $param->getShortName() .
                   17422:                             '", already installed as version ' . $packageVersion);
                   17423:                         $params[$i] = false;
                   17424:                     }
                   17425:                 }
                   17426:             }
                   17427:         }
                   17428: 
                   17429:         PEAR_Downloader_Package::removeDuplicates($params);
                   17430:     }
                   17431: 
                   17432:     function _detect2($deps, $pname, $options, $params)
                   17433:     {
                   17434:         $this->_downloadDeps = array();
                   17435:         $groupnotfound = false;
                   17436:         foreach (array('package', 'subpackage') as $packagetype) {
                   17437:             // get required dependency group
                   17438:             if (isset($deps['required'][$packagetype])) {
                   17439:                 if (isset($deps['required'][$packagetype][0])) {
                   17440:                     foreach ($deps['required'][$packagetype] as $dep) {
                   17441:                         if (isset($dep['conflicts'])) {
                   17442:                             // skip any package that this package conflicts with
                   17443:                             continue;
                   17444:                         }
                   17445:                         $ret = $this->_detect2Dep($dep, $pname, 'required', $params);
                   17446:                         if (is_array($ret)) {
                   17447:                             $this->_downloadDeps[] = $ret;
                   17448:                         } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
                   17449:                             $this->_downloader->log(0, $ret->getMessage());
                   17450:                         }
                   17451:                     }
                   17452:                 } else {
                   17453:                     $dep = $deps['required'][$packagetype];
                   17454:                     if (!isset($dep['conflicts'])) {
                   17455:                         // skip any package that this package conflicts with
                   17456:                         $ret = $this->_detect2Dep($dep, $pname, 'required', $params);
                   17457:                         if (is_array($ret)) {
                   17458:                             $this->_downloadDeps[] = $ret;
                   17459:                         } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
                   17460:                             $this->_downloader->log(0, $ret->getMessage());
                   17461:                         }
                   17462:                     }
                   17463:                 }
                   17464:             }
                   17465: 
                   17466:             // get optional dependency group, if any
                   17467:             if (isset($deps['optional'][$packagetype])) {
                   17468:                 $skipnames = array();
                   17469:                 if (!isset($deps['optional'][$packagetype][0])) {
                   17470:                     $deps['optional'][$packagetype] = array($deps['optional'][$packagetype]);
                   17471:                 }
                   17472: 
                   17473:                 foreach ($deps['optional'][$packagetype] as $dep) {
                   17474:                     $skip = false;
                   17475:                     if (!isset($options['alldeps'])) {
                   17476:                         $dep['package'] = $dep['name'];
                   17477:                         if (!isset($options['soft'])) {
                   17478:                             $this->_downloader->log(3, 'Notice: package "' .
                   17479:                               $this->_registry->parsedPackageNameToString($this->getParsedPackage(),
                   17480:                                     true) . '" optional dependency "' .
                   17481:                                 $this->_registry->parsedPackageNameToString(array('package' =>
                   17482:                                     $dep['name'], 'channel' => 'pear.php.net'), true) .
                   17483:                                 '" will not be automatically downloaded');
                   17484:                         }
                   17485:                         $skipnames[] = $this->_registry->parsedPackageNameToString($dep, true);
                   17486:                         $skip = true;
                   17487:                         unset($dep['package']);
                   17488:                     }
                   17489: 
                   17490:                     $ret = $this->_detect2Dep($dep, $pname, 'optional', $params);
                   17491:                     if (PEAR::isError($ret) && !isset($options['soft'])) {
                   17492:                         $this->_downloader->log(0, $ret->getMessage());
                   17493:                     }
                   17494: 
                   17495:                     if (!$ret) {
                   17496:                         $dep['package'] = $dep['name'];
                   17497:                         $skip = count($skipnames) ?
                   17498:                             $skipnames[count($skipnames) - 1] : '';
                   17499:                         if ($skip ==
                   17500:                               $this->_registry->parsedPackageNameToString($dep, true)) {
                   17501:                             array_pop($skipnames);
                   17502:                         }
                   17503:                     }
                   17504: 
                   17505:                     if (!$skip && is_array($ret)) {
                   17506:                         $this->_downloadDeps[] = $ret;
                   17507:                     }
                   17508:                 }
                   17509: 
                   17510:                 if (count($skipnames)) {
                   17511:                     if (!isset($options['soft'])) {
                   17512:                         $this->_downloader->log(1, 'Did not download optional dependencies: ' .
                   17513:                             implode(', ', $skipnames) .
                   17514:                             ', use --alldeps to download automatically');
                   17515:                     }
                   17516:                 }
                   17517:             }
                   17518: 
                   17519:             // get requested dependency group, if any
                   17520:             $groupname = $this->getGroup();
                   17521:             $explicit  = $this->_explicitGroup;
                   17522:             if (!$groupname) {
                   17523:                 if (!$this->canDefault()) {
                   17524:                     continue;
                   17525:                 }
                   17526: 
                   17527:                 $groupname = 'default'; // try the default dependency group
                   17528:             }
                   17529: 
                   17530:             if ($groupnotfound) {
                   17531:                 continue;
                   17532:             }
                   17533: 
                   17534:             if (isset($deps['group'])) {
                   17535:                 if (isset($deps['group']['attribs'])) {
                   17536:                     if (strtolower($deps['group']['attribs']['name']) == strtolower($groupname)) {
                   17537:                         $group = $deps['group'];
                   17538:                     } elseif ($explicit) {
                   17539:                         if (!isset($options['soft'])) {
                   17540:                             $this->_downloader->log(0, 'Warning: package "' .
                   17541:                                 $this->_registry->parsedPackageNameToString($pname, true) .
                   17542:                                 '" has no dependency ' . 'group named "' . $groupname . '"');
                   17543:                         }
                   17544: 
                   17545:                         $groupnotfound = true;
                   17546:                         continue;
                   17547:                     }
                   17548:                 } else {
                   17549:                     $found = false;
                   17550:                     foreach ($deps['group'] as $group) {
                   17551:                         if (strtolower($group['attribs']['name']) == strtolower($groupname)) {
                   17552:                             $found = true;
                   17553:                             break;
                   17554:                         }
                   17555:                     }
                   17556: 
                   17557:                     if (!$found) {
                   17558:                         if ($explicit) {
                   17559:                             if (!isset($options['soft'])) {
                   17560:                                 $this->_downloader->log(0, 'Warning: package "' .
                   17561:                                     $this->_registry->parsedPackageNameToString($pname, true) .
                   17562:                                     '" has no dependency ' . 'group named "' . $groupname . '"');
                   17563:                             }
                   17564:                         }
                   17565: 
                   17566:                         $groupnotfound = true;
                   17567:                         continue;
                   17568:                     }
                   17569:                 }
                   17570:             }
                   17571: 
                   17572:             if (isset($group) && isset($group[$packagetype])) {
                   17573:                 if (isset($group[$packagetype][0])) {
                   17574:                     foreach ($group[$packagetype] as $dep) {
                   17575:                         $ret = $this->_detect2Dep($dep, $pname, 'dependency group "' .
                   17576:                             $group['attribs']['name'] . '"', $params);
                   17577:                         if (is_array($ret)) {
                   17578:                             $this->_downloadDeps[] = $ret;
                   17579:                         } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
                   17580:                             $this->_downloader->log(0, $ret->getMessage());
                   17581:                         }
                   17582:                     }
                   17583:                 } else {
                   17584:                     $ret = $this->_detect2Dep($group[$packagetype], $pname,
                   17585:                         'dependency group "' .
                   17586:                         $group['attribs']['name'] . '"', $params);
                   17587:                     if (is_array($ret)) {
                   17588:                         $this->_downloadDeps[] = $ret;
                   17589:                     } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
                   17590:                         $this->_downloader->log(0, $ret->getMessage());
                   17591:                     }
                   17592:                 }
                   17593:             }
                   17594:         }
                   17595:     }
                   17596: 
                   17597:     function _detect2Dep($dep, $pname, $group, $params)
                   17598:     {
                   17599:         if (isset($dep['conflicts'])) {
                   17600:             return true;
                   17601:         }
                   17602: 
                   17603:         $options = $this->_downloader->getOptions();
                   17604:         if (isset($dep['uri'])) {
                   17605:             return array('uri' => $dep['uri'], 'dep' => $dep);;
                   17606:         }
                   17607: 
                   17608:         $testdep = $dep;
                   17609:         $testdep['package'] = $dep['name'];
                   17610:         if (PEAR_Downloader_Package::willDownload($testdep, $params)) {
                   17611:             $dep['package'] = $dep['name'];
                   17612:             if (!isset($options['soft'])) {
                   17613:                 $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group .
                   17614:                     ' dependency "' .
                   17615:                     $this->_registry->parsedPackageNameToString($dep, true) .
                   17616:                     '", will be installed');
                   17617:             }
                   17618:             return false;
                   17619:         }
                   17620: 
                   17621:         $options = $this->_downloader->getOptions();
                   17622:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   17623:         if ($this->_explicitState) {
                   17624:             $pname['state'] = $this->_explicitState;
                   17625:         }
                   17626: 
                   17627:         $url = $this->_downloader->_getDepPackageDownloadUrl($dep, $pname);
                   17628:         if (PEAR::isError($url)) {
                   17629:             PEAR::popErrorHandling();
                   17630:             return $url;
                   17631:         }
                   17632: 
                   17633:         $dep['package'] = $dep['name'];
                   17634:         $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params, $group == 'optional' &&
                   17635:             !isset($options['alldeps']), true);
                   17636:         PEAR::popErrorHandling();
                   17637:         if (PEAR::isError($ret)) {
                   17638:             if (!isset($options['soft'])) {
                   17639:                 $this->_downloader->log(0, $ret->getMessage());
                   17640:             }
                   17641: 
                   17642:             return false;
                   17643:         }
                   17644: 
                   17645:         // check to see if a dep is already installed and is the same or newer
                   17646:         if (!isset($dep['min']) && !isset($dep['max']) && !isset($dep['recommended'])) {
                   17647:             $oper = 'has';
                   17648:         } else {
                   17649:             $oper = 'gt';
                   17650:         }
                   17651: 
                   17652:         // do not try to move this before getDepPackageDownloadURL
                   17653:         // we can't determine whether upgrade is necessary until we know what
                   17654:         // version would be downloaded
                   17655:         if (!isset($options['force']) && $this->isInstalled($ret, $oper)) {
                   17656:             $version = $this->_installRegistry->packageInfo($dep['name'], 'version', $dep['channel']);
                   17657:             $dep['package'] = $dep['name'];
                   17658:             if (!isset($options['soft'])) {
                   17659:                 $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group .
                   17660:                     ' dependency "' .
                   17661:                 $this->_registry->parsedPackageNameToString($dep, true) .
                   17662:                     '" version ' . $url['version'] . ', already installed as version ' .
                   17663:                     $version);
                   17664:             }
                   17665: 
                   17666:             return false;
                   17667:         }
                   17668: 
                   17669:         if (isset($dep['nodefault'])) {
                   17670:             $ret['nodefault'] = true;
                   17671:         }
                   17672: 
                   17673:         return $ret;
                   17674:     }
                   17675: 
                   17676:     function _detect1($deps, $pname, $options, $params)
                   17677:     {
                   17678:         $this->_downloadDeps = array();
                   17679:         $skipnames = array();
                   17680:         foreach ($deps as $dep) {
                   17681:             $nodownload = false;
                   17682:             if (isset ($dep['type']) && $dep['type'] === 'pkg') {
                   17683:                 $dep['channel'] = 'pear.php.net';
                   17684:                 $dep['package'] = $dep['name'];
                   17685:                 switch ($dep['rel']) {
                   17686:                     case 'not' :
                   17687:                         continue 2;
                   17688:                     case 'ge' :
                   17689:                     case 'eq' :
                   17690:                     case 'gt' :
                   17691:                     case 'has' :
                   17692:                         $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
                   17693:                             'required' :
                   17694:                             'optional';
                   17695:                         if (PEAR_Downloader_Package::willDownload($dep, $params)) {
                   17696:                             $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group
                   17697:                                 . ' dependency "' .
                   17698:                                 $this->_registry->parsedPackageNameToString($dep, true) .
                   17699:                                 '", will be installed');
                   17700:                             continue 2;
                   17701:                         }
                   17702:                         $fakedp = new PEAR_PackageFile_v1;
                   17703:                         $fakedp->setPackage($dep['name']);
                   17704:                         // skip internet check if we are not upgrading (bug #5810)
                   17705:                         if (!isset($options['upgrade']) && $this->isInstalled(
                   17706:                               $fakedp, $dep['rel'])) {
                   17707:                             $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group
                   17708:                                 . ' dependency "' .
                   17709:                                 $this->_registry->parsedPackageNameToString($dep, true) .
                   17710:                                 '", is already installed');
                   17711:                             continue 2;
                   17712:                         }
                   17713:                 }
                   17714: 
                   17715:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   17716:                 if ($this->_explicitState) {
                   17717:                     $pname['state'] = $this->_explicitState;
                   17718:                 }
                   17719: 
                   17720:                 $url = $this->_downloader->_getDepPackageDownloadUrl($dep, $pname);
                   17721:                 $chan = 'pear.php.net';
                   17722:                 if (PEAR::isError($url)) {
                   17723:                     // check to see if this is a pecl package that has jumped
                   17724:                     // from pear.php.net to pecl.php.net channel
                   17725:                     if (!class_exists('PEAR_Dependency2')) {
                   17726:                         require_once 'PEAR/Dependency2.php';
                   17727:                     }
                   17728: 
                   17729:                     $newdep = PEAR_Dependency2::normalizeDep($dep);
                   17730:                     $newdep = $newdep[0];
                   17731:                     $newdep['channel'] = 'pecl.php.net';
                   17732:                     $chan = 'pecl.php.net';
                   17733:                     $url = $this->_downloader->_getDepPackageDownloadUrl($newdep, $pname);
                   17734:                     $obj = &$this->_installRegistry->getPackage($dep['name']);
                   17735:                     if (PEAR::isError($url)) {
                   17736:                         PEAR::popErrorHandling();
                   17737:                         if ($obj !== null && $this->isInstalled($obj, $dep['rel'])) {
                   17738:                             $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
                   17739:                                 'required' :
                   17740:                                 'optional';
                   17741:                             $dep['package'] = $dep['name'];
                   17742:                             if (!isset($options['soft'])) {
                   17743:                                 $this->_downloader->log(3, $this->getShortName() .
                   17744:                                     ': Skipping ' . $group . ' dependency "' .
                   17745:                                     $this->_registry->parsedPackageNameToString($dep, true) .
                   17746:                                     '", already installed as version ' . $obj->getVersion());
                   17747:                             }
                   17748:                             $skip = count($skipnames) ?
                   17749:                                 $skipnames[count($skipnames) - 1] : '';
                   17750:                             if ($skip ==
                   17751:                                   $this->_registry->parsedPackageNameToString($dep, true)) {
                   17752:                                 array_pop($skipnames);
                   17753:                             }
                   17754:                             continue;
                   17755:                         } else {
                   17756:                             if (isset($dep['optional']) && $dep['optional'] == 'yes') {
                   17757:                                 $this->_downloader->log(2, $this->getShortName() .
                   17758:                                     ': Skipping optional dependency "' .
                   17759:                                     $this->_registry->parsedPackageNameToString($dep, true) .
                   17760:                                     '", no releases exist');
                   17761:                                 continue;
                   17762:                             } else {
                   17763:                                 return $url;
                   17764:                             }
                   17765:                         }
                   17766:                     }
                   17767:                 }
                   17768: 
                   17769:                 PEAR::popErrorHandling();
                   17770:                 if (!isset($options['alldeps'])) {
                   17771:                     if (isset($dep['optional']) && $dep['optional'] == 'yes') {
                   17772:                         if (!isset($options['soft'])) {
                   17773:                             $this->_downloader->log(3, 'Notice: package "' .
                   17774:                                 $this->getShortName() .
                   17775:                                 '" optional dependency "' .
                   17776:                                 $this->_registry->parsedPackageNameToString(
                   17777:                                     array('channel' => $chan, 'package' =>
                   17778:                                     $dep['name']), true) .
                   17779:                                 '" will not be automatically downloaded');
                   17780:                         }
                   17781:                         $skipnames[] = $this->_registry->parsedPackageNameToString(
                   17782:                                 array('channel' => $chan, 'package' =>
                   17783:                                 $dep['name']), true);
                   17784:                         $nodownload = true;
                   17785:                     }
                   17786:                 }
                   17787: 
                   17788:                 if (!isset($options['alldeps']) && !isset($options['onlyreqdeps'])) {
                   17789:                     if (!isset($dep['optional']) || $dep['optional'] == 'no') {
                   17790:                         if (!isset($options['soft'])) {
                   17791:                             $this->_downloader->log(3, 'Notice: package "' .
                   17792:                                 $this->getShortName() .
                   17793:                                 '" required dependency "' .
                   17794:                                 $this->_registry->parsedPackageNameToString(
                   17795:                                     array('channel' => $chan, 'package' =>
                   17796:                                     $dep['name']), true) .
                   17797:                                 '" will not be automatically downloaded');
                   17798:                         }
                   17799:                         $skipnames[] = $this->_registry->parsedPackageNameToString(
                   17800:                                 array('channel' => $chan, 'package' =>
                   17801:                                 $dep['name']), true);
                   17802:                         $nodownload = true;
                   17803:                     }
                   17804:                 }
                   17805: 
                   17806:                 // check to see if a dep is already installed
                   17807:                 // do not try to move this before getDepPackageDownloadURL
                   17808:                 // we can't determine whether upgrade is necessary until we know what
                   17809:                 // version would be downloaded
                   17810:                 if (!isset($options['force']) && $this->isInstalled(
                   17811:                         $url, $dep['rel'])) {
                   17812:                     $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
                   17813:                         'required' :
                   17814:                         'optional';
                   17815:                     $dep['package'] = $dep['name'];
                   17816:                     if (isset($newdep)) {
                   17817:                         $version = $this->_installRegistry->packageInfo($newdep['name'], 'version', $newdep['channel']);
                   17818:                     } else {
                   17819:                         $version = $this->_installRegistry->packageInfo($dep['name'], 'version');
                   17820:                     }
                   17821: 
                   17822:                     $dep['version'] = $url['version'];
                   17823:                     if (!isset($options['soft'])) {
                   17824:                         $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group .
                   17825:                             ' dependency "' .
                   17826:                             $this->_registry->parsedPackageNameToString($dep, true) .
                   17827:                             '", already installed as version ' . $version);
                   17828:                     }
                   17829: 
                   17830:                     $skip = count($skipnames) ?
                   17831:                         $skipnames[count($skipnames) - 1] : '';
                   17832:                     if ($skip ==
                   17833:                           $this->_registry->parsedPackageNameToString($dep, true)) {
                   17834:                         array_pop($skipnames);
                   17835:                     }
                   17836: 
                   17837:                     continue;
                   17838:                 }
                   17839: 
                   17840:                 if ($nodownload) {
                   17841:                     continue;
                   17842:                 }
                   17843: 
                   17844:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   17845:                 if (isset($newdep)) {
                   17846:                     $dep = $newdep;
                   17847:                 }
                   17848: 
                   17849:                 $dep['package'] = $dep['name'];
                   17850:                 $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params,
                   17851:                     isset($dep['optional']) && $dep['optional'] == 'yes' &&
                   17852:                     !isset($options['alldeps']), true);
                   17853:                 PEAR::popErrorHandling();
                   17854:                 if (PEAR::isError($ret)) {
                   17855:                     if (!isset($options['soft'])) {
                   17856:                         $this->_downloader->log(0, $ret->getMessage());
                   17857:                     }
                   17858:                     continue;
                   17859:                 }
                   17860: 
                   17861:                 $this->_downloadDeps[] = $ret;
                   17862:             }
                   17863:         }
                   17864: 
                   17865:         if (count($skipnames)) {
                   17866:             if (!isset($options['soft'])) {
                   17867:                 $this->_downloader->log(1, 'Did not download dependencies: ' .
                   17868:                     implode(', ', $skipnames) .
                   17869:                     ', use --alldeps or --onlyreqdeps to download automatically');
                   17870:             }
                   17871:         }
                   17872:     }
                   17873: 
                   17874:     function setDownloadURL($pkg)
                   17875:     {
                   17876:         $this->_downloadURL = $pkg;
                   17877:     }
                   17878: 
                   17879:     /**
                   17880:      * Set the package.xml object for this downloaded package
                   17881:      *
                   17882:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 $pkg
                   17883:      */
                   17884:     function setPackageFile(&$pkg)
                   17885:     {
                   17886:         $this->_packagefile = &$pkg;
                   17887:     }
                   17888: 
                   17889:     function getShortName()
                   17890:     {
                   17891:         return $this->_registry->parsedPackageNameToString(array('channel' => $this->getChannel(),
                   17892:             'package' => $this->getPackage()), true);
                   17893:     }
                   17894: 
                   17895:     function getParsedPackage()
                   17896:     {
                   17897:         if (isset($this->_packagefile) || isset($this->_parsedname)) {
                   17898:             return array('channel' => $this->getChannel(),
                   17899:                 'package' => $this->getPackage(),
                   17900:                 'version' => $this->getVersion());
                   17901:         }
                   17902: 
                   17903:         return false;
                   17904:     }
                   17905: 
                   17906:     function getDownloadURL()
                   17907:     {
                   17908:         return $this->_downloadURL;
                   17909:     }
                   17910: 
                   17911:     function canDefault()
                   17912:     {
                   17913:         if (isset($this->_downloadURL) && isset($this->_downloadURL['nodefault'])) {
                   17914:             return false;
                   17915:         }
                   17916: 
                   17917:         return true;
                   17918:     }
                   17919: 
                   17920:     function getPackage()
                   17921:     {
                   17922:         if (isset($this->_packagefile)) {
                   17923:             return $this->_packagefile->getPackage();
                   17924:         } elseif (isset($this->_downloadURL['info'])) {
                   17925:             return $this->_downloadURL['info']->getPackage();
                   17926:         }
                   17927: 
                   17928:         return false;
                   17929:     }
                   17930: 
                   17931:     /**
                   17932:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   17933:      */
                   17934:     function isSubpackage(&$pf)
                   17935:     {
                   17936:         if (isset($this->_packagefile)) {
                   17937:             return $this->_packagefile->isSubpackage($pf);
                   17938:         } elseif (isset($this->_downloadURL['info'])) {
                   17939:             return $this->_downloadURL['info']->isSubpackage($pf);
                   17940:         }
                   17941: 
                   17942:         return false;
                   17943:     }
                   17944: 
                   17945:     function getPackageType()
                   17946:     {
                   17947:         if (isset($this->_packagefile)) {
                   17948:             return $this->_packagefile->getPackageType();
                   17949:         } elseif (isset($this->_downloadURL['info'])) {
                   17950:             return $this->_downloadURL['info']->getPackageType();
                   17951:         }
                   17952: 
                   17953:         return false;
                   17954:     }
                   17955: 
                   17956:     function isBundle()
                   17957:     {
                   17958:         if (isset($this->_packagefile)) {
                   17959:             return $this->_packagefile->getPackageType() == 'bundle';
                   17960:         }
                   17961: 
                   17962:         return false;
                   17963:     }
                   17964: 
                   17965:     function getPackageXmlVersion()
                   17966:     {
                   17967:         if (isset($this->_packagefile)) {
                   17968:             return $this->_packagefile->getPackagexmlVersion();
                   17969:         } elseif (isset($this->_downloadURL['info'])) {
                   17970:             return $this->_downloadURL['info']->getPackagexmlVersion();
                   17971:         }
                   17972: 
                   17973:         return '1.0';
                   17974:     }
                   17975: 
                   17976:     function getChannel()
                   17977:     {
                   17978:         if (isset($this->_packagefile)) {
                   17979:             return $this->_packagefile->getChannel();
                   17980:         } elseif (isset($this->_downloadURL['info'])) {
                   17981:             return $this->_downloadURL['info']->getChannel();
                   17982:         }
                   17983: 
                   17984:         return false;
                   17985:     }
                   17986: 
                   17987:     function getURI()
                   17988:     {
                   17989:         if (isset($this->_packagefile)) {
                   17990:             return $this->_packagefile->getURI();
                   17991:         } elseif (isset($this->_downloadURL['info'])) {
                   17992:             return $this->_downloadURL['info']->getURI();
                   17993:         }
                   17994: 
                   17995:         return false;
                   17996:     }
                   17997: 
                   17998:     function getVersion()
                   17999:     {
                   18000:         if (isset($this->_packagefile)) {
                   18001:             return $this->_packagefile->getVersion();
                   18002:         } elseif (isset($this->_downloadURL['version'])) {
                   18003:             return $this->_downloadURL['version'];
                   18004:         }
                   18005: 
                   18006:         return false;
                   18007:     }
                   18008: 
                   18009:     function isCompatible($pf)
                   18010:     {
                   18011:         if (isset($this->_packagefile)) {
                   18012:             return $this->_packagefile->isCompatible($pf);
                   18013:         } elseif (isset($this->_downloadURL['info'])) {
                   18014:             return $this->_downloadURL['info']->isCompatible($pf);
                   18015:         }
                   18016: 
                   18017:         return true;
                   18018:     }
                   18019: 
                   18020:     function setGroup($group)
                   18021:     {
                   18022:         $this->_parsedname['group'] = $group;
                   18023:     }
                   18024: 
                   18025:     function getGroup()
                   18026:     {
                   18027:         if (isset($this->_parsedname['group'])) {
                   18028:             return $this->_parsedname['group'];
                   18029:         }
                   18030: 
                   18031:         return '';
                   18032:     }
                   18033: 
                   18034:     function isExtension($name)
                   18035:     {
                   18036:         if (isset($this->_packagefile)) {
                   18037:             return $this->_packagefile->isExtension($name);
                   18038:         } elseif (isset($this->_downloadURL['info'])) {
                   18039:             if ($this->_downloadURL['info']->getPackagexmlVersion() == '2.0') {
                   18040:                 return $this->_downloadURL['info']->getProvidesExtension() == $name;
                   18041:             }
                   18042: 
                   18043:             return false;
                   18044:         }
                   18045: 
                   18046:         return false;
                   18047:     }
                   18048: 
                   18049:     function getDeps()
                   18050:     {
                   18051:         if (isset($this->_packagefile)) {
                   18052:             $ver = $this->_packagefile->getPackagexmlVersion();
                   18053:             if (version_compare($ver, '2.0', '>=')) {
                   18054:                 return $this->_packagefile->getDeps(true);
                   18055:             }
                   18056: 
                   18057:             return $this->_packagefile->getDeps();
                   18058:         } elseif (isset($this->_downloadURL['info'])) {
                   18059:             $ver = $this->_downloadURL['info']->getPackagexmlVersion();
                   18060:             if (version_compare($ver, '2.0', '>=')) {
                   18061:                 return $this->_downloadURL['info']->getDeps(true);
                   18062:             }
                   18063: 
                   18064:             return $this->_downloadURL['info']->getDeps();
                   18065:         }
                   18066: 
                   18067:         return array();
                   18068:     }
                   18069: 
                   18070:     /**
                   18071:      * @param array Parsed array from {@link PEAR_Registry::parsePackageName()} or a dependency
                   18072:      *                     returned from getDepDownloadURL()
                   18073:      */
                   18074:     function isEqual($param)
                   18075:     {
                   18076:         if (is_object($param)) {
                   18077:             $channel = $param->getChannel();
                   18078:             $package = $param->getPackage();
                   18079:             if ($param->getURI()) {
                   18080:                 $param = array(
                   18081:                     'channel' => $param->getChannel(),
                   18082:                     'package' => $param->getPackage(),
                   18083:                     'version' => $param->getVersion(),
                   18084:                     'uri' => $param->getURI(),
                   18085:                 );
                   18086:             } else {
                   18087:                 $param = array(
                   18088:                     'channel' => $param->getChannel(),
                   18089:                     'package' => $param->getPackage(),
                   18090:                     'version' => $param->getVersion(),
                   18091:                 );
                   18092:             }
                   18093:         } else {
                   18094:             if (isset($param['uri'])) {
                   18095:                 if ($this->getChannel() != '__uri') {
                   18096:                     return false;
                   18097:                 }
                   18098:                 return $param['uri'] == $this->getURI();
                   18099:             }
                   18100: 
                   18101:             $package = isset($param['package']) ? $param['package'] : $param['info']->getPackage();
                   18102:             $channel = isset($param['channel']) ? $param['channel'] : $param['info']->getChannel();
                   18103:             if (isset($param['rel'])) {
                   18104:                 if (!class_exists('PEAR_Dependency2')) {
                   18105:                     require_once 'PEAR/Dependency2.php';
                   18106:                 }
                   18107: 
                   18108:                 $newdep = PEAR_Dependency2::normalizeDep($param);
                   18109:                 $newdep = $newdep[0];
                   18110:             } elseif (isset($param['min'])) {
                   18111:                 $newdep = $param;
                   18112:             }
                   18113:         }
                   18114: 
                   18115:         if (isset($newdep)) {
                   18116:             if (!isset($newdep['min'])) {
                   18117:                 $newdep['min'] = '0';
                   18118:             }
                   18119: 
                   18120:             if (!isset($newdep['max'])) {
                   18121:                 $newdep['max'] = '100000000000000000000';
                   18122:             }
                   18123: 
                   18124:             // use magic to support pecl packages suddenly jumping to the pecl channel
                   18125:             // we need to support both dependency possibilities
                   18126:             if ($channel == 'pear.php.net' && $this->getChannel() == 'pecl.php.net') {
                   18127:                 if ($package == $this->getPackage()) {
                   18128:                     $channel = 'pecl.php.net';
                   18129:                 }
                   18130:             }
                   18131:             if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') {
                   18132:                 if ($package == $this->getPackage()) {
                   18133:                     $channel = 'pear.php.net';
                   18134:                 }
                   18135:             }
                   18136: 
                   18137:             return (strtolower($package) == strtolower($this->getPackage()) &&
                   18138:                 $channel == $this->getChannel() &&
                   18139:                 version_compare($newdep['min'], $this->getVersion(), '<=') &&
                   18140:                 version_compare($newdep['max'], $this->getVersion(), '>='));
                   18141:         }
                   18142: 
                   18143:         // use magic to support pecl packages suddenly jumping to the pecl channel
                   18144:         if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') {
                   18145:             if (strtolower($package) == strtolower($this->getPackage())) {
                   18146:                 $channel = 'pear.php.net';
                   18147:             }
                   18148:         }
                   18149: 
                   18150:         if (isset($param['version'])) {
                   18151:             return (strtolower($package) == strtolower($this->getPackage()) &&
                   18152:                 $channel == $this->getChannel() &&
                   18153:                 $param['version'] == $this->getVersion());
                   18154:         }
                   18155: 
                   18156:         return strtolower($package) == strtolower($this->getPackage()) &&
                   18157:             $channel == $this->getChannel();
                   18158:     }
                   18159: 
                   18160:     function isInstalled($dep, $oper = '==')
                   18161:     {
                   18162:         if (!$dep) {
                   18163:             return false;
                   18164:         }
                   18165: 
                   18166:         if ($oper != 'ge' && $oper != 'gt' && $oper != 'has' && $oper != '==') {
                   18167:             return false;
                   18168:         }
                   18169: 
                   18170:         if (is_object($dep)) {
                   18171:             $package = $dep->getPackage();
                   18172:             $channel = $dep->getChannel();
                   18173:             if ($dep->getURI()) {
                   18174:                 $dep = array(
                   18175:                     'uri' => $dep->getURI(),
                   18176:                     'version' => $dep->getVersion(),
                   18177:                 );
                   18178:             } else {
                   18179:                 $dep = array(
                   18180:                     'version' => $dep->getVersion(),
                   18181:                 );
                   18182:             }
                   18183:         } else {
                   18184:             if (isset($dep['uri'])) {
                   18185:                 $channel = '__uri';
                   18186:                 $package = $dep['dep']['name'];
                   18187:             } else {
                   18188:                 $channel = $dep['info']->getChannel();
                   18189:                 $package = $dep['info']->getPackage();
                   18190:             }
                   18191:         }
                   18192: 
                   18193:         $options = $this->_downloader->getOptions();
                   18194:         $test    = $this->_installRegistry->packageExists($package, $channel);
                   18195:         if (!$test && $channel == 'pecl.php.net') {
                   18196:             // do magic to allow upgrading from old pecl packages to new ones
                   18197:             $test = $this->_installRegistry->packageExists($package, 'pear.php.net');
                   18198:             $channel = 'pear.php.net';
                   18199:         }
                   18200: 
                   18201:         if ($test) {
                   18202:             if (isset($dep['uri'])) {
                   18203:                 if ($this->_installRegistry->packageInfo($package, 'uri', '__uri') == $dep['uri']) {
                   18204:                     return true;
                   18205:                 }
                   18206:             }
                   18207: 
                   18208:             if (isset($options['upgrade'])) {
                   18209:                 $packageVersion = $this->_installRegistry->packageInfo($package, 'version', $channel);
                   18210:                 if (version_compare($packageVersion, $dep['version'], '>=')) {
                   18211:                     return true;
                   18212:                 }
                   18213: 
                   18214:                 return false;
                   18215:             }
                   18216: 
                   18217:             return true;
                   18218:         }
                   18219: 
                   18220:         return false;
                   18221:     }
                   18222: 
                   18223:     /**
                   18224:      * Detect duplicate package names with differing versions
                   18225:      *
                   18226:      * If a user requests to install Date 1.4.6 and Date 1.4.7,
                   18227:      * for instance, this is a logic error.  This method
                   18228:      * detects this situation.
                   18229:      *
                   18230:      * @param array $params array of PEAR_Downloader_Package objects
                   18231:      * @param array $errorparams empty array
                   18232:      * @return array array of stupid duplicated packages in PEAR_Downloader_Package obejcts
                   18233:      */
                   18234:     function detectStupidDuplicates($params, &$errorparams)
                   18235:     {
                   18236:         $existing = array();
                   18237:         foreach ($params as $i => $param) {
                   18238:             $package = $param->getPackage();
                   18239:             $channel = $param->getChannel();
                   18240:             $group   = $param->getGroup();
                   18241:             if (!isset($existing[$channel . '/' . $package])) {
                   18242:                 $existing[$channel . '/' . $package] = array();
                   18243:             }
                   18244: 
                   18245:             if (!isset($existing[$channel . '/' . $package][$group])) {
                   18246:                 $existing[$channel . '/' . $package][$group] = array();
                   18247:             }
                   18248: 
                   18249:             $existing[$channel . '/' . $package][$group][] = $i;
                   18250:         }
                   18251: 
                   18252:         $indices = array();
                   18253:         foreach ($existing as $package => $groups) {
                   18254:             foreach ($groups as $group => $dupes) {
                   18255:                 if (count($dupes) > 1) {
                   18256:                     $indices = $indices + $dupes;
                   18257:                 }
                   18258:             }
                   18259:         }
                   18260: 
                   18261:         $indices = array_unique($indices);
                   18262:         foreach ($indices as $index) {
                   18263:             $errorparams[] = $params[$index];
                   18264:         }
                   18265: 
                   18266:         return count($errorparams);
                   18267:     }
                   18268: 
                   18269:     /**
                   18270:      * @param array
                   18271:      * @param bool ignore install groups - for final removal of dupe packages
                   18272:      * @static
                   18273:      */
                   18274:     function removeDuplicates(&$params, $ignoreGroups = false)
                   18275:     {
                   18276:         $pnames = array();
                   18277:         foreach ($params as $i => $param) {
                   18278:             if (!$param) {
                   18279:                 continue;
                   18280:             }
                   18281: 
                   18282:             if ($param->getPackage()) {
                   18283:                 $group = $ignoreGroups ? '' : $param->getGroup();
                   18284:                 $pnames[$i] = $param->getChannel() . '/' .
                   18285:                     $param->getPackage() . '-' . $param->getVersion() . '#' . $group;
                   18286:             }
                   18287:         }
                   18288: 
                   18289:         $pnames = array_unique($pnames);
                   18290:         $unset  = array_diff(array_keys($params), array_keys($pnames));
                   18291:         $testp  = array_flip($pnames);
                   18292:         foreach ($params as $i => $param) {
                   18293:             if (!$param) {
                   18294:                 $unset[] = $i;
                   18295:                 continue;
                   18296:             }
                   18297: 
                   18298:             if (!is_a($param, 'PEAR_Downloader_Package')) {
                   18299:                 $unset[] = $i;
                   18300:                 continue;
                   18301:             }
                   18302: 
                   18303:             $group = $ignoreGroups ? '' : $param->getGroup();
                   18304:             if (!isset($testp[$param->getChannel() . '/' . $param->getPackage() . '-' .
                   18305:                   $param->getVersion() . '#' . $group])) {
                   18306:                 $unset[] = $i;
                   18307:             }
                   18308:         }
                   18309: 
                   18310:         foreach ($unset as $i) {
                   18311:             unset($params[$i]);
                   18312:         }
                   18313: 
                   18314:         $ret = array();
                   18315:         foreach ($params as $i => $param) {
                   18316:             $ret[] = &$params[$i];
                   18317:         }
                   18318: 
                   18319:         $params = array();
                   18320:         foreach ($ret as $i => $param) {
                   18321:             $params[] = &$ret[$i];
                   18322:         }
                   18323:     }
                   18324: 
                   18325:     function explicitState()
                   18326:     {
                   18327:         return $this->_explicitState;
                   18328:     }
                   18329: 
                   18330:     function setExplicitState($s)
                   18331:     {
                   18332:         $this->_explicitState = $s;
                   18333:     }
                   18334: 
                   18335:     /**
                   18336:      * @static
                   18337:      */
                   18338:     function mergeDependencies(&$params)
                   18339:     {
                   18340:         $bundles = $newparams = array();
                   18341:         foreach ($params as $i => $param) {
                   18342:             if (!$param->isBundle()) {
                   18343:                 continue;
                   18344:             }
                   18345: 
                   18346:             $bundles[] = $i;
                   18347:             $pf = &$param->getPackageFile();
                   18348:             $newdeps = array();
                   18349:             $contents = $pf->getBundledPackages();
                   18350:             if (!is_array($contents)) {
                   18351:                 $contents = array($contents);
                   18352:             }
                   18353: 
                   18354:             foreach ($contents as $file) {
                   18355:                 $filecontents = $pf->getFileContents($file);
                   18356:                 $dl = &$param->getDownloader();
                   18357:                 $options = $dl->getOptions();
                   18358:                 if (PEAR::isError($dir = $dl->getDownloadDir())) {
                   18359:                     return $dir;
                   18360:                 }
                   18361: 
                   18362:                 $fp = @fopen($dir . DIRECTORY_SEPARATOR . $file, 'wb');
                   18363:                 if (!$fp) {
                   18364:                     continue;
                   18365:                 }
                   18366: 
                   18367:                 // FIXME do symlink check
                   18368: 
                   18369:                 fwrite($fp, $filecontents, strlen($filecontents));
                   18370:                 fclose($fp);
                   18371:                 if ($s = $params[$i]->explicitState()) {
                   18372:                     $obj->setExplicitState($s);
                   18373:                 }
                   18374: 
                   18375:                 $obj = &new PEAR_Downloader_Package($params[$i]->getDownloader());
                   18376:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   18377:                 if (PEAR::isError($dir = $dl->getDownloadDir())) {
                   18378:                     PEAR::popErrorHandling();
                   18379:                     return $dir;
                   18380:                 }
                   18381: 
                   18382:                 $e = $obj->_fromFile($a = $dir . DIRECTORY_SEPARATOR . $file);
                   18383:                 PEAR::popErrorHandling();
                   18384:                 if (PEAR::isError($e)) {
                   18385:                     if (!isset($options['soft'])) {
                   18386:                         $dl->log(0, $e->getMessage());
                   18387:                     }
                   18388:                     continue;
                   18389:                 }
                   18390: 
                   18391:                 $j = &$obj;
                   18392:                 if (!PEAR_Downloader_Package::willDownload($j,
                   18393:                       array_merge($params, $newparams)) && !$param->isInstalled($j)) {
                   18394:                     $newparams[] = &$j;
                   18395:                 }
                   18396:             }
                   18397:         }
                   18398: 
                   18399:         foreach ($bundles as $i) {
                   18400:             unset($params[$i]); // remove bundles - only their contents matter for installation
                   18401:         }
                   18402: 
                   18403:         PEAR_Downloader_Package::removeDuplicates($params); // strip any unset indices
                   18404:         if (count($newparams)) { // add in bundled packages for install
                   18405:             foreach ($newparams as $i => $unused) {
                   18406:                 $params[] = &$newparams[$i];
                   18407:             }
                   18408:             $newparams = array();
                   18409:         }
                   18410: 
                   18411:         foreach ($params as $i => $param) {
                   18412:             $newdeps = array();
                   18413:             foreach ($param->_downloadDeps as $dep) {
                   18414:                 $merge = array_merge($params, $newparams);
                   18415:                 if (!PEAR_Downloader_Package::willDownload($dep, $merge)
                   18416:                     && !$param->isInstalled($dep)
                   18417:                 ) {
                   18418:                     $newdeps[] = $dep;
                   18419:                 } else {
                   18420:                     //var_dump($dep);
                   18421:                     // detect versioning conflicts here
                   18422:                 }
                   18423:             }
                   18424: 
                   18425:             // convert the dependencies into PEAR_Downloader_Package objects for the next time around
                   18426:             $params[$i]->_downloadDeps = array();
                   18427:             foreach ($newdeps as $dep) {
                   18428:                 $obj = &new PEAR_Downloader_Package($params[$i]->getDownloader());
                   18429:                 if ($s = $params[$i]->explicitState()) {
                   18430:                     $obj->setExplicitState($s);
                   18431:                 }
                   18432: 
                   18433:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   18434:                 $e = $obj->fromDepURL($dep);
                   18435:                 PEAR::popErrorHandling();
                   18436:                 if (PEAR::isError($e)) {
                   18437:                     if (!isset($options['soft'])) {
                   18438:                         $obj->_downloader->log(0, $e->getMessage());
                   18439:                     }
                   18440:                     continue;
                   18441:                 }
                   18442: 
                   18443:                 $e = $obj->detectDependencies($params);
                   18444:                 if (PEAR::isError($e)) {
                   18445:                     if (!isset($options['soft'])) {
                   18446:                         $obj->_downloader->log(0, $e->getMessage());
                   18447:                     }
                   18448:                 }
                   18449: 
                   18450:                 $j = &$obj;
                   18451:                 $newparams[] = &$j;
                   18452:             }
                   18453:         }
                   18454: 
                   18455:         if (count($newparams)) {
                   18456:             foreach ($newparams as $i => $unused) {
                   18457:                 $params[] = &$newparams[$i];
                   18458:             }
                   18459:             return true;
                   18460:         }
                   18461: 
                   18462:         return false;
                   18463:     }
                   18464: 
                   18465: 
                   18466:     /**
                   18467:      * @static
                   18468:      */
                   18469:     function willDownload($param, $params)
                   18470:     {
                   18471:         if (!is_array($params)) {
                   18472:             return false;
                   18473:         }
                   18474: 
                   18475:         foreach ($params as $obj) {
                   18476:             if ($obj->isEqual($param)) {
                   18477:                 return true;
                   18478:             }
                   18479:         }
                   18480: 
                   18481:         return false;
                   18482:     }
                   18483: 
                   18484:     /**
                   18485:      * For simpler unit-testing
                   18486:      * @param PEAR_Config
                   18487:      * @param int
                   18488:      * @param string
                   18489:      */
                   18490:     function &getPackagefileObject(&$c, $d)
                   18491:     {
                   18492:         $a = &new PEAR_PackageFile($c, $d);
                   18493:         return $a;
                   18494:     }
                   18495: 
                   18496:     /**
                   18497:      * This will retrieve from a local file if possible, and parse out
                   18498:      * a group name as well.  The original parameter will be modified to reflect this.
                   18499:      * @param string|array can be a parsed package name as well
                   18500:      * @access private
                   18501:      */
                   18502:     function _fromFile(&$param)
                   18503:     {
                   18504:         $saveparam = $param;
                   18505:         if (is_string($param)) {
                   18506:             if (!@file_exists($param)) {
                   18507:                 $test = explode('#', $param);
                   18508:                 $group = array_pop($test);
                   18509:                 if (@file_exists(implode('#', $test))) {
                   18510:                     $this->setGroup($group);
                   18511:                     $param = implode('#', $test);
                   18512:                     $this->_explicitGroup = true;
                   18513:                 }
                   18514:             }
                   18515: 
                   18516:             if (@is_file($param)) {
                   18517:                 $this->_type = 'local';
                   18518:                 $options = $this->_downloader->getOptions();
                   18519:                 $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->_debug);
                   18520:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   18521:                 $pf = &$pkg->fromAnyFile($param, PEAR_VALIDATE_INSTALLING);
                   18522:                 PEAR::popErrorHandling();
                   18523:                 if (PEAR::isError($pf)) {
                   18524:                     $this->_valid = false;
                   18525:                     $param = $saveparam;
                   18526:                     return $pf;
                   18527:                 }
                   18528:                 $this->_packagefile = &$pf;
                   18529:                 if (!$this->getGroup()) {
                   18530:                     $this->setGroup('default'); // install the default dependency group
                   18531:                 }
                   18532:                 return $this->_valid = true;
                   18533:             }
                   18534:         }
                   18535:         $param = $saveparam;
                   18536:         return $this->_valid = false;
                   18537:     }
                   18538: 
                   18539:     function _fromUrl($param, $saveparam = '')
                   18540:     {
                   18541:         if (!is_array($param) && (preg_match('#^(http|https|ftp)://#', $param))) {
                   18542:             $options = $this->_downloader->getOptions();
                   18543:             $this->_type = 'url';
                   18544:             $callback = $this->_downloader->ui ?
                   18545:                 array(&$this->_downloader, '_downloadCallback') : null;
                   18546:             $this->_downloader->pushErrorHandling(PEAR_ERROR_RETURN);
                   18547:             if (PEAR::isError($dir = $this->_downloader->getDownloadDir())) {
                   18548:                 $this->_downloader->popErrorHandling();
                   18549:                 return $dir;
                   18550:             }
                   18551: 
                   18552:             $this->_downloader->log(3, 'Downloading "' . $param . '"');
                   18553:             $file = $this->_downloader->downloadHttp($param, $this->_downloader->ui,
                   18554:                 $dir, $callback, null, false, $this->getChannel());
                   18555:             $this->_downloader->popErrorHandling();
                   18556:             if (PEAR::isError($file)) {
                   18557:                 if (!empty($saveparam)) {
                   18558:                     $saveparam = ", cannot download \"$saveparam\"";
                   18559:                 }
                   18560:                 $err = PEAR::raiseError('Could not download from "' . $param .
                   18561:                     '"' . $saveparam . ' (' . $file->getMessage() . ')');
                   18562:                     return $err;
                   18563:             }
                   18564: 
                   18565:             if ($this->_rawpackagefile) {
                   18566:                 require_once 'Archive/Tar.php';
                   18567:                 $tar = &new Archive_Tar($file);
                   18568:                 $packagexml = $tar->extractInString('package2.xml');
                   18569:                 if (!$packagexml) {
                   18570:                     $packagexml = $tar->extractInString('package.xml');
                   18571:                 }
                   18572: 
                   18573:                 if (str_replace(array("\n", "\r"), array('',''), $packagexml) !=
                   18574:                       str_replace(array("\n", "\r"), array('',''), $this->_rawpackagefile)) {
                   18575:                     if ($this->getChannel() != 'pear.php.net') {
                   18576:                         return PEAR::raiseError('CRITICAL ERROR: package.xml downloaded does ' .
                   18577:                             'not match value returned from xml-rpc');
                   18578:                     }
                   18579: 
                   18580:                     // be more lax for the existing PEAR packages that have not-ok
                   18581:                     // characters in their package.xml
                   18582:                     $this->_downloader->log(0, 'CRITICAL WARNING: The "' .
                   18583:                         $this->getPackage() . '" package has invalid characters in its ' .
                   18584:                         'package.xml.  The next version of PEAR may not be able to install ' .
                   18585:                         'this package for security reasons.  Please open a bug report at ' .
                   18586:                         'http://pear.php.net/package/' . $this->getPackage() . '/bugs');
                   18587:                 }
                   18588:             }
                   18589: 
                   18590:             // whew, download worked!
                   18591:             $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->debug);
                   18592: 
                   18593:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   18594:             $pf = &$pkg->fromAnyFile($file, PEAR_VALIDATE_INSTALLING);
                   18595:             PEAR::popErrorHandling();
                   18596:             if (PEAR::isError($pf)) {
                   18597:                 if (is_array($pf->getUserInfo())) {
                   18598:                     foreach ($pf->getUserInfo() as $err) {
                   18599:                         if (is_array($err)) {
                   18600:                             $err = $err['message'];
                   18601:                         }
                   18602: 
                   18603:                         if (!isset($options['soft'])) {
                   18604:                             $this->_downloader->log(0, "Validation Error: $err");
                   18605:                         }
                   18606:                     }
                   18607:                 }
                   18608: 
                   18609:                 if (!isset($options['soft'])) {
                   18610:                     $this->_downloader->log(0, $pf->getMessage());
                   18611:                 }
                   18612: 
                   18613:                 ///FIXME need to pass back some error code that we can use to match with to cancel all further operations
                   18614:                 /// At least stop all deps of this package from being installed
                   18615:                 $out = $saveparam ? $saveparam : $param;
                   18616:                 $err = PEAR::raiseError('Download of "' . $out . '" succeeded, but it is not a valid package archive');
                   18617:                 $this->_valid = false;
                   18618:                 return $err;
                   18619:             }
                   18620: 
                   18621:             $this->_packagefile = &$pf;
                   18622:             $this->setGroup('default'); // install the default dependency group
                   18623:             return $this->_valid = true;
                   18624:         }
                   18625: 
                   18626:         return $this->_valid = false;
                   18627:     }
                   18628: 
                   18629:     /**
                   18630:      *
                   18631:      * @param string|array pass in an array of format
                   18632:      *                     array(
                   18633:      *                      'package' => 'pname',
                   18634:      *                     ['channel' => 'channame',]
                   18635:      *                     ['version' => 'version',]
                   18636:      *                     ['state' => 'state',])
                   18637:      *                     or a string of format [channame/]pname[-version|-state]
                   18638:      */
                   18639:     function _fromString($param)
                   18640:     {
                   18641:         $options = $this->_downloader->getOptions();
                   18642:         $channel = $this->_config->get('default_channel');
                   18643:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   18644:         $pname = $this->_registry->parsePackageName($param, $channel);
                   18645:         PEAR::popErrorHandling();
                   18646:         if (PEAR::isError($pname)) {
                   18647:             if ($pname->getCode() == 'invalid') {
                   18648:                 $this->_valid = false;
                   18649:                 return false;
                   18650:             }
                   18651: 
                   18652:             if ($pname->getCode() == 'channel') {
                   18653:                 $parsed = $pname->getUserInfo();
                   18654:                 if ($this->_downloader->discover($parsed['channel'])) {
                   18655:                     if ($this->_config->get('auto_discover')) {
                   18656:                         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   18657:                         $pname = $this->_registry->parsePackageName($param, $channel);
                   18658:                         PEAR::popErrorHandling();
                   18659:                     } else {
                   18660:                         if (!isset($options['soft'])) {
                   18661:                             $this->_downloader->log(0, 'Channel "' . $parsed['channel'] .
                   18662:                                 '" is not initialized, use ' .
                   18663:                                 '"pear channel-discover ' . $parsed['channel'] . '" to initialize' .
                   18664:                                 'or pear config-set auto_discover 1');
                   18665:                         }
                   18666:                     }
                   18667:                 }
                   18668: 
                   18669:                 if (PEAR::isError($pname)) {
                   18670:                     if (!isset($options['soft'])) {
                   18671:                         $this->_downloader->log(0, $pname->getMessage());
                   18672:                     }
                   18673: 
                   18674:                     if (is_array($param)) {
                   18675:                         $param = $this->_registry->parsedPackageNameToString($param);
                   18676:                     }
                   18677: 
                   18678:                     $err = PEAR::raiseError('invalid package name/package file "' . $param . '"');
                   18679:                     $this->_valid = false;
                   18680:                     return $err;
                   18681:                 }
                   18682:             } else {
                   18683:                 if (!isset($options['soft'])) {
                   18684:                     $this->_downloader->log(0, $pname->getMessage());
                   18685:                 }
                   18686: 
                   18687:                 $err = PEAR::raiseError('invalid package name/package file "' . $param . '"');
                   18688:                 $this->_valid = false;
                   18689:                 return $err;
                   18690:             }
                   18691:         }
                   18692: 
                   18693:         if (!isset($this->_type)) {
                   18694:             $this->_type = 'rest';
                   18695:         }
                   18696: 
                   18697:         $this->_parsedname    = $pname;
                   18698:         $this->_explicitState = isset($pname['state']) ? $pname['state'] : false;
                   18699:         $this->_explicitGroup = isset($pname['group']) ? true : false;
                   18700: 
                   18701:         $info = $this->_downloader->_getPackageDownloadUrl($pname);
                   18702:         if (PEAR::isError($info)) {
                   18703:             if ($info->getCode() != -976 && $pname['channel'] == 'pear.php.net') {
                   18704:                 // try pecl
                   18705:                 $pname['channel'] = 'pecl.php.net';
                   18706:                 if ($test = $this->_downloader->_getPackageDownloadUrl($pname)) {
                   18707:                     if (!PEAR::isError($test)) {
                   18708:                         $info = PEAR::raiseError($info->getMessage() . ' - package ' .
                   18709:                             $this->_registry->parsedPackageNameToString($pname, true) .
                   18710:                             ' can be installed with "pecl install ' . $pname['package'] .
                   18711:                             '"');
                   18712:                     } else {
                   18713:                         $pname['channel'] = 'pear.php.net';
                   18714:                     }
                   18715:                 } else {
                   18716:                     $pname['channel'] = 'pear.php.net';
                   18717:                 }
                   18718:             }
                   18719: 
                   18720:             return $info;
                   18721:         }
                   18722: 
                   18723:         $this->_rawpackagefile = $info['raw'];
                   18724:         $ret = $this->_analyzeDownloadURL($info, $param, $pname);
                   18725:         if (PEAR::isError($ret)) {
                   18726:             return $ret;
                   18727:         }
                   18728: 
                   18729:         if ($ret) {
                   18730:             $this->_downloadURL = $ret;
                   18731:             return $this->_valid = (bool) $ret;
                   18732:         }
                   18733:     }
                   18734: 
                   18735:     /**
                   18736:      * @param array output of package.getDownloadURL
                   18737:      * @param string|array|object information for detecting packages to be downloaded, and
                   18738:      *                            for errors
                   18739:      * @param array name information of the package
                   18740:      * @param array|null packages to be downloaded
                   18741:      * @param bool is this an optional dependency?
                   18742:      * @param bool is this any kind of dependency?
                   18743:      * @access private
                   18744:      */
                   18745:     function _analyzeDownloadURL($info, $param, $pname, $params = null, $optional = false,
                   18746:                                  $isdependency = false)
                   18747:     {
                   18748:         if (!is_string($param) && PEAR_Downloader_Package::willDownload($param, $params)) {
                   18749:             return false;
                   18750:         }
                   18751: 
                   18752:         if ($info === false) {
                   18753:             $saveparam = !is_string($param) ? ", cannot download \"$param\"" : '';
                   18754: 
                   18755:             // no releases exist
                   18756:             return PEAR::raiseError('No releases for package "' .
                   18757:                 $this->_registry->parsedPackageNameToString($pname, true) . '" exist' . $saveparam);
                   18758:         }
                   18759: 
                   18760:         if (strtolower($info['info']->getChannel()) != strtolower($pname['channel'])) {
                   18761:             $err = false;
                   18762:             if ($pname['channel'] == 'pecl.php.net') {
                   18763:                 if ($info['info']->getChannel() != 'pear.php.net') {
                   18764:                     $err = true;
                   18765:                 }
                   18766:             } elseif ($info['info']->getChannel() == 'pecl.php.net') {
                   18767:                 if ($pname['channel'] != 'pear.php.net') {
                   18768:                     $err = true;
                   18769:                 }
                   18770:             } else {
                   18771:                 $err = true;
                   18772:             }
                   18773: 
                   18774:             if ($err) {
                   18775:                 return PEAR::raiseError('SECURITY ERROR: package in channel "' . $pname['channel'] .
                   18776:                     '" retrieved another channel\'s name for download! ("' .
                   18777:                     $info['info']->getChannel() . '")');
                   18778:             }
                   18779:         }
                   18780: 
                   18781:         $preferred_state = $this->_config->get('preferred_state');
                   18782:         if (!isset($info['url'])) {
                   18783:             $package_version = $this->_registry->packageInfo($info['info']->getPackage(),
                   18784:             'version', $info['info']->getChannel());
                   18785:             if ($this->isInstalled($info)) {
                   18786:                 if ($isdependency && version_compare($info['version'], $package_version, '<=')) {
                   18787:                     // ignore bogus errors of "failed to download dependency"
                   18788:                     // if it is already installed and the one that would be
                   18789:                     // downloaded is older or the same version (Bug #7219)
                   18790:                     return false;
                   18791:                 }
                   18792:             }
                   18793: 
                   18794:             if ($info['version'] === $package_version) {
                   18795:                 if (!isset($options['soft'])) {
                   18796:                     $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] .
                   18797:                         '/' . $pname['package'] . '-' . $package_version. ', additionally the suggested version' .
                   18798:                         ' (' . $package_version . ') is the same as the locally installed one.');
                   18799:                 }
                   18800: 
                   18801:                 return false;
                   18802:             }
                   18803: 
                   18804:             if (version_compare($info['version'], $package_version, '<=')) {
                   18805:                 if (!isset($options['soft'])) {
                   18806:                     $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] .
                   18807:                         '/' . $pname['package'] . '-' . $package_version . ', additionally the suggested version' .
                   18808:                         ' (' . $info['version'] . ') is a lower version than the locally installed one (' . $package_version . ').');
                   18809:                 }
                   18810: 
                   18811:                 return false;
                   18812:             }
                   18813: 
                   18814:             $instead =  ', will instead download version ' . $info['version'] .
                   18815:                         ', stability "' . $info['info']->getState() . '"';
                   18816:             // releases exist, but we failed to get any
                   18817:             if (isset($this->_downloader->_options['force'])) {
                   18818:                 if (isset($pname['version'])) {
                   18819:                     $vs = ', version "' . $pname['version'] . '"';
                   18820:                 } elseif (isset($pname['state'])) {
                   18821:                     $vs = ', stability "' . $pname['state'] . '"';
                   18822:                 } elseif ($param == 'dependency') {
                   18823:                     if (!class_exists('PEAR_Common')) {
                   18824:                         require_once 'PEAR/Common.php';
                   18825:                     }
                   18826: 
                   18827:                     if (!in_array($info['info']->getState(),
                   18828:                           PEAR_Common::betterStates($preferred_state, true))) {
                   18829:                         if ($optional) {
                   18830:                             // don't spit out confusing error message
                   18831:                             return $this->_downloader->_getPackageDownloadUrl(
                   18832:                                 array('package' => $pname['package'],
                   18833:                                       'channel' => $pname['channel'],
                   18834:                                       'version' => $info['version']));
                   18835:                         }
                   18836:                         $vs = ' within preferred state "' . $preferred_state .
                   18837:                             '"';
                   18838:                     } else {
                   18839:                         if (!class_exists('PEAR_Dependency2')) {
                   18840:                             require_once 'PEAR/Dependency2.php';
                   18841:                         }
                   18842: 
                   18843:                         if ($optional) {
                   18844:                             // don't spit out confusing error message
                   18845:                             return $this->_downloader->_getPackageDownloadUrl(
                   18846:                                 array('package' => $pname['package'],
                   18847:                                       'channel' => $pname['channel'],
                   18848:                                       'version' => $info['version']));
                   18849:                         }
                   18850:                         $vs = PEAR_Dependency2::_getExtraString($pname);
                   18851:                         $instead = '';
                   18852:                     }
                   18853:                 } else {
                   18854:                     $vs = ' within preferred state "' . $preferred_state . '"';
                   18855:                 }
                   18856: 
                   18857:                 if (!isset($options['soft'])) {
                   18858:                     $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] .
                   18859:                         '/' . $pname['package'] . $vs . $instead);
                   18860:                 }
                   18861: 
                   18862:                 // download the latest release
                   18863:                 return $this->_downloader->_getPackageDownloadUrl(
                   18864:                     array('package' => $pname['package'],
                   18865:                           'channel' => $pname['channel'],
                   18866:                           'version' => $info['version']));
                   18867:             } else {
                   18868:                 if (isset($info['php']) && $info['php']) {
                   18869:                     $err = PEAR::raiseError('Failed to download ' .
                   18870:                         $this->_registry->parsedPackageNameToString(
                   18871:                             array('channel' => $pname['channel'],
                   18872:                                   'package' => $pname['package']),
                   18873:                                 true) .
                   18874:                         ', latest release is version ' . $info['php']['v'] .
                   18875:                         ', but it requires PHP version "' .
                   18876:                         $info['php']['m'] . '", use "' .
                   18877:                         $this->_registry->parsedPackageNameToString(
                   18878:                             array('channel' => $pname['channel'], 'package' => $pname['package'],
                   18879:                             'version' => $info['php']['v'])) . '" to install',
                   18880:                             PEAR_DOWNLOADER_PACKAGE_PHPVERSION);
                   18881:                     return $err;
                   18882:                 }
                   18883: 
                   18884:                 // construct helpful error message
                   18885:                 if (isset($pname['version'])) {
                   18886:                     $vs = ', version "' . $pname['version'] . '"';
                   18887:                 } elseif (isset($pname['state'])) {
                   18888:                     $vs = ', stability "' . $pname['state'] . '"';
                   18889:                 } elseif ($param == 'dependency') {
                   18890:                     if (!class_exists('PEAR_Common')) {
                   18891:                         require_once 'PEAR/Common.php';
                   18892:                     }
                   18893: 
                   18894:                     if (!in_array($info['info']->getState(),
                   18895:                           PEAR_Common::betterStates($preferred_state, true))) {
                   18896:                         if ($optional) {
                   18897:                             // don't spit out confusing error message, and don't die on
                   18898:                             // optional dep failure!
                   18899:                             return $this->_downloader->_getPackageDownloadUrl(
                   18900:                                 array('package' => $pname['package'],
                   18901:                                       'channel' => $pname['channel'],
                   18902:                                       'version' => $info['version']));
                   18903:                         }
                   18904:                         $vs = ' within preferred state "' . $preferred_state . '"';
                   18905:                     } else {
                   18906:                         if (!class_exists('PEAR_Dependency2')) {
                   18907:                             require_once 'PEAR/Dependency2.php';
                   18908:                         }
                   18909: 
                   18910:                         if ($optional) {
                   18911:                             // don't spit out confusing error message, and don't die on
                   18912:                             // optional dep failure!
                   18913:                             return $this->_downloader->_getPackageDownloadUrl(
                   18914:                                 array('package' => $pname['package'],
                   18915:                                       'channel' => $pname['channel'],
                   18916:                                       'version' => $info['version']));
                   18917:                         }
                   18918:                         $vs = PEAR_Dependency2::_getExtraString($pname);
                   18919:                     }
                   18920:                 } else {
                   18921:                     $vs = ' within preferred state "' . $this->_downloader->config->get('preferred_state') . '"';
                   18922:                 }
                   18923: 
                   18924:                 $options = $this->_downloader->getOptions();
                   18925:                 // this is only set by the "download-all" command
                   18926:                 if (isset($options['ignorepreferred_state'])) {
                   18927:                     $err = PEAR::raiseError(
                   18928:                         'Failed to download ' . $this->_registry->parsedPackageNameToString(
                   18929:                             array('channel' => $pname['channel'], 'package' => $pname['package']),
                   18930:                                 true)
                   18931:                          . $vs .
                   18932:                         ', latest release is version ' . $info['version'] .
                   18933:                         ', stability "' . $info['info']->getState() . '", use "' .
                   18934:                         $this->_registry->parsedPackageNameToString(
                   18935:                             array('channel' => $pname['channel'], 'package' => $pname['package'],
                   18936:                             'version' => $info['version'])) . '" to install',
                   18937:                             PEAR_DOWNLOADER_PACKAGE_STATE);
                   18938:                     return $err;
                   18939:                 }
                   18940: 
                   18941:                 // Checks if the user has a package installed already and checks the release against
                   18942:                 // the state against the installed package, this allows upgrades for packages
                   18943:                 // with lower stability than the preferred_state
                   18944:                 $stability = $this->_registry->packageInfo($pname['package'], 'stability', $pname['channel']);
                   18945:                 if (!$this->isInstalled($info)
                   18946:                     || !in_array($info['info']->getState(), PEAR_Common::betterStates($stability['release'], true))
                   18947:                 ) {
                   18948:                     $err = PEAR::raiseError(
                   18949:                         'Failed to download ' . $this->_registry->parsedPackageNameToString(
                   18950:                             array('channel' => $pname['channel'], 'package' => $pname['package']),
                   18951:                                 true)
                   18952:                          . $vs .
                   18953:                         ', latest release is version ' . $info['version'] .
                   18954:                         ', stability "' . $info['info']->getState() . '", use "' .
                   18955:                         $this->_registry->parsedPackageNameToString(
                   18956:                             array('channel' => $pname['channel'], 'package' => $pname['package'],
                   18957:                             'version' => $info['version'])) . '" to install');
                   18958:                     return $err;
                   18959:                 }
                   18960:             }
                   18961:         }
                   18962: 
                   18963:         if (isset($info['deprecated']) && $info['deprecated']) {
                   18964:             $this->_downloader->log(0,
                   18965:                 'WARNING: "' .
                   18966:                     $this->_registry->parsedPackageNameToString(
                   18967:                             array('channel' => $info['info']->getChannel(),
                   18968:                                   'package' => $info['info']->getPackage()), true) .
                   18969:                 '" is deprecated in favor of "' .
                   18970:                     $this->_registry->parsedPackageNameToString($info['deprecated'], true) .
                   18971:                 '"');
                   18972:         }
                   18973: 
                   18974:         return $info;
                   18975:     }
1.1.1.2 ! misho    18976: }PEAR-1.9.4/PEAR/Frontend/CLI.php0000644000076500000240000006221611605156614014671 0ustar  helgistaff<?php
1.1       misho    18977: /**
                   18978:  * PEAR_Frontend_CLI
                   18979:  *
                   18980:  * PHP versions 4 and 5
                   18981:  *
                   18982:  * @category   pear
                   18983:  * @package    PEAR
                   18984:  * @author     Stig Bakken <ssb@php.net>
                   18985:  * @author     Greg Beaver <cellog@php.net>
                   18986:  * @copyright  1997-2009 The Authors
                   18987:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   18988:  * @version    CVS: $Id: CLI.php 313023 2011-07-06 19:17:11Z dufuz $
                   18989:  * @link       http://pear.php.net/package/PEAR
                   18990:  * @since      File available since Release 0.1
                   18991:  */
                   18992: /**
                   18993:  * base class
                   18994:  */
                   18995: require_once 'PEAR/Frontend.php';
                   18996: 
                   18997: /**
                   18998:  * Command-line Frontend for the PEAR Installer
                   18999:  * @category   pear
                   19000:  * @package    PEAR
                   19001:  * @author     Stig Bakken <ssb@php.net>
                   19002:  * @author     Greg Beaver <cellog@php.net>
                   19003:  * @copyright  1997-2009 The Authors
                   19004:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   19005:  * @version    Release: 1.9.4
                   19006:  * @link       http://pear.php.net/package/PEAR
                   19007:  * @since      Class available since Release 0.1
                   19008:  */
                   19009: class PEAR_Frontend_CLI extends PEAR_Frontend
                   19010: {
                   19011:     /**
                   19012:      * What type of user interface this frontend is for.
                   19013:      * @var string
                   19014:      * @access public
                   19015:      */
                   19016:     var $type = 'CLI';
                   19017:     var $lp = ''; // line prefix
                   19018: 
                   19019:     var $params = array();
                   19020:     var $term = array(
                   19021:         'bold'   => '',
                   19022:         'normal' => '',
                   19023:     );
                   19024: 
                   19025:     function PEAR_Frontend_CLI()
                   19026:     {
                   19027:         parent::PEAR();
                   19028:         $term = getenv('TERM'); //(cox) $_ENV is empty for me in 4.1.1
                   19029:         if (function_exists('posix_isatty') && !posix_isatty(1)) {
                   19030:             // output is being redirected to a file or through a pipe
                   19031:         } elseif ($term) {
                   19032:             if (preg_match('/^(xterm|vt220|linux)/', $term)) {
                   19033:                 $this->term['bold']   = sprintf("%c%c%c%c", 27, 91, 49, 109);
                   19034:                 $this->term['normal'] = sprintf("%c%c%c", 27, 91, 109);
                   19035:             } elseif (preg_match('/^vt100/', $term)) {
                   19036:                 $this->term['bold']   = sprintf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0);
                   19037:                 $this->term['normal'] = sprintf("%c%c%c%c%c", 27, 91, 109, 0, 0);
                   19038:             }
                   19039:         } elseif (OS_WINDOWS) {
                   19040:             // XXX add ANSI codes here
                   19041:         }
                   19042:     }
                   19043: 
                   19044:     /**
                   19045:      * @param object PEAR_Error object
                   19046:      */
                   19047:     function displayError($e)
                   19048:     {
                   19049:         return $this->_displayLine($e->getMessage());
                   19050:     }
                   19051: 
                   19052:     /**
                   19053:      * @param object PEAR_Error object
                   19054:      */
                   19055:     function displayFatalError($eobj)
                   19056:     {
                   19057:         $this->displayError($eobj);
                   19058:         if (class_exists('PEAR_Config')) {
                   19059:             $config = &PEAR_Config::singleton();
                   19060:             if ($config->get('verbose') > 5) {
                   19061:                 if (function_exists('debug_print_backtrace')) {
                   19062:                     debug_print_backtrace();
                   19063:                     exit(1);
                   19064:                 }
                   19065: 
                   19066:                 $raised = false;
                   19067:                 foreach (debug_backtrace() as $i => $frame) {
                   19068:                     if (!$raised) {
                   19069:                         if (isset($frame['class'])
                   19070:                             && strtolower($frame['class']) == 'pear'
                   19071:                             && strtolower($frame['function']) == 'raiseerror'
                   19072:                         ) {
                   19073:                             $raised = true;
                   19074:                         } else {
                   19075:                             continue;
                   19076:                         }
                   19077:                     }
                   19078: 
                   19079:                     $frame['class']    = !isset($frame['class'])    ? '' : $frame['class'];
                   19080:                     $frame['type']     = !isset($frame['type'])     ? '' : $frame['type'];
                   19081:                     $frame['function'] = !isset($frame['function']) ? '' : $frame['function'];
                   19082:                     $frame['line']     = !isset($frame['line'])     ? '' : $frame['line'];
                   19083:                     $this->_displayLine("#$i: $frame[class]$frame[type]$frame[function] $frame[line]");
                   19084:                 }
                   19085:             }
                   19086:         }
                   19087: 
                   19088:         exit(1);
                   19089:     }
                   19090: 
                   19091:     /**
                   19092:      * Instruct the runInstallScript method to skip a paramgroup that matches the
                   19093:      * id value passed in.
                   19094:      *
                   19095:      * This method is useful for dynamically configuring which sections of a post-install script
                   19096:      * will be run based on the user's setup, which is very useful for making flexible
                   19097:      * post-install scripts without losing the cross-Frontend ability to retrieve user input
                   19098:      * @param string
                   19099:      */
                   19100:     function skipParamgroup($id)
                   19101:     {
                   19102:         $this->_skipSections[$id] = true;
                   19103:     }
                   19104: 
                   19105:     function runPostinstallScripts(&$scripts)
                   19106:     {
                   19107:         foreach ($scripts as $i => $script) {
                   19108:             $this->runInstallScript($scripts[$i]->_params, $scripts[$i]->_obj);
                   19109:         }
                   19110:     }
                   19111: 
                   19112:     /**
                   19113:      * @param array $xml contents of postinstallscript tag
                   19114:      * @param object $script post-installation script
                   19115:      * @param string install|upgrade
                   19116:      */
                   19117:     function runInstallScript($xml, &$script)
                   19118:     {
                   19119:         $this->_skipSections = array();
                   19120:         if (!is_array($xml) || !isset($xml['paramgroup'])) {
                   19121:             $script->run(array(), '_default');
                   19122:             return;
                   19123:         }
                   19124: 
                   19125:         $completedPhases = array();
                   19126:         if (!isset($xml['paramgroup'][0])) {
                   19127:             $xml['paramgroup'] = array($xml['paramgroup']);
                   19128:         }
                   19129: 
                   19130:         foreach ($xml['paramgroup'] as $group) {
                   19131:             if (isset($this->_skipSections[$group['id']])) {
                   19132:                 // the post-install script chose to skip this section dynamically
                   19133:                 continue;
                   19134:             }
                   19135: 
                   19136:             if (isset($group['name'])) {
                   19137:                 $paramname = explode('::', $group['name']);
                   19138:                 if ($lastgroup['id'] != $paramname[0]) {
                   19139:                     continue;
                   19140:                 }
                   19141: 
                   19142:                 $group['name'] = $paramname[1];
                   19143:                 if (!isset($answers)) {
                   19144:                     return;
                   19145:                 }
                   19146: 
                   19147:                 if (isset($answers[$group['name']])) {
                   19148:                     switch ($group['conditiontype']) {
                   19149:                         case '=' :
                   19150:                             if ($answers[$group['name']] != $group['value']) {
                   19151:                                 continue 2;
                   19152:                             }
                   19153:                         break;
                   19154:                         case '!=' :
                   19155:                             if ($answers[$group['name']] == $group['value']) {
                   19156:                                 continue 2;
                   19157:                             }
                   19158:                         break;
                   19159:                         case 'preg_match' :
                   19160:                             if (!@preg_match('/' . $group['value'] . '/',
                   19161:                                   $answers[$group['name']])) {
                   19162:                                 continue 2;
                   19163:                             }
                   19164:                         break;
                   19165:                         default :
                   19166:                         return;
                   19167:                     }
                   19168:                 }
                   19169:             }
                   19170: 
                   19171:             $lastgroup = $group;
                   19172:             if (isset($group['instructions'])) {
                   19173:                 $this->_display($group['instructions']);
                   19174:             }
                   19175: 
                   19176:             if (!isset($group['param'][0])) {
                   19177:                 $group['param'] = array($group['param']);
                   19178:             }
                   19179: 
                   19180:             if (isset($group['param'])) {
                   19181:                 if (method_exists($script, 'postProcessPrompts')) {
                   19182:                     $prompts = $script->postProcessPrompts($group['param'], $group['id']);
                   19183:                     if (!is_array($prompts) || count($prompts) != count($group['param'])) {
                   19184:                         $this->outputData('postinstall', 'Error: post-install script did not ' .
                   19185:                             'return proper post-processed prompts');
                   19186:                         $prompts = $group['param'];
                   19187:                     } else {
                   19188:                         foreach ($prompts as $i => $var) {
                   19189:                             if (!is_array($var) || !isset($var['prompt']) ||
                   19190:                                   !isset($var['name']) ||
                   19191:                                   ($var['name'] != $group['param'][$i]['name']) ||
                   19192:                                   ($var['type'] != $group['param'][$i]['type'])
                   19193:                             ) {
                   19194:                                 $this->outputData('postinstall', 'Error: post-install script ' .
                   19195:                                     'modified the variables or prompts, severe security risk. ' .
                   19196:                                     'Will instead use the defaults from the package.xml');
                   19197:                                 $prompts = $group['param'];
                   19198:                             }
                   19199:                         }
                   19200:                     }
                   19201: 
                   19202:                     $answers = $this->confirmDialog($prompts);
                   19203:                 } else {
                   19204:                     $answers = $this->confirmDialog($group['param']);
                   19205:                 }
                   19206:             }
                   19207: 
                   19208:             if ((isset($answers) && $answers) || !isset($group['param'])) {
                   19209:                 if (!isset($answers)) {
                   19210:                     $answers = array();
                   19211:                 }
                   19212: 
                   19213:                 array_unshift($completedPhases, $group['id']);
                   19214:                 if (!$script->run($answers, $group['id'])) {
                   19215:                     $script->run($completedPhases, '_undoOnError');
                   19216:                     return;
                   19217:                 }
                   19218:             } else {
                   19219:                 $script->run($completedPhases, '_undoOnError');
                   19220:                 return;
                   19221:             }
                   19222:         }
                   19223:     }
                   19224: 
                   19225:     /**
                   19226:      * Ask for user input, confirm the answers and continue until the user is satisfied
                   19227:      * @param array an array of arrays, format array('name' => 'paramname', 'prompt' =>
                   19228:      *              'text to display', 'type' => 'string'[, default => 'default value'])
                   19229:      * @return array
                   19230:      */
                   19231:     function confirmDialog($params)
                   19232:     {
                   19233:         $answers = $prompts = $types = array();
                   19234:         foreach ($params as $param) {
                   19235:             $prompts[$param['name']] = $param['prompt'];
                   19236:             $types[$param['name']]   = $param['type'];
                   19237:             $answers[$param['name']] = isset($param['default']) ? $param['default'] : '';
                   19238:         }
                   19239: 
                   19240:         $tried = false;
                   19241:         do {
                   19242:             if ($tried) {
                   19243:                 $i = 1;
                   19244:                 foreach ($answers as $var => $value) {
                   19245:                     if (!strlen($value)) {
                   19246:                         echo $this->bold("* Enter an answer for #" . $i . ": ({$prompts[$var]})\n");
                   19247:                     }
                   19248:                     $i++;
                   19249:                 }
                   19250:             }
                   19251: 
                   19252:             $answers = $this->userDialog('', $prompts, $types, $answers);
                   19253:             $tried   = true;
                   19254:         } while (is_array($answers) && count(array_filter($answers)) != count($prompts));
                   19255: 
                   19256:         return $answers;
                   19257:     }
                   19258: 
                   19259:     function userDialog($command, $prompts, $types = array(), $defaults = array(), $screensize = 20)
                   19260:     {
                   19261:         if (!is_array($prompts)) {
                   19262:             return array();
                   19263:         }
                   19264: 
                   19265:         $testprompts = array_keys($prompts);
                   19266:         $result      = $defaults;
                   19267: 
                   19268:         reset($prompts);
                   19269:         if (count($prompts) === 1) {
                   19270:             foreach ($prompts as $key => $prompt) {
                   19271:                 $type    = $types[$key];
                   19272:                 $default = @$defaults[$key];
                   19273:                 print "$prompt ";
                   19274:                 if ($default) {
                   19275:                     print "[$default] ";
                   19276:                 }
                   19277:                 print ": ";
                   19278: 
                   19279:                 $line         = fgets(STDIN, 2048);
                   19280:                 $result[$key] =  ($default && trim($line) == '') ? $default : trim($line);
                   19281:             }
                   19282: 
                   19283:             return $result;
                   19284:         }
                   19285: 
                   19286:         $first_run = true;
                   19287:         while (true) {
                   19288:             $descLength = max(array_map('strlen', $prompts));
                   19289:             $descFormat = "%-{$descLength}s";
                   19290:             $last       = count($prompts);
                   19291: 
                   19292:             $i = 0;
                   19293:             foreach ($prompts as $n => $var) {
                   19294:                 $res = isset($result[$n]) ? $result[$n] : null;
                   19295:                 printf("%2d. $descFormat : %s\n", ++$i, $prompts[$n], $res);
                   19296:             }
                   19297:             print "\n1-$last, 'all', 'abort', or Enter to continue: ";
                   19298: 
                   19299:             $tmp = trim(fgets(STDIN, 1024));
                   19300:             if (empty($tmp)) {
                   19301:                 break;
                   19302:             }
                   19303: 
                   19304:             if ($tmp == 'abort') {
                   19305:                 return false;
                   19306:             }
                   19307: 
                   19308:             if (isset($testprompts[(int)$tmp - 1])) {
                   19309:                 $var     = $testprompts[(int)$tmp - 1];
                   19310:                 $desc    = $prompts[$var];
                   19311:                 $current = @$result[$var];
                   19312:                 print "$desc [$current] : ";
                   19313:                 $tmp = trim(fgets(STDIN, 1024));
                   19314:                 if ($tmp !== '') {
                   19315:                     $result[$var] = $tmp;
                   19316:                 }
                   19317:             } elseif ($tmp == 'all') {
                   19318:                 foreach ($prompts as $var => $desc) {
                   19319:                     $current = $result[$var];
                   19320:                     print "$desc [$current] : ";
                   19321:                     $tmp = trim(fgets(STDIN, 1024));
                   19322:                     if (trim($tmp) !== '') {
                   19323:                         $result[$var] = trim($tmp);
                   19324:                     }
                   19325:                 }
                   19326:             }
                   19327: 
                   19328:             $first_run = false;
                   19329:         }
                   19330: 
                   19331:         return $result;
                   19332:     }
                   19333: 
                   19334:     function userConfirm($prompt, $default = 'yes')
                   19335:     {
                   19336:         trigger_error("PEAR_Frontend_CLI::userConfirm not yet converted", E_USER_ERROR);
                   19337:         static $positives = array('y', 'yes', 'on', '1');
                   19338:         static $negatives = array('n', 'no', 'off', '0');
                   19339:         print "$this->lp$prompt [$default] : ";
                   19340:         $fp = fopen("php://stdin", "r");
                   19341:         $line = fgets($fp, 2048);
                   19342:         fclose($fp);
                   19343:         $answer = strtolower(trim($line));
                   19344:         if (empty($answer)) {
                   19345:             $answer = $default;
                   19346:         }
                   19347:         if (in_array($answer, $positives)) {
                   19348:             return true;
                   19349:         }
                   19350:         if (in_array($answer, $negatives)) {
                   19351:             return false;
                   19352:         }
                   19353:         if (in_array($default, $positives)) {
                   19354:             return true;
                   19355:         }
                   19356:         return false;
                   19357:     }
                   19358: 
                   19359:     function outputData($data, $command = '_default')
                   19360:     {
                   19361:         switch ($command) {
                   19362:             case 'channel-info':
                   19363:                 foreach ($data as $type => $section) {
                   19364:                     if ($type == 'main') {
                   19365:                         $section['data'] = array_values($section['data']);
                   19366:                     }
                   19367: 
                   19368:                     $this->outputData($section);
                   19369:                 }
                   19370:                 break;
                   19371:             case 'install':
                   19372:             case 'upgrade':
                   19373:             case 'upgrade-all':
                   19374:                 if (is_array($data) && isset($data['release_warnings'])) {
                   19375:                     $this->_displayLine('');
                   19376:                     $this->_startTable(array(
                   19377:                         'border' => false,
                   19378:                         'caption' => 'Release Warnings'
                   19379:                     ));
                   19380:                     $this->_tableRow(array($data['release_warnings']), null, array(1 => array('wrap' => 55)));
                   19381:                     $this->_endTable();
                   19382:                     $this->_displayLine('');
                   19383:                 }
                   19384: 
                   19385:                 $this->_displayLine(is_array($data) ? $data['data'] : $data);
                   19386:                 break;
                   19387:             case 'search':
                   19388:                 $this->_startTable($data);
                   19389:                 if (isset($data['headline']) && is_array($data['headline'])) {
                   19390:                     $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55)));
                   19391:                 }
                   19392: 
                   19393:                 $packages = array();
                   19394:                 foreach($data['data'] as $category) {
                   19395:                     foreach($category as $name => $pkg) {
                   19396:                         $packages[$pkg[0]] = $pkg;
                   19397:                     }
                   19398:                 }
                   19399: 
                   19400:                 $p = array_keys($packages);
                   19401:                 natcasesort($p);
                   19402:                 foreach ($p as $name) {
                   19403:                     $this->_tableRow($packages[$name], null, array(1 => array('wrap' => 55)));
                   19404:                 }
                   19405: 
                   19406:                 $this->_endTable();
                   19407:                 break;
                   19408:             case 'list-all':
                   19409:                 if (!isset($data['data'])) {
                   19410:                       $this->_displayLine('No packages in channel');
                   19411:                       break;
                   19412:                 }
                   19413: 
                   19414:                 $this->_startTable($data);
                   19415:                 if (isset($data['headline']) && is_array($data['headline'])) {
                   19416:                     $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55)));
                   19417:                 }
                   19418: 
                   19419:                 $packages = array();
                   19420:                 foreach($data['data'] as $category) {
                   19421:                     foreach($category as $name => $pkg) {
                   19422:                         $packages[$pkg[0]] = $pkg;
                   19423:                     }
                   19424:                 }
                   19425: 
                   19426:                 $p = array_keys($packages);
                   19427:                 natcasesort($p);
                   19428:                 foreach ($p as $name) {
                   19429:                     $pkg = $packages[$name];
                   19430:                     unset($pkg[4], $pkg[5]);
                   19431:                     $this->_tableRow($pkg, null, array(1 => array('wrap' => 55)));
                   19432:                 }
                   19433: 
                   19434:                 $this->_endTable();
                   19435:                 break;
                   19436:             case 'config-show':
                   19437:                 $data['border'] = false;
                   19438:                 $opts = array(
                   19439:                     0 => array('wrap' => 30),
                   19440:                     1 => array('wrap' => 20),
                   19441:                     2 => array('wrap' => 35)
                   19442:                 );
                   19443: 
                   19444:                 $this->_startTable($data);
                   19445:                 if (isset($data['headline']) && is_array($data['headline'])) {
                   19446:                     $this->_tableRow($data['headline'], array('bold' => true), $opts);
                   19447:                 }
                   19448: 
                   19449:                 foreach ($data['data'] as $group) {
                   19450:                     foreach ($group as $value) {
                   19451:                         if ($value[2] == '') {
                   19452:                             $value[2] = "<not set>";
                   19453:                         }
                   19454: 
                   19455:                         $this->_tableRow($value, null, $opts);
                   19456:                     }
                   19457:                 }
                   19458: 
                   19459:                 $this->_endTable();
                   19460:                 break;
                   19461:             case 'remote-info':
                   19462:                 $d = $data;
                   19463:                 $data = array(
                   19464:                     'caption' => 'Package details:',
                   19465:                     'border'  => false,
                   19466:                     'data'    => array(
                   19467:                         array("Latest",      $data['stable']),
                   19468:                         array("Installed",   $data['installed']),
                   19469:                         array("Package",     $data['name']),
                   19470:                         array("License",     $data['license']),
                   19471:                         array("Category",    $data['category']),
                   19472:                         array("Summary",     $data['summary']),
                   19473:                         array("Description", $data['description']),
                   19474:                     ),
                   19475:                 );
                   19476: 
                   19477:                 if (isset($d['deprecated']) && $d['deprecated']) {
                   19478:                     $conf = &PEAR_Config::singleton();
                   19479:                     $reg = $conf->getRegistry();
                   19480:                     $name = $reg->parsedPackageNameToString($d['deprecated'], true);
                   19481:                     $data['data'][] = array('Deprecated! use', $name);
                   19482:                 }
                   19483:             default: {
                   19484:                 if (is_array($data)) {
                   19485:                     $this->_startTable($data);
                   19486:                     $count = count($data['data'][0]);
                   19487:                     if ($count == 2) {
                   19488:                         $opts = array(0 => array('wrap' => 25),
                   19489:                                       1 => array('wrap' => 48)
                   19490:                         );
                   19491:                     } elseif ($count == 3) {
                   19492:                         $opts = array(0 => array('wrap' => 30),
                   19493:                                       1 => array('wrap' => 20),
                   19494:                                       2 => array('wrap' => 35)
                   19495:                         );
                   19496:                     } else {
                   19497:                         $opts = null;
                   19498:                     }
                   19499:                     if (isset($data['headline']) && is_array($data['headline'])) {
                   19500:                         $this->_tableRow($data['headline'],
                   19501:                                          array('bold' => true),
                   19502:                                          $opts);
                   19503:                     }
                   19504: 
                   19505:                     if (is_array($data['data'])) {
                   19506:                         foreach($data['data'] as $row) {
                   19507:                             $this->_tableRow($row, null, $opts);
                   19508:                         }
                   19509:                     } else {
                   19510:                         $this->_tableRow(array($data['data']), null, $opts);
                   19511:                      }
                   19512:                     $this->_endTable();
                   19513:                 } else {
                   19514:                     $this->_displayLine($data);
                   19515:                 }
                   19516:             }
                   19517:         }
                   19518:     }
                   19519: 
                   19520:     function log($text, $append_crlf = true)
                   19521:     {
                   19522:         if ($append_crlf) {
                   19523:             return $this->_displayLine($text);
                   19524:         }
                   19525: 
                   19526:         return $this->_display($text);
                   19527:     }
                   19528: 
                   19529:     function bold($text)
                   19530:     {
                   19531:         if (empty($this->term['bold'])) {
                   19532:             return strtoupper($text);
                   19533:         }
                   19534: 
                   19535:         return $this->term['bold'] . $text . $this->term['normal'];
                   19536:     }
                   19537: 
                   19538:     function _displayHeading($title)
                   19539:     {
                   19540:         print $this->lp.$this->bold($title)."\n";
                   19541:         print $this->lp.str_repeat("=", strlen($title))."\n";
                   19542:     }
                   19543: 
                   19544:     function _startTable($params = array())
                   19545:     {
                   19546:         $params['table_data'] = array();
                   19547:         $params['widest']     = array();  // indexed by column
                   19548:         $params['highest']    = array(); // indexed by row
                   19549:         $params['ncols']      = 0;
                   19550:         $this->params         = $params;
                   19551:     }
                   19552: 
                   19553:     function _tableRow($columns, $rowparams = array(), $colparams = array())
                   19554:     {
                   19555:         $highest = 1;
                   19556:         for ($i = 0; $i < count($columns); $i++) {
                   19557:             $col = &$columns[$i];
                   19558:             if (isset($colparams[$i]) && !empty($colparams[$i]['wrap'])) {
                   19559:                 $col = wordwrap($col, $colparams[$i]['wrap']);
                   19560:             }
                   19561: 
                   19562:             if (strpos($col, "\n") !== false) {
                   19563:                 $multiline = explode("\n", $col);
                   19564:                 $w = 0;
                   19565:                 foreach ($multiline as $n => $line) {
                   19566:                     $len = strlen($line);
                   19567:                     if ($len > $w) {
                   19568:                         $w = $len;
                   19569:                     }
                   19570:                 }
                   19571:                 $lines = count($multiline);
                   19572:             } else {
                   19573:                 $w = strlen($col);
                   19574:             }
                   19575: 
                   19576:             if (isset($this->params['widest'][$i])) {
                   19577:                 if ($w > $this->params['widest'][$i]) {
                   19578:                     $this->params['widest'][$i] = $w;
                   19579:                 }
                   19580:             } else {
                   19581:                 $this->params['widest'][$i] = $w;
                   19582:             }
                   19583: 
                   19584:             $tmp = count_chars($columns[$i], 1);
                   19585:             // handle unix, mac and windows formats
                   19586:             $lines = (isset($tmp[10]) ? $tmp[10] : (isset($tmp[13]) ? $tmp[13] : 0)) + 1;
                   19587:             if ($lines > $highest) {
                   19588:                 $highest = $lines;
                   19589:             }
                   19590:         }
                   19591: 
                   19592:         if (count($columns) > $this->params['ncols']) {
                   19593:             $this->params['ncols'] = count($columns);
                   19594:         }
                   19595: 
                   19596:         $new_row = array(
                   19597:             'data'      => $columns,
                   19598:             'height'    => $highest,
                   19599:             'rowparams' => $rowparams,
                   19600:             'colparams' => $colparams,
                   19601:         );
                   19602:         $this->params['table_data'][] = $new_row;
                   19603:     }
                   19604: 
                   19605:     function _endTable()
                   19606:     {
                   19607:         extract($this->params);
                   19608:         if (!empty($caption)) {
                   19609:             $this->_displayHeading($caption);
                   19610:         }
                   19611: 
                   19612:         if (count($table_data) === 0) {
                   19613:             return;
                   19614:         }
                   19615: 
                   19616:         if (!isset($width)) {
                   19617:             $width = $widest;
                   19618:         } else {
                   19619:             for ($i = 0; $i < $ncols; $i++) {
                   19620:                 if (!isset($width[$i])) {
                   19621:                     $width[$i] = $widest[$i];
                   19622:                 }
                   19623:             }
                   19624:         }
                   19625: 
                   19626:         $border = false;
                   19627:         if (empty($border)) {
                   19628:             $cellstart  = '';
                   19629:             $cellend    = ' ';
                   19630:             $rowend     = '';
                   19631:             $padrowend  = false;
                   19632:             $borderline = '';
                   19633:         } else {
                   19634:             $cellstart  = '| ';
                   19635:             $cellend    = ' ';
                   19636:             $rowend     = '|';
                   19637:             $padrowend  = true;
                   19638:             $borderline = '+';
                   19639:             foreach ($width as $w) {
                   19640:                 $borderline .= str_repeat('-', $w + strlen($cellstart) + strlen($cellend) - 1);
                   19641:                 $borderline .= '+';
                   19642:             }
                   19643:         }
                   19644: 
                   19645:         if ($borderline) {
                   19646:             $this->_displayLine($borderline);
                   19647:         }
                   19648: 
                   19649:         for ($i = 0; $i < count($table_data); $i++) {
                   19650:             extract($table_data[$i]);
                   19651:             if (!is_array($rowparams)) {
                   19652:                 $rowparams = array();
                   19653:             }
                   19654: 
                   19655:             if (!is_array($colparams)) {
                   19656:                 $colparams = array();
                   19657:             }
                   19658: 
                   19659:             $rowlines = array();
                   19660:             if ($height > 1) {
                   19661:                 for ($c = 0; $c < count($data); $c++) {
                   19662:                     $rowlines[$c] = preg_split('/(\r?\n|\r)/', $data[$c]);
                   19663:                     if (count($rowlines[$c]) < $height) {
                   19664:                         $rowlines[$c] = array_pad($rowlines[$c], $height, '');
                   19665:                     }
                   19666:                 }
                   19667:             } else {
                   19668:                 for ($c = 0; $c < count($data); $c++) {
                   19669:                     $rowlines[$c] = array($data[$c]);
                   19670:                 }
                   19671:             }
                   19672: 
                   19673:             for ($r = 0; $r < $height; $r++) {
                   19674:                 $rowtext = '';
                   19675:                 for ($c = 0; $c < count($data); $c++) {
                   19676:                     if (isset($colparams[$c])) {
                   19677:                         $attribs = array_merge($rowparams, $colparams);
                   19678:                     } else {
                   19679:                         $attribs = $rowparams;
                   19680:                     }
                   19681: 
                   19682:                     $w = isset($width[$c]) ? $width[$c] : 0;
                   19683:                     //$cell = $data[$c];
                   19684:                     $cell = $rowlines[$c][$r];
                   19685:                     $l = strlen($cell);
                   19686:                     if ($l > $w) {
                   19687:                         $cell = substr($cell, 0, $w);
                   19688:                     }
                   19689: 
                   19690:                     if (isset($attribs['bold'])) {
                   19691:                         $cell = $this->bold($cell);
                   19692:                     }
                   19693: 
                   19694:                     if ($l < $w) {
                   19695:                         // not using str_pad here because we may
                   19696:                         // add bold escape characters to $cell
                   19697:                         $cell .= str_repeat(' ', $w - $l);
                   19698:                     }
                   19699: 
                   19700:                     $rowtext .= $cellstart . $cell . $cellend;
                   19701:                 }
                   19702: 
                   19703:                 if (!$border) {
                   19704:                     $rowtext = rtrim($rowtext);
                   19705:                 }
                   19706: 
                   19707:                 $rowtext .= $rowend;
                   19708:                 $this->_displayLine($rowtext);
                   19709:             }
                   19710:         }
                   19711: 
                   19712:         if ($borderline) {
                   19713:             $this->_displayLine($borderline);
                   19714:         }
                   19715:     }
                   19716: 
                   19717:     function _displayLine($text)
                   19718:     {
                   19719:         print "$this->lp$text\n";
                   19720:     }
                   19721: 
                   19722:     function _display($text)
                   19723:     {
                   19724:         print $text;
                   19725:     }
1.1.1.2 ! misho    19726: }PEAR-1.9.4/PEAR/Installer/Role/Common.php0000644000076500000240000001423311605156614016565 0ustar  helgistaff<?php
1.1       misho    19727: /**
                   19728:  * Base class for all installation roles.
                   19729:  *
                   19730:  * PHP versions 4 and 5
                   19731:  *
                   19732:  * @category   pear
                   19733:  * @package    PEAR
                   19734:  * @author     Greg Beaver <cellog@php.net>
                   19735:  * @copyright  1997-2006 The PHP Group
                   19736:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   19737:  * @version    CVS: $Id: Common.php 313023 2011-07-06 19:17:11Z dufuz $
                   19738:  * @link       http://pear.php.net/package/PEAR
                   19739:  * @since      File available since Release 1.4.0a1
                   19740:  */
                   19741: /**
                   19742:  * Base class for all installation roles.
                   19743:  *
                   19744:  * This class allows extensibility of file roles.  Packages with complex
                   19745:  * customization can now provide custom file roles along with the possibility of
                   19746:  * adding configuration values to match.
                   19747:  * @category   pear
                   19748:  * @package    PEAR
                   19749:  * @author     Greg Beaver <cellog@php.net>
                   19750:  * @copyright  1997-2006 The PHP Group
                   19751:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   19752:  * @version    Release: 1.9.4
                   19753:  * @link       http://pear.php.net/package/PEAR
                   19754:  * @since      Class available since Release 1.4.0a1
                   19755:  */
                   19756: class PEAR_Installer_Role_Common
                   19757: {
                   19758:     /**
                   19759:      * @var PEAR_Config
                   19760:      * @access protected
                   19761:      */
                   19762:     var $config;
                   19763: 
                   19764:     /**
                   19765:      * @param PEAR_Config
                   19766:      */
                   19767:     function PEAR_Installer_Role_Common(&$config)
                   19768:     {
                   19769:         $this->config = $config;
                   19770:     }
                   19771: 
                   19772:     /**
                   19773:      * Retrieve configuration information about a file role from its XML info
                   19774:      *
                   19775:      * @param string $role Role Classname, as in "PEAR_Installer_Role_Data"
                   19776:      * @return array
                   19777:      */
                   19778:     function getInfo($role)
                   19779:     {
                   19780:         if (empty($GLOBALS['_PEAR_INSTALLER_ROLES'][$role])) {
                   19781:             return PEAR::raiseError('Unknown Role class: "' . $role . '"');
                   19782:         }
                   19783:         return $GLOBALS['_PEAR_INSTALLER_ROLES'][$role];
                   19784:     }
                   19785: 
                   19786:     /**
                   19787:      * This is called for each file to set up the directories and files
                   19788:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   19789:      * @param array attributes from the <file> tag
                   19790:      * @param string file name
                   19791:      * @return array an array consisting of:
                   19792:      *
                   19793:      *    1 the original, pre-baseinstalldir installation directory
                   19794:      *    2 the final installation directory
                   19795:      *    3 the full path to the final location of the file
                   19796:      *    4 the location of the pre-installation file
                   19797:      */
                   19798:     function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null)
                   19799:     {
                   19800:         $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . 
                   19801:             ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
                   19802:         if (PEAR::isError($roleInfo)) {
                   19803:             return $roleInfo;
                   19804:         }
                   19805:         if (!$roleInfo['locationconfig']) {
                   19806:             return false;
                   19807:         }
                   19808:         if ($roleInfo['honorsbaseinstall']) {
                   19809:             $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'], $layer,
                   19810:                 $pkg->getChannel());
                   19811:             if (!empty($atts['baseinstalldir'])) {
                   19812:                 $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
                   19813:             }
                   19814:         } elseif ($roleInfo['unusualbaseinstall']) {
                   19815:             $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'],
                   19816:                     $layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage();
                   19817:             if (!empty($atts['baseinstalldir'])) {
                   19818:                 $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
                   19819:             }
                   19820:         } else {
                   19821:             $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'],
                   19822:                     $layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage();
                   19823:         }
                   19824:         if (dirname($file) != '.' && empty($atts['install-as'])) {
                   19825:             $dest_dir .= DIRECTORY_SEPARATOR . dirname($file);
                   19826:         }
                   19827:         if (empty($atts['install-as'])) {
                   19828:             $dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file);
                   19829:         } else {
                   19830:             $dest_file = $dest_dir . DIRECTORY_SEPARATOR . $atts['install-as'];
                   19831:         }
                   19832:         $orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file;
                   19833: 
                   19834:         // Clean up the DIRECTORY_SEPARATOR mess
                   19835:         $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
                   19836:         
                   19837:         list($dest_dir, $dest_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"),
                   19838:                                                     array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR,
                   19839:                                                           DIRECTORY_SEPARATOR),
                   19840:                                                     array($dest_dir, $dest_file, $orig_file));
                   19841:         return array($save_destdir, $dest_dir, $dest_file, $orig_file);
                   19842:     }
                   19843: 
                   19844:     /**
                   19845:      * Get the name of the configuration variable that specifies the location of this file
                   19846:      * @return string|false
                   19847:      */
                   19848:     function getLocationConfig()
                   19849:     {
                   19850:         $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . 
                   19851:             ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
                   19852:         if (PEAR::isError($roleInfo)) {
                   19853:             return $roleInfo;
                   19854:         }
                   19855:         return $roleInfo['locationconfig'];
                   19856:     }
                   19857: 
                   19858:     /**
                   19859:      * Do any unusual setup here
                   19860:      * @param PEAR_Installer
                   19861:      * @param PEAR_PackageFile_v2
                   19862:      * @param array file attributes
                   19863:      * @param string file name
                   19864:      */
                   19865:     function setup(&$installer, $pkg, $atts, $file)
                   19866:     {
                   19867:     }
                   19868: 
                   19869:     function isExecutable()
                   19870:     {
                   19871:         $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . 
                   19872:             ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
                   19873:         if (PEAR::isError($roleInfo)) {
                   19874:             return $roleInfo;
                   19875:         }
                   19876:         return $roleInfo['executable'];
                   19877:     }
                   19878: 
                   19879:     function isInstallable()
                   19880:     {
                   19881:         $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . 
                   19882:             ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
                   19883:         if (PEAR::isError($roleInfo)) {
                   19884:             return $roleInfo;
                   19885:         }
                   19886:         return $roleInfo['installable'];
                   19887:     }
                   19888: 
                   19889:     function isExtension()
                   19890:     {
                   19891:         $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . 
                   19892:             ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
                   19893:         if (PEAR::isError($roleInfo)) {
                   19894:             return $roleInfo;
                   19895:         }
                   19896:         return $roleInfo['phpextension'];
                   19897:     }
                   19898: }
1.1.1.2 ! misho    19899: ?>PEAR-1.9.4/PEAR/Installer/Role/Cfg.xml0000644000076500000240000000064511605156614016047 0ustar  helgistaff<role version="1.0">
1.1       misho    19900:  <releasetypes>php</releasetypes>
                   19901:  <releasetypes>extsrc</releasetypes>
                   19902:  <releasetypes>extbin</releasetypes>
                   19903:  <releasetypes>zendextsrc</releasetypes>
                   19904:  <releasetypes>zendextbin</releasetypes>
                   19905:  <installable>1</installable>
                   19906:  <locationconfig>cfg_dir</locationconfig>
                   19907:  <honorsbaseinstall />
                   19908:  <unusualbaseinstall>1</unusualbaseinstall>
                   19909:  <phpfile />
                   19910:  <executable />
                   19911:  <phpextension />
                   19912:  <config_vars />
1.1.1.2 ! misho    19913: </role>PEAR-1.9.4/PEAR/Installer/Role/Cfg.php0000644000076500000240000000770211605156614016037 0ustar  helgistaff<?php
1.1       misho    19914: /**
                   19915:  * PEAR_Installer_Role_Cfg
                   19916:  *
                   19917:  * PHP versions 4 and 5
                   19918:  *
                   19919:  * @category   pear
                   19920:  * @package    PEAR
                   19921:  * @author     Greg Beaver <cellog@php.net>
                   19922:  * @copyright  2007-2009 The Authors
                   19923:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   19924:  * @version    CVS: $Id: Cfg.php 313023 2011-07-06 19:17:11Z dufuz $
                   19925:  * @link       http://pear.php.net/package/PEAR
                   19926:  * @since      File available since Release 1.7.0
                   19927:  */
                   19928: 
                   19929: /**
                   19930:  * @category   pear
                   19931:  * @package    PEAR
                   19932:  * @author     Greg Beaver <cellog@php.net>
                   19933:  * @copyright  2007-2009 The Authors
                   19934:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   19935:  * @version    Release: 1.9.4
                   19936:  * @link       http://pear.php.net/package/PEAR
                   19937:  * @since      Class available since Release 1.7.0
                   19938:  */
                   19939: class PEAR_Installer_Role_Cfg extends PEAR_Installer_Role_Common
                   19940: {
                   19941:     /**
                   19942:      * @var PEAR_Installer
                   19943:      */
                   19944:     var $installer;
                   19945: 
                   19946:     /**
                   19947:      * the md5 of the original file
                   19948:      *
                   19949:      * @var unknown_type
                   19950:      */
                   19951:     var $md5 = null;
                   19952: 
                   19953:     /**
                   19954:      * Do any unusual setup here
                   19955:      * @param PEAR_Installer
                   19956:      * @param PEAR_PackageFile_v2
                   19957:      * @param array file attributes
                   19958:      * @param string file name
                   19959:      */
                   19960:     function setup(&$installer, $pkg, $atts, $file)
                   19961:     {
                   19962:         $this->installer = &$installer;
                   19963:         $reg = &$this->installer->config->getRegistry();
                   19964:         $package = $reg->getPackage($pkg->getPackage(), $pkg->getChannel());
                   19965:         if ($package) {
                   19966:             $filelist = $package->getFilelist();
                   19967:             if (isset($filelist[$file]) && isset($filelist[$file]['md5sum'])) {
                   19968:                 $this->md5 = $filelist[$file]['md5sum'];
                   19969:             }
                   19970:         }
                   19971:     }
                   19972: 
                   19973:     function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null)
                   19974:     {
                   19975:         $test = parent::processInstallation($pkg, $atts, $file, $tmp_path, $layer);
                   19976:         if (@file_exists($test[2]) && @file_exists($test[3])) {
                   19977:             $md5 = md5_file($test[2]);
                   19978:             // configuration has already been installed, check for mods
                   19979:             if ($md5 !== $this->md5 && $md5 !== md5_file($test[3])) {
                   19980:                 // configuration has been modified, so save our version as
                   19981:                 // configfile-version
                   19982:                 $old = $test[2];
                   19983:                 $test[2] .= '.new-' . $pkg->getVersion();
                   19984:                 // backup original and re-install it
                   19985:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   19986:                 $tmpcfg = $this->config->get('temp_dir');
                   19987:                 $newloc = System::mkdir(array('-p', $tmpcfg));
                   19988:                 if (!$newloc) {
                   19989:                     // try temp_dir
                   19990:                     $newloc = System::mktemp(array('-d'));
                   19991:                     if (!$newloc || PEAR::isError($newloc)) {
                   19992:                         PEAR::popErrorHandling();
                   19993:                         return PEAR::raiseError('Could not save existing configuration file '.
                   19994:                             $old . ', unable to install.  Please set temp_dir ' .
                   19995:                             'configuration variable to a writeable location and try again');
                   19996:                     }
                   19997:                 } else {
                   19998:                     $newloc = $tmpcfg;
                   19999:                 }
                   20000: 
                   20001:                 $temp_file = $newloc . DIRECTORY_SEPARATOR . uniqid('savefile');
                   20002:                 if (!@copy($old, $temp_file)) {
                   20003:                     PEAR::popErrorHandling();
                   20004:                     return PEAR::raiseError('Could not save existing configuration file '.
                   20005:                         $old . ', unable to install.  Please set temp_dir ' .
                   20006:                         'configuration variable to a writeable location and try again');
                   20007:                 }
                   20008: 
                   20009:                 PEAR::popErrorHandling();
                   20010:                 $this->installer->log(0, "WARNING: configuration file $old is being installed as $test[2], you should manually merge in changes to the existing configuration file");
                   20011:                 $this->installer->addFileOperation('rename', array($temp_file, $old, false));
                   20012:                 $this->installer->addFileOperation('delete', array($temp_file));
                   20013:             }
                   20014:         }
                   20015: 
                   20016:         return $test;
                   20017:     }
1.1.1.2 ! misho    20018: }PEAR-1.9.4/PEAR/Installer/Role/Data.xml0000644000076500000240000000062211605156614016214 0ustar  helgistaff<role version="1.0">
1.1       misho    20019:  <releasetypes>php</releasetypes>
                   20020:  <releasetypes>extsrc</releasetypes>
                   20021:  <releasetypes>extbin</releasetypes>
                   20022:  <releasetypes>zendextsrc</releasetypes>
                   20023:  <releasetypes>zendextbin</releasetypes>
                   20024:  <installable>1</installable>
                   20025:  <locationconfig>data_dir</locationconfig>
                   20026:  <honorsbaseinstall />
                   20027:  <unusualbaseinstall />
                   20028:  <phpfile />
                   20029:  <executable />
                   20030:  <phpextension />
                   20031:  <config_vars />
1.1.1.2 ! misho    20032: </role>PEAR-1.9.4/PEAR/Installer/Role/Data.php0000644000076500000240000000152311605156614016204 0ustar  helgistaff<?php
1.1       misho    20033: /**
                   20034:  * PEAR_Installer_Role_Data
                   20035:  *
                   20036:  * PHP versions 4 and 5
                   20037:  *
                   20038:  * @category   pear
                   20039:  * @package    PEAR
                   20040:  * @author     Greg Beaver <cellog@php.net>
                   20041:  * @copyright  1997-2009 The Authors
                   20042:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20043:  * @version    CVS: $Id: Data.php 313023 2011-07-06 19:17:11Z dufuz $
                   20044:  * @link       http://pear.php.net/package/PEAR
                   20045:  * @since      File available since Release 1.4.0a1
                   20046:  */
                   20047: 
                   20048: /**
                   20049:  * @category   pear
                   20050:  * @package    PEAR
                   20051:  * @author     Greg Beaver <cellog@php.net>
                   20052:  * @copyright  1997-2009 The Authors
                   20053:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20054:  * @version    Release: 1.9.4
                   20055:  * @link       http://pear.php.net/package/PEAR
                   20056:  * @since      Class available since Release 1.4.0a1
                   20057:  */
                   20058: class PEAR_Installer_Role_Data extends PEAR_Installer_Role_Common {}
1.1.1.2 ! misho    20059: ?>PEAR-1.9.4/PEAR/Installer/Role/Doc.xml0000644000076500000240000000062111605156614016047 0ustar  helgistaff<role version="1.0">
1.1       misho    20060:  <releasetypes>php</releasetypes>
                   20061:  <releasetypes>extsrc</releasetypes>
                   20062:  <releasetypes>extbin</releasetypes>
                   20063:  <releasetypes>zendextsrc</releasetypes>
                   20064:  <releasetypes>zendextbin</releasetypes>
                   20065:  <installable>1</installable>
                   20066:  <locationconfig>doc_dir</locationconfig>
                   20067:  <honorsbaseinstall />
                   20068:  <unusualbaseinstall />
                   20069:  <phpfile />
                   20070:  <executable />
                   20071:  <phpextension />
                   20072:  <config_vars />
1.1.1.2 ! misho    20073: </role>PEAR-1.9.4/PEAR/Installer/Role/Doc.php0000644000076500000240000000152011605156614016035 0ustar  helgistaff<?php
1.1       misho    20074: /**
                   20075:  * PEAR_Installer_Role_Doc
                   20076:  *
                   20077:  * PHP versions 4 and 5
                   20078:  *
                   20079:  * @category   pear
                   20080:  * @package    PEAR
                   20081:  * @author     Greg Beaver <cellog@php.net>
                   20082:  * @copyright  1997-2009 The Authors
                   20083:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20084:  * @version    CVS: $Id: Doc.php 313023 2011-07-06 19:17:11Z dufuz $
                   20085:  * @link       http://pear.php.net/package/PEAR
                   20086:  * @since      File available since Release 1.4.0a1
                   20087:  */
                   20088: 
                   20089: /**
                   20090:  * @category   pear
                   20091:  * @package    PEAR
                   20092:  * @author     Greg Beaver <cellog@php.net>
                   20093:  * @copyright  1997-2009 The Authors
                   20094:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20095:  * @version    Release: 1.9.4
                   20096:  * @link       http://pear.php.net/package/PEAR
                   20097:  * @since      Class available since Release 1.4.0a1
                   20098:  */
                   20099: class PEAR_Installer_Role_Doc extends PEAR_Installer_Role_Common {}
1.1.1.2 ! misho    20100: ?>PEAR-1.9.4/PEAR/Installer/Role/Ext.xml0000644000076500000240000000050211605156614016100 0ustar  helgistaff<role version="1.0">
1.1       misho    20101:  <releasetypes>extbin</releasetypes>
                   20102:  <releasetypes>zendextbin</releasetypes>
                   20103:  <installable>1</installable>
                   20104:  <locationconfig>ext_dir</locationconfig>
                   20105:  <honorsbaseinstall>1</honorsbaseinstall>
                   20106:  <unusualbaseinstall />
                   20107:  <phpfile />
                   20108:  <executable />
                   20109:  <phpextension>1</phpextension>
                   20110:  <config_vars />
1.1.1.2 ! misho    20111: </role>PEAR-1.9.4/PEAR/Installer/Role/Ext.php0000644000076500000240000000152011605156614016070 0ustar  helgistaff<?php
1.1       misho    20112: /**
                   20113:  * PEAR_Installer_Role_Ext
                   20114:  *
                   20115:  * PHP versions 4 and 5
                   20116:  *
                   20117:  * @category   pear
                   20118:  * @package    PEAR
                   20119:  * @author     Greg Beaver <cellog@php.net>
                   20120:  * @copyright  1997-2009 The Authors
                   20121:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20122:  * @version    CVS: $Id: Ext.php 313023 2011-07-06 19:17:11Z dufuz $
                   20123:  * @link       http://pear.php.net/package/PEAR
                   20124:  * @since      File available since Release 1.4.0a1
                   20125:  */
                   20126: 
                   20127: /**
                   20128:  * @category   pear
                   20129:  * @package    PEAR
                   20130:  * @author     Greg Beaver <cellog@php.net>
                   20131:  * @copyright  1997-2009 The Authors
                   20132:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20133:  * @version    Release: 1.9.4
                   20134:  * @link       http://pear.php.net/package/PEAR
                   20135:  * @since      Class available since Release 1.4.0a1
                   20136:  */
                   20137: class PEAR_Installer_Role_Ext extends PEAR_Installer_Role_Common {}
1.1.1.2 ! misho    20138: ?>PEAR-1.9.4/PEAR/Installer/Role/Php.xml0000644000076500000240000000065511605156614016100 0ustar  helgistaff<role version="1.0">
1.1       misho    20139:  <releasetypes>php</releasetypes>
                   20140:  <releasetypes>extsrc</releasetypes>
                   20141:  <releasetypes>extbin</releasetypes>
                   20142:  <releasetypes>zendextsrc</releasetypes>
                   20143:  <releasetypes>zendextbin</releasetypes>
                   20144:  <installable>1</installable>
                   20145:  <locationconfig>php_dir</locationconfig>
                   20146:  <honorsbaseinstall>1</honorsbaseinstall>
                   20147:  <unusualbaseinstall />
                   20148:  <phpfile>1</phpfile>
                   20149:  <executable />
                   20150:  <phpextension />
                   20151:  <config_vars />
1.1.1.2 ! misho    20152: </role>PEAR-1.9.4/PEAR/Installer/Role/Php.php0000644000076500000240000000152011605156614016057 0ustar  helgistaff<?php
1.1       misho    20153: /**
                   20154:  * PEAR_Installer_Role_Php
                   20155:  *
                   20156:  * PHP versions 4 and 5
                   20157:  *
                   20158:  * @category   pear
                   20159:  * @package    PEAR
                   20160:  * @author     Greg Beaver <cellog@php.net>
                   20161:  * @copyright  1997-2009 The Authors
                   20162:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20163:  * @version    CVS: $Id: Php.php 313023 2011-07-06 19:17:11Z dufuz $
                   20164:  * @link       http://pear.php.net/package/PEAR
                   20165:  * @since      File available since Release 1.4.0a1
                   20166:  */
                   20167: 
                   20168: /**
                   20169:  * @category   pear
                   20170:  * @package    PEAR
                   20171:  * @author     Greg Beaver <cellog@php.net>
                   20172:  * @copyright  1997-2009 The Authors
                   20173:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20174:  * @version    Release: 1.9.4
                   20175:  * @link       http://pear.php.net/package/PEAR
                   20176:  * @since      Class available since Release 1.4.0a1
                   20177:  */
                   20178: class PEAR_Installer_Role_Php extends PEAR_Installer_Role_Common {}
1.1.1.2 ! misho    20179: ?>PEAR-1.9.4/PEAR/Installer/Role/Script.xml0000644000076500000240000000066011605156614016611 0ustar  helgistaff<role version="1.0">
1.1       misho    20180:  <releasetypes>php</releasetypes>
                   20181:  <releasetypes>extsrc</releasetypes>
                   20182:  <releasetypes>extbin</releasetypes>
                   20183:  <releasetypes>zendextsrc</releasetypes>
                   20184:  <releasetypes>zendextbin</releasetypes>
                   20185:  <installable>1</installable>
                   20186:  <locationconfig>bin_dir</locationconfig>
                   20187:  <honorsbaseinstall>1</honorsbaseinstall>
                   20188:  <unusualbaseinstall />
                   20189:  <phpfile />
                   20190:  <executable>1</executable>
                   20191:  <phpextension />
                   20192:  <config_vars />
1.1.1.2 ! misho    20193: </role>PEAR-1.9.4/PEAR/Installer/Role/Script.php0000644000076500000240000000153111605156614016576 0ustar  helgistaff<?php
1.1       misho    20194: /**
                   20195:  * PEAR_Installer_Role_Script
                   20196:  *
                   20197:  * PHP versions 4 and 5
                   20198:  *
                   20199:  * @category   pear
                   20200:  * @package    PEAR
                   20201:  * @author     Greg Beaver <cellog@php.net>
                   20202:  * @copyright  1997-2009 The Authors
                   20203:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20204:  * @version    CVS: $Id: Script.php 313023 2011-07-06 19:17:11Z dufuz $
                   20205:  * @link       http://pear.php.net/package/PEAR
                   20206:  * @since      File available since Release 1.4.0a1
                   20207:  */
                   20208: 
                   20209: /**
                   20210:  * @category   pear
                   20211:  * @package    PEAR
                   20212:  * @author     Greg Beaver <cellog@php.net>
                   20213:  * @copyright  1997-2009 The Authors
                   20214:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20215:  * @version    Release: 1.9.4
                   20216:  * @link       http://pear.php.net/package/PEAR
                   20217:  * @since      Class available since Release 1.4.0a1
                   20218:  */
                   20219: class PEAR_Installer_Role_Script extends PEAR_Installer_Role_Common {}
1.1.1.2 ! misho    20220: ?>PEAR-1.9.4/PEAR/Installer/Role/Src.xml0000644000076500000240000000044211605156614016072 0ustar  helgistaff<role version="1.0">
1.1       misho    20221:  <releasetypes>extsrc</releasetypes>
                   20222:  <releasetypes>zendextsrc</releasetypes>
                   20223:  <installable>1</installable>
                   20224:  <locationconfig>temp_dir</locationconfig>
                   20225:  <honorsbaseinstall />
                   20226:  <unusualbaseinstall />
                   20227:  <phpfile />
                   20228:  <executable />
                   20229:  <phpextension />
                   20230:  <config_vars />
1.1.1.2 ! misho    20231: </role>PEAR-1.9.4/PEAR/Installer/Role/Src.php0000644000076500000240000000166511605156614016071 0ustar  helgistaff<?php
1.1       misho    20232: /**
                   20233:  * PEAR_Installer_Role_Src
                   20234:  *
                   20235:  * PHP versions 4 and 5
                   20236:  *
                   20237:  * @category   pear
                   20238:  * @package    PEAR
                   20239:  * @author     Greg Beaver <cellog@php.net>
                   20240:  * @copyright  1997-2009 The Authors
                   20241:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20242:  * @version    CVS: $Id: Src.php 313023 2011-07-06 19:17:11Z dufuz $
                   20243:  * @link       http://pear.php.net/package/PEAR
                   20244:  * @since      File available since Release 1.4.0a1
                   20245:  */
                   20246: 
                   20247: /**
                   20248:  * @category   pear
                   20249:  * @package    PEAR
                   20250:  * @author     Greg Beaver <cellog@php.net>
                   20251:  * @copyright  1997-2009 The Authors
                   20252:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20253:  * @version    Release: 1.9.4
                   20254:  * @link       http://pear.php.net/package/PEAR
                   20255:  * @since      Class available since Release 1.4.0a1
                   20256:  */
                   20257: class PEAR_Installer_Role_Src extends PEAR_Installer_Role_Common
                   20258: {
                   20259:     function setup(&$installer, $pkg, $atts, $file)
                   20260:     {
                   20261:         $installer->source_files++;
                   20262:     }
                   20263: }
1.1.1.2 ! misho    20264: ?>PEAR-1.9.4/PEAR/Installer/Role/Test.xml0000644000076500000240000000062211605156614016262 0ustar  helgistaff<role version="1.0">
1.1       misho    20265:  <releasetypes>php</releasetypes>
                   20266:  <releasetypes>extsrc</releasetypes>
                   20267:  <releasetypes>extbin</releasetypes>
                   20268:  <releasetypes>zendextsrc</releasetypes>
                   20269:  <releasetypes>zendextbin</releasetypes>
                   20270:  <installable>1</installable>
                   20271:  <locationconfig>test_dir</locationconfig>
                   20272:  <honorsbaseinstall />
                   20273:  <unusualbaseinstall />
                   20274:  <phpfile />
                   20275:  <executable />
                   20276:  <phpextension />
                   20277:  <config_vars />
1.1.1.2 ! misho    20278: </role>PEAR-1.9.4/PEAR/Installer/Role/Test.php0000644000076500000240000000152311605156614016252 0ustar  helgistaff<?php
1.1       misho    20279: /**
                   20280:  * PEAR_Installer_Role_Test
                   20281:  *
                   20282:  * PHP versions 4 and 5
                   20283:  *
                   20284:  * @category   pear
                   20285:  * @package    PEAR
                   20286:  * @author     Greg Beaver <cellog@php.net>
                   20287:  * @copyright  1997-2009 The Authors
                   20288:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20289:  * @version    CVS: $Id: Test.php 313023 2011-07-06 19:17:11Z dufuz $
                   20290:  * @link       http://pear.php.net/package/PEAR
                   20291:  * @since      File available since Release 1.4.0a1
                   20292:  */
                   20293: 
                   20294: /**
                   20295:  * @category   pear
                   20296:  * @package    PEAR
                   20297:  * @author     Greg Beaver <cellog@php.net>
                   20298:  * @copyright  1997-2009 The Authors
                   20299:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20300:  * @version    Release: 1.9.4
                   20301:  * @link       http://pear.php.net/package/PEAR
                   20302:  * @since      Class available since Release 1.4.0a1
                   20303:  */
                   20304: class PEAR_Installer_Role_Test extends PEAR_Installer_Role_Common {}
1.1.1.2 ! misho    20305: ?>PEAR-1.9.4/PEAR/Installer/Role/Www.xml0000644000076500000240000000064411605156614016133 0ustar  helgistaff<role version="1.0">
1.1       misho    20306:  <releasetypes>php</releasetypes>
                   20307:  <releasetypes>extsrc</releasetypes>
                   20308:  <releasetypes>extbin</releasetypes>
                   20309:  <releasetypes>zendextsrc</releasetypes>
                   20310:  <releasetypes>zendextbin</releasetypes>
                   20311:  <installable>1</installable>
                   20312:  <locationconfig>www_dir</locationconfig>
                   20313:  <honorsbaseinstall>1</honorsbaseinstall>
                   20314:  <unusualbaseinstall />
                   20315:  <phpfile />
                   20316:  <executable />
                   20317:  <phpextension />
                   20318:  <config_vars />
1.1.1.2 ! misho    20319: </role>PEAR-1.9.4/PEAR/Installer/Role/Www.php0000644000076500000240000000151411605156614016117 0ustar  helgistaff<?php
1.1       misho    20320: /**
                   20321:  * PEAR_Installer_Role_Www
                   20322:  *
                   20323:  * PHP versions 4 and 5
                   20324:  *
                   20325:  * @category   pear
                   20326:  * @package    PEAR
                   20327:  * @author     Greg Beaver <cellog@php.net>
                   20328:  * @copyright  2007-2009 The Authors
                   20329:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20330:  * @version    CVS: $Id: Www.php 313023 2011-07-06 19:17:11Z dufuz $
                   20331:  * @link       http://pear.php.net/package/PEAR
                   20332:  * @since      File available since Release 1.7.0
                   20333:  */
                   20334: 
                   20335: /**
                   20336:  * @category   pear
                   20337:  * @package    PEAR
                   20338:  * @author     Greg Beaver <cellog@php.net>
                   20339:  * @copyright  2007-2009 The Authors
                   20340:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20341:  * @version    Release: 1.9.4
                   20342:  * @link       http://pear.php.net/package/PEAR
                   20343:  * @since      Class available since Release 1.7.0
                   20344:  */
                   20345: class PEAR_Installer_Role_Www extends PEAR_Installer_Role_Common {}
1.1.1.2 ! misho    20346: ?>PEAR-1.9.4/PEAR/Installer/Role.php0000644000076500000240000001746411605156614015346 0ustar  helgistaff<?php
1.1       misho    20347: /**
                   20348:  * PEAR_Installer_Role
                   20349:  *
                   20350:  * PHP versions 4 and 5
                   20351:  *
                   20352:  * @category   pear
                   20353:  * @package    PEAR
                   20354:  * @author     Greg Beaver <cellog@php.net>
                   20355:  * @copyright  1997-2009 The Authors
                   20356:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20357:  * @version    CVS: $Id: Role.php 313023 2011-07-06 19:17:11Z dufuz $
                   20358:  * @link       http://pear.php.net/package/PEAR
                   20359:  * @since      File available since Release 1.4.0a1
                   20360:  */
                   20361: 
                   20362: /**
                   20363:  * base class for installer roles
                   20364:  */
                   20365: require_once 'PEAR/Installer/Role/Common.php';
                   20366: require_once 'PEAR/XMLParser.php';
                   20367: /**
                   20368:  * @category   pear
                   20369:  * @package    PEAR
                   20370:  * @author     Greg Beaver <cellog@php.net>
                   20371:  * @copyright  1997-2009 The Authors
                   20372:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20373:  * @version    Release: 1.9.4
                   20374:  * @link       http://pear.php.net/package/PEAR
                   20375:  * @since      Class available since Release 1.4.0a1
                   20376:  */
                   20377: class PEAR_Installer_Role
                   20378: {
                   20379:     /**
                   20380:      * Set up any additional configuration variables that file roles require
                   20381:      *
                   20382:      * Never call this directly, it is called by the PEAR_Config constructor
                   20383:      * @param PEAR_Config
                   20384:      * @access private
                   20385:      * @static
                   20386:      */
                   20387:     function initializeConfig(&$config)
                   20388:     {
                   20389:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
                   20390:             PEAR_Installer_Role::registerRoles();
                   20391:         }
                   20392: 
                   20393:         foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $class => $info) {
                   20394:             if (!$info['config_vars']) {
                   20395:                 continue;
                   20396:             }
                   20397: 
                   20398:             $config->_addConfigVars($class, $info['config_vars']);
                   20399:         }
                   20400:     }
                   20401: 
                   20402:     /**
                   20403:      * @param PEAR_PackageFile_v2
                   20404:      * @param string role name
                   20405:      * @param PEAR_Config
                   20406:      * @return PEAR_Installer_Role_Common
                   20407:      * @static
                   20408:      */
                   20409:     function &factory($pkg, $role, &$config)
                   20410:     {
                   20411:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
                   20412:             PEAR_Installer_Role::registerRoles();
                   20413:         }
                   20414: 
                   20415:         if (!in_array($role, PEAR_Installer_Role::getValidRoles($pkg->getPackageType()))) {
                   20416:             $a = false;
                   20417:             return $a;
                   20418:         }
                   20419: 
                   20420:         $a = 'PEAR_Installer_Role_' . ucfirst($role);
                   20421:         if (!class_exists($a)) {
                   20422:             require_once str_replace('_', '/', $a) . '.php';
                   20423:         }
                   20424: 
                   20425:         $b = new $a($config);
                   20426:         return $b;
                   20427:     }
                   20428: 
                   20429:     /**
                   20430:      * Get a list of file roles that are valid for the particular release type.
                   20431:      *
                   20432:      * For instance, src files serve no purpose in regular php releases.
                   20433:      * @param string
                   20434:      * @param bool clear cache
                   20435:      * @return array
                   20436:      * @static
                   20437:      */
                   20438:     function getValidRoles($release, $clear = false)
                   20439:     {
                   20440:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
                   20441:             PEAR_Installer_Role::registerRoles();
                   20442:         }
                   20443: 
                   20444:         static $ret = array();
                   20445:         if ($clear) {
                   20446:             $ret = array();
                   20447:         }
                   20448: 
                   20449:         if (isset($ret[$release])) {
                   20450:             return $ret[$release];
                   20451:         }
                   20452: 
                   20453:         $ret[$release] = array();
                   20454:         foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
                   20455:             if (in_array($release, $okreleases['releasetypes'])) {
                   20456:                 $ret[$release][] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
                   20457:             }
                   20458:         }
                   20459: 
                   20460:         return $ret[$release];
                   20461:     }
                   20462: 
                   20463:     /**
                   20464:      * Get a list of roles that require their files to be installed
                   20465:      *
                   20466:      * Most roles must be installed, but src and package roles, for instance
                   20467:      * are pseudo-roles.  src files are compiled into a new extension.  Package
                   20468:      * roles are actually fully bundled releases of a package
                   20469:      * @param bool clear cache
                   20470:      * @return array
                   20471:      * @static
                   20472:      */
                   20473:     function getInstallableRoles($clear = false)
                   20474:     {
                   20475:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
                   20476:             PEAR_Installer_Role::registerRoles();
                   20477:         }
                   20478: 
                   20479:         static $ret;
                   20480:         if ($clear) {
                   20481:             unset($ret);
                   20482:         }
                   20483: 
                   20484:         if (isset($ret)) {
                   20485:             return $ret;
                   20486:         }
                   20487: 
                   20488:         $ret = array();
                   20489:         foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
                   20490:             if ($okreleases['installable']) {
                   20491:                 $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
                   20492:             }
                   20493:         }
                   20494: 
                   20495:         return $ret;
                   20496:     }
                   20497: 
                   20498:     /**
                   20499:      * Return an array of roles that are affected by the baseinstalldir attribute
                   20500:      *
                   20501:      * Most roles ignore this attribute, and instead install directly into:
                   20502:      * PackageName/filepath
                   20503:      * so a tests file tests/file.phpt is installed into PackageName/tests/filepath.php
                   20504:      * @param bool clear cache
                   20505:      * @return array
                   20506:      * @static
                   20507:      */
                   20508:     function getBaseinstallRoles($clear = false)
                   20509:     {
                   20510:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
                   20511:             PEAR_Installer_Role::registerRoles();
                   20512:         }
                   20513: 
                   20514:         static $ret;
                   20515:         if ($clear) {
                   20516:             unset($ret);
                   20517:         }
                   20518: 
                   20519:         if (isset($ret)) {
                   20520:             return $ret;
                   20521:         }
                   20522: 
                   20523:         $ret = array();
                   20524:         foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
                   20525:             if ($okreleases['honorsbaseinstall']) {
                   20526:                 $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
                   20527:             }
                   20528:         }
                   20529: 
                   20530:         return $ret;
                   20531:     }
                   20532: 
                   20533:     /**
                   20534:      * Return an array of file roles that should be analyzed for PHP content at package time,
                   20535:      * like the "php" role.
                   20536:      * @param bool clear cache
                   20537:      * @return array
                   20538:      * @static
                   20539:      */
                   20540:     function getPhpRoles($clear = false)
                   20541:     {
                   20542:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
                   20543:             PEAR_Installer_Role::registerRoles();
                   20544:         }
                   20545: 
                   20546:         static $ret;
                   20547:         if ($clear) {
                   20548:             unset($ret);
                   20549:         }
                   20550: 
                   20551:         if (isset($ret)) {
                   20552:             return $ret;
                   20553:         }
                   20554: 
                   20555:         $ret = array();
                   20556:         foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
                   20557:             if ($okreleases['phpfile']) {
                   20558:                 $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
                   20559:             }
                   20560:         }
                   20561: 
                   20562:         return $ret;
                   20563:     }
                   20564: 
                   20565:     /**
                   20566:      * Scan through the Command directory looking for classes
                   20567:      * and see what commands they implement.
                   20568:      * @param string which directory to look for classes, defaults to
                   20569:      *               the Installer/Roles subdirectory of
                   20570:      *               the directory from where this file (__FILE__) is
                   20571:      *               included.
                   20572:      *
                   20573:      * @return bool TRUE on success, a PEAR error on failure
                   20574:      * @access public
                   20575:      * @static
                   20576:      */
                   20577:     function registerRoles($dir = null)
                   20578:     {
                   20579:         $GLOBALS['_PEAR_INSTALLER_ROLES'] = array();
                   20580:         $parser = new PEAR_XMLParser;
                   20581:         if ($dir === null) {
                   20582:             $dir = dirname(__FILE__) . '/Role';
                   20583:         }
                   20584: 
                   20585:         if (!file_exists($dir) || !is_dir($dir)) {
                   20586:             return PEAR::raiseError("registerRoles: opendir($dir) failed: does not exist/is not directory");
                   20587:         }
                   20588: 
                   20589:         $dp = @opendir($dir);
                   20590:         if (empty($dp)) {
                   20591:             return PEAR::raiseError("registerRoles: opendir($dir) failed: $php_errmsg");
                   20592:         }
                   20593: 
                   20594:         while ($entry = readdir($dp)) {
                   20595:             if ($entry{0} == '.' || substr($entry, -4) != '.xml') {
                   20596:                 continue;
                   20597:             }
                   20598: 
                   20599:             $class = "PEAR_Installer_Role_".substr($entry, 0, -4);
                   20600:             // List of roles
                   20601:             if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'][$class])) {
                   20602:                 $file = "$dir/$entry";
                   20603:                 $parser->parse(file_get_contents($file));
                   20604:                 $data = $parser->getData();
                   20605:                 if (!is_array($data['releasetypes'])) {
                   20606:                     $data['releasetypes'] = array($data['releasetypes']);
                   20607:                 }
                   20608: 
                   20609:                 $GLOBALS['_PEAR_INSTALLER_ROLES'][$class] = $data;
                   20610:             }
                   20611:         }
                   20612: 
                   20613:         closedir($dp);
                   20614:         ksort($GLOBALS['_PEAR_INSTALLER_ROLES']);
                   20615:         PEAR_Installer_Role::getBaseinstallRoles(true);
                   20616:         PEAR_Installer_Role::getInstallableRoles(true);
                   20617:         PEAR_Installer_Role::getPhpRoles(true);
                   20618:         PEAR_Installer_Role::getValidRoles('****', true);
                   20619:         return true;
                   20620:     }
1.1.1.2 ! misho    20621: }PEAR-1.9.4/PEAR/PackageFile/Generator/v1.php0000644000076500000240000014234211605156614017111 0ustar  helgistaff<?php
1.1       misho    20622: /**
                   20623:  * package.xml generation class, package.xml version 1.0
                   20624:  *
                   20625:  * PHP versions 4 and 5
                   20626:  *
                   20627:  * @category   pear
                   20628:  * @package    PEAR
                   20629:  * @author     Greg Beaver <cellog@php.net>
                   20630:  * @copyright  1997-2009 The Authors
                   20631:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20632:  * @version    CVS: $Id: v1.php 313023 2011-07-06 19:17:11Z dufuz $
                   20633:  * @link       http://pear.php.net/package/PEAR
                   20634:  * @since      File available since Release 1.4.0a1
                   20635:  */
                   20636: /**
                   20637:  * needed for PEAR_VALIDATE_* constants
                   20638:  */
                   20639: require_once 'PEAR/Validate.php';
                   20640: require_once 'System.php';
                   20641: require_once 'PEAR/PackageFile/v2.php';
                   20642: /**
                   20643:  * This class converts a PEAR_PackageFile_v1 object into any output format.
                   20644:  *
                   20645:  * Supported output formats include array, XML string, and a PEAR_PackageFile_v2
                   20646:  * object, for converting package.xml 1.0 into package.xml 2.0 with no sweat.
                   20647:  * @category   pear
                   20648:  * @package    PEAR
                   20649:  * @author     Greg Beaver <cellog@php.net>
                   20650:  * @copyright  1997-2009 The Authors
                   20651:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   20652:  * @version    Release: 1.9.4
                   20653:  * @link       http://pear.php.net/package/PEAR
                   20654:  * @since      Class available since Release 1.4.0a1
                   20655:  */
                   20656: class PEAR_PackageFile_Generator_v1
                   20657: {
                   20658:     /**
                   20659:      * @var PEAR_PackageFile_v1
                   20660:      */
                   20661:     var $_packagefile;
                   20662:     function PEAR_PackageFile_Generator_v1(&$packagefile)
                   20663:     {
                   20664:         $this->_packagefile = &$packagefile;
                   20665:     }
                   20666: 
                   20667:     function getPackagerVersion()
                   20668:     {
                   20669:         return '1.9.4';
                   20670:     }
                   20671: 
                   20672:     /**
                   20673:      * @param PEAR_Packager
                   20674:      * @param bool if true, a .tgz is written, otherwise a .tar is written
                   20675:      * @param string|null directory in which to save the .tgz
                   20676:      * @return string|PEAR_Error location of package or error object
                   20677:      */
                   20678:     function toTgz(&$packager, $compress = true, $where = null)
                   20679:     {
                   20680:         require_once 'Archive/Tar.php';
                   20681:         if ($where === null) {
                   20682:             if (!($where = System::mktemp(array('-d')))) {
                   20683:                 return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: mktemp failed');
                   20684:             }
                   20685:         } elseif (!@System::mkDir(array('-p', $where))) {
                   20686:             return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: "' . $where . '" could' .
                   20687:                 ' not be created');
                   20688:         }
                   20689:         if (file_exists($where . DIRECTORY_SEPARATOR . 'package.xml') &&
                   20690:               !is_file($where . DIRECTORY_SEPARATOR . 'package.xml')) {
                   20691:             return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: unable to save package.xml as' .
                   20692:                 ' "' . $where . DIRECTORY_SEPARATOR . 'package.xml"');
                   20693:         }
                   20694:         if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) {
                   20695:             return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: invalid package file');
                   20696:         }
                   20697:         $pkginfo = $this->_packagefile->getArray();
                   20698:         $ext = $compress ? '.tgz' : '.tar';
                   20699:         $pkgver = $pkginfo['package'] . '-' . $pkginfo['version'];
                   20700:         $dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext;
                   20701:         if (file_exists(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext) &&
                   20702:               !is_file(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext)) {
                   20703:             return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: cannot create tgz file "' .
                   20704:                 getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext . '"');
                   20705:         }
                   20706:         if ($pkgfile = $this->_packagefile->getPackageFile()) {
                   20707:             $pkgdir = dirname(realpath($pkgfile));
                   20708:             $pkgfile = basename($pkgfile);
                   20709:         } else {
                   20710:             return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: package file object must ' .
                   20711:                 'be created from a real file');
                   20712:         }
                   20713:         // {{{ Create the package file list
                   20714:         $filelist = array();
                   20715:         $i = 0;
                   20716: 
                   20717:         foreach ($this->_packagefile->getFilelist() as $fname => $atts) {
                   20718:             $file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
                   20719:             if (!file_exists($file)) {
                   20720:                 return PEAR::raiseError("File does not exist: $fname");
                   20721:             } else {
                   20722:                 $filelist[$i++] = $file;
                   20723:                 if (!isset($atts['md5sum'])) {
                   20724:                     $this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($file));
                   20725:                 }
                   20726:                 $packager->log(2, "Adding file $fname");
                   20727:             }
                   20728:         }
                   20729:         // }}}
                   20730:         $packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, 'package.xml', true);
                   20731:         if ($packagexml) {
                   20732:             $tar =& new Archive_Tar($dest_package, $compress);
                   20733:             $tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors
                   20734:             // ----- Creates with the package.xml file
                   20735:             $ok = $tar->createModify(array($packagexml), '', $where);
                   20736:             if (PEAR::isError($ok)) {
                   20737:                 return $ok;
                   20738:             } elseif (!$ok) {
                   20739:                 return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed');
                   20740:             }
                   20741:             // ----- Add the content of the package
                   20742:             if (!$tar->addModify($filelist, $pkgver, $pkgdir)) {
                   20743:                 return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed');
                   20744:             }
                   20745:             return $dest_package;
                   20746:         }
                   20747:     }
                   20748: 
                   20749:     /**
                   20750:      * @param string|null directory to place the package.xml in, or null for a temporary dir
                   20751:      * @param int one of the PEAR_VALIDATE_* constants
                   20752:      * @param string name of the generated file
                   20753:      * @param bool if true, then no analysis will be performed on role="php" files
                   20754:      * @return string|PEAR_Error path to the created file on success
                   20755:      */
                   20756:     function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml',
                   20757:                            $nofilechecking = false)
                   20758:     {
                   20759:         if (!$this->_packagefile->validate($state, $nofilechecking)) {
                   20760:             return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: invalid package.xml',
                   20761:                 null, null, null, $this->_packagefile->getValidationWarnings());
                   20762:         }
                   20763:         if ($where === null) {
                   20764:             if (!($where = System::mktemp(array('-d')))) {
                   20765:                 return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: mktemp failed');
                   20766:             }
                   20767:         } elseif (!@System::mkDir(array('-p', $where))) {
                   20768:             return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: "' . $where . '" could' .
                   20769:                 ' not be created');
                   20770:         }
                   20771:         $newpkgfile = $where . DIRECTORY_SEPARATOR . $name;
                   20772:         $np = @fopen($newpkgfile, 'wb');
                   20773:         if (!$np) {
                   20774:             return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: unable to save ' .
                   20775:                "$name as $newpkgfile");
                   20776:         }
                   20777:         fwrite($np, $this->toXml($state, true));
                   20778:         fclose($np);
                   20779:         return $newpkgfile;
                   20780:     }
                   20781: 
                   20782:     /**
                   20783:      * fix both XML encoding to be UTF8, and replace standard XML entities < > " & '
                   20784:      *
                   20785:      * @param string $string
                   20786:      * @return string
                   20787:      * @access private
                   20788:      */
                   20789:     function _fixXmlEncoding($string)
                   20790:     {
                   20791:         if (version_compare(phpversion(), '5.0.0', 'lt')) {
                   20792:             $string = utf8_encode($string);
                   20793:         }
                   20794:         return strtr($string, array(
                   20795:                                           '&'  => '&amp;',
                   20796:                                           '>'  => '&gt;',
                   20797:                                           '<'  => '&lt;',
                   20798:                                           '"'  => '&quot;',
                   20799:                                           '\'' => '&apos;' ));
                   20800:     }
                   20801: 
                   20802:     /**
                   20803:      * Return an XML document based on the package info (as returned
                   20804:      * by the PEAR_Common::infoFrom* methods).
                   20805:      *
                   20806:      * @return string XML data
                   20807:      */
                   20808:     function toXml($state = PEAR_VALIDATE_NORMAL, $nofilevalidation = false)
                   20809:     {
                   20810:         $this->_packagefile->setDate(date('Y-m-d'));
                   20811:         if (!$this->_packagefile->validate($state, $nofilevalidation)) {
                   20812:             return false;
                   20813:         }
                   20814:         $pkginfo = $this->_packagefile->getArray();
                   20815:         static $maint_map = array(
                   20816:             "handle" => "user",
                   20817:             "name" => "name",
                   20818:             "email" => "email",
                   20819:             "role" => "role",
                   20820:             );
                   20821:         $ret = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
                   20822:         $ret .= "<!DOCTYPE package SYSTEM \"http://pear.php.net/dtd/package-1.0\">\n";
                   20823:         $ret .= "<package version=\"1.0\" packagerversion=\"1.9.4\">\n" .
                   20824: " <name>$pkginfo[package]</name>";
                   20825:         if (isset($pkginfo['extends'])) {
                   20826:             $ret .= "\n<extends>$pkginfo[extends]</extends>";
                   20827:         }
                   20828:         $ret .=
                   20829:  "\n <summary>".$this->_fixXmlEncoding($pkginfo['summary'])."</summary>\n" .
                   20830: " <description>".trim($this->_fixXmlEncoding($pkginfo['description']))."\n </description>\n" .
                   20831: " <maintainers>\n";
                   20832:         foreach ($pkginfo['maintainers'] as $maint) {
                   20833:             $ret .= "  <maintainer>\n";
                   20834:             foreach ($maint_map as $idx => $elm) {
                   20835:                 $ret .= "   <$elm>";
                   20836:                 $ret .= $this->_fixXmlEncoding($maint[$idx]);
                   20837:                 $ret .= "</$elm>\n";
                   20838:             }
                   20839:             $ret .= "  </maintainer>\n";
                   20840:         }
                   20841:         $ret .= "  </maintainers>\n";
                   20842:         $ret .= $this->_makeReleaseXml($pkginfo, false, $state);
                   20843:         if (isset($pkginfo['changelog']) && count($pkginfo['changelog']) > 0) {
                   20844:             $ret .= " <changelog>\n";
                   20845:             foreach ($pkginfo['changelog'] as $oldrelease) {
                   20846:                 $ret .= $this->_makeReleaseXml($oldrelease, true);
                   20847:             }
                   20848:             $ret .= " </changelog>\n";
                   20849:         }
                   20850:         $ret .= "</package>\n";
                   20851:         return $ret;
                   20852:     }
                   20853: 
                   20854:     // }}}
                   20855:     // {{{ _makeReleaseXml()
                   20856: 
                   20857:     /**
                   20858:      * Generate part of an XML description with release information.
                   20859:      *
                   20860:      * @param array  $pkginfo    array with release information
                   20861:      * @param bool   $changelog  whether the result will be in a changelog element
                   20862:      *
                   20863:      * @return string XML data
                   20864:      *
                   20865:      * @access private
                   20866:      */
                   20867:     function _makeReleaseXml($pkginfo, $changelog = false, $state = PEAR_VALIDATE_NORMAL)
                   20868:     {
                   20869:         // XXX QUOTE ENTITIES IN PCDATA, OR EMBED IN CDATA BLOCKS!!
                   20870:         $indent = $changelog ? "  " : "";
                   20871:         $ret = "$indent <release>\n";
                   20872:         if (!empty($pkginfo['version'])) {
                   20873:             $ret .= "$indent  <version>$pkginfo[version]</version>\n";
                   20874:         }
                   20875:         if (!empty($pkginfo['release_date'])) {
                   20876:             $ret .= "$indent  <date>$pkginfo[release_date]</date>\n";
                   20877:         }
                   20878:         if (!empty($pkginfo['release_license'])) {
                   20879:             $ret .= "$indent  <license>$pkginfo[release_license]</license>\n";
                   20880:         }
                   20881:         if (!empty($pkginfo['release_state'])) {
                   20882:             $ret .= "$indent  <state>$pkginfo[release_state]</state>\n";
                   20883:         }
                   20884:         if (!empty($pkginfo['release_notes'])) {
                   20885:             $ret .= "$indent  <notes>".trim($this->_fixXmlEncoding($pkginfo['release_notes']))
                   20886:             ."\n$indent  </notes>\n";
                   20887:         }
                   20888:         if (!empty($pkginfo['release_warnings'])) {
                   20889:             $ret .= "$indent  <warnings>".$this->_fixXmlEncoding($pkginfo['release_warnings'])."</warnings>\n";
                   20890:         }
                   20891:         if (isset($pkginfo['release_deps']) && sizeof($pkginfo['release_deps']) > 0) {
                   20892:             $ret .= "$indent  <deps>\n";
                   20893:             foreach ($pkginfo['release_deps'] as $dep) {
                   20894:                 $ret .= "$indent   <dep type=\"$dep[type]\" rel=\"$dep[rel]\"";
                   20895:                 if (isset($dep['version'])) {
                   20896:                     $ret .= " version=\"$dep[version]\"";
                   20897:                 }
                   20898:                 if (isset($dep['optional'])) {
                   20899:                     $ret .= " optional=\"$dep[optional]\"";
                   20900:                 }
                   20901:                 if (isset($dep['name'])) {
                   20902:                     $ret .= ">$dep[name]</dep>\n";
                   20903:                 } else {
                   20904:                     $ret .= "/>\n";
                   20905:                 }
                   20906:             }
                   20907:             $ret .= "$indent  </deps>\n";
                   20908:         }
                   20909:         if (isset($pkginfo['configure_options'])) {
                   20910:             $ret .= "$indent  <configureoptions>\n";
                   20911:             foreach ($pkginfo['configure_options'] as $c) {
                   20912:                 $ret .= "$indent   <configureoption name=\"".
                   20913:                     $this->_fixXmlEncoding($c['name']) . "\"";
                   20914:                 if (isset($c['default'])) {
                   20915:                     $ret .= " default=\"" . $this->_fixXmlEncoding($c['default']) . "\"";
                   20916:                 }
                   20917:                 $ret .= " prompt=\"" . $this->_fixXmlEncoding($c['prompt']) . "\"";
                   20918:                 $ret .= "/>\n";
                   20919:             }
                   20920:             $ret .= "$indent  </configureoptions>\n";
                   20921:         }
                   20922:         if (isset($pkginfo['provides'])) {
                   20923:             foreach ($pkginfo['provides'] as $key => $what) {
                   20924:                 $ret .= "$indent  <provides type=\"$what[type]\" ";
                   20925:                 $ret .= "name=\"$what[name]\" ";
                   20926:                 if (isset($what['extends'])) {
                   20927:                     $ret .= "extends=\"$what[extends]\" ";
                   20928:                 }
                   20929:                 $ret .= "/>\n";
                   20930:             }
                   20931:         }
                   20932:         if (isset($pkginfo['filelist'])) {
                   20933:             $ret .= "$indent  <filelist>\n";
                   20934:             if ($state ^ PEAR_VALIDATE_PACKAGING) {
                   20935:                 $ret .= $this->recursiveXmlFilelist($pkginfo['filelist']);
                   20936:             } else {
                   20937:                 foreach ($pkginfo['filelist'] as $file => $fa) {
                   20938:                     if (!isset($fa['role'])) {
                   20939:                         $fa['role'] = '';
                   20940:                     }
                   20941:                     $ret .= "$indent   <file role=\"$fa[role]\"";
                   20942:                     if (isset($fa['baseinstalldir'])) {
                   20943:                         $ret .= ' baseinstalldir="' .
                   20944:                             $this->_fixXmlEncoding($fa['baseinstalldir']) . '"';
                   20945:                     }
                   20946:                     if (isset($fa['md5sum'])) {
                   20947:                         $ret .= " md5sum=\"$fa[md5sum]\"";
                   20948:                     }
                   20949:                     if (isset($fa['platform'])) {
                   20950:                         $ret .= " platform=\"$fa[platform]\"";
                   20951:                     }
                   20952:                     if (!empty($fa['install-as'])) {
                   20953:                         $ret .= ' install-as="' .
                   20954:                             $this->_fixXmlEncoding($fa['install-as']) . '"';
                   20955:                     }
                   20956:                     $ret .= ' name="' . $this->_fixXmlEncoding($file) . '"';
                   20957:                     if (empty($fa['replacements'])) {
                   20958:                         $ret .= "/>\n";
                   20959:                     } else {
                   20960:                         $ret .= ">\n";
                   20961:                         foreach ($fa['replacements'] as $r) {
                   20962:                             $ret .= "$indent    <replace";
                   20963:                             foreach ($r as $k => $v) {
                   20964:                                 $ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"';
                   20965:                             }
                   20966:                             $ret .= "/>\n";
                   20967:                         }
                   20968:                         $ret .= "$indent   </file>\n";
                   20969:                     }
                   20970:                 }
                   20971:             }
                   20972:             $ret .= "$indent  </filelist>\n";
                   20973:         }
                   20974:         $ret .= "$indent </release>\n";
                   20975:         return $ret;
                   20976:     }
                   20977: 
                   20978:     /**
                   20979:      * @param array
                   20980:      * @access protected
                   20981:      */
                   20982:     function recursiveXmlFilelist($list)
                   20983:     {
                   20984:         $this->_dirs = array();
                   20985:         foreach ($list as $file => $attributes) {
                   20986:             $this->_addDir($this->_dirs, explode('/', dirname($file)), $file, $attributes);
                   20987:         }
                   20988:         return $this->_formatDir($this->_dirs);
                   20989:     }
                   20990: 
                   20991:     /**
                   20992:      * @param array
                   20993:      * @param array
                   20994:      * @param string|null
                   20995:      * @param array|null
                   20996:      * @access private
                   20997:      */
                   20998:     function _addDir(&$dirs, $dir, $file = null, $attributes = null)
                   20999:     {
                   21000:         if ($dir == array() || $dir == array('.')) {
                   21001:             $dirs['files'][basename($file)] = $attributes;
                   21002:             return;
                   21003:         }
                   21004:         $curdir = array_shift($dir);
                   21005:         if (!isset($dirs['dirs'][$curdir])) {
                   21006:             $dirs['dirs'][$curdir] = array();
                   21007:         }
                   21008:         $this->_addDir($dirs['dirs'][$curdir], $dir, $file, $attributes);
                   21009:     }
                   21010: 
                   21011:     /**
                   21012:      * @param array
                   21013:      * @param string
                   21014:      * @param string
                   21015:      * @access private
                   21016:      */
                   21017:     function _formatDir($dirs, $indent = '', $curdir = '')
                   21018:     {
                   21019:         $ret = '';
                   21020:         if (!count($dirs)) {
                   21021:             return '';
                   21022:         }
                   21023:         if (isset($dirs['dirs'])) {
                   21024:             uksort($dirs['dirs'], 'strnatcasecmp');
                   21025:             foreach ($dirs['dirs'] as $dir => $contents) {
                   21026:                 $usedir = "$curdir/$dir";
                   21027:                 $ret .= "$indent   <dir name=\"$dir\">\n";
                   21028:                 $ret .= $this->_formatDir($contents, "$indent ", $usedir);
                   21029:                 $ret .= "$indent   </dir> <!-- $usedir -->\n";
                   21030:             }
                   21031:         }
                   21032:         if (isset($dirs['files'])) {
                   21033:             uksort($dirs['files'], 'strnatcasecmp');
                   21034:             foreach ($dirs['files'] as $file => $attribs) {
                   21035:                 $ret .= $this->_formatFile($file, $attribs, $indent);
                   21036:             }
                   21037:         }
                   21038:         return $ret;
                   21039:     }
                   21040: 
                   21041:     /**
                   21042:      * @param string
                   21043:      * @param array
                   21044:      * @param string
                   21045:      * @access private
                   21046:      */
                   21047:     function _formatFile($file, $attributes, $indent)
                   21048:     {
                   21049:         $ret = "$indent   <file role=\"$attributes[role]\"";
                   21050:         if (isset($attributes['baseinstalldir'])) {
                   21051:             $ret .= ' baseinstalldir="' .
                   21052:                 $this->_fixXmlEncoding($attributes['baseinstalldir']) . '"';
                   21053:         }
                   21054:         if (isset($attributes['md5sum'])) {
                   21055:             $ret .= " md5sum=\"$attributes[md5sum]\"";
                   21056:         }
                   21057:         if (isset($attributes['platform'])) {
                   21058:             $ret .= " platform=\"$attributes[platform]\"";
                   21059:         }
                   21060:         if (!empty($attributes['install-as'])) {
                   21061:             $ret .= ' install-as="' .
                   21062:                 $this->_fixXmlEncoding($attributes['install-as']) . '"';
                   21063:         }
                   21064:         $ret .= ' name="' . $this->_fixXmlEncoding($file) . '"';
                   21065:         if (empty($attributes['replacements'])) {
                   21066:             $ret .= "/>\n";
                   21067:         } else {
                   21068:             $ret .= ">\n";
                   21069:             foreach ($attributes['replacements'] as $r) {
                   21070:                 $ret .= "$indent    <replace";
                   21071:                 foreach ($r as $k => $v) {
                   21072:                     $ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"';
                   21073:                 }
                   21074:                 $ret .= "/>\n";
                   21075:             }
                   21076:             $ret .= "$indent   </file>\n";
                   21077:         }
                   21078:         return $ret;
                   21079:     }
                   21080: 
                   21081:     // {{{ _unIndent()
                   21082: 
                   21083:     /**
                   21084:      * Unindent given string (?)
                   21085:      *
                   21086:      * @param string $str The string that has to be unindented.
                   21087:      * @return string
                   21088:      * @access private
                   21089:      */
                   21090:     function _unIndent($str)
                   21091:     {
                   21092:         // remove leading newlines
                   21093:         $str = preg_replace('/^[\r\n]+/', '', $str);
                   21094:         // find whitespace at the beginning of the first line
                   21095:         $indent_len = strspn($str, " \t");
                   21096:         $indent = substr($str, 0, $indent_len);
                   21097:         $data = '';
                   21098:         // remove the same amount of whitespace from following lines
                   21099:         foreach (explode("\n", $str) as $line) {
                   21100:             if (substr($line, 0, $indent_len) == $indent) {
                   21101:                 $data .= substr($line, $indent_len) . "\n";
                   21102:             }
                   21103:         }
                   21104:         return $data;
                   21105:     }
                   21106: 
                   21107:     /**
                   21108:      * @return array
                   21109:      */
                   21110:     function dependenciesToV2()
                   21111:     {
                   21112:         $arr = array();
                   21113:         $this->_convertDependencies2_0($arr);
                   21114:         return $arr['dependencies'];
                   21115:     }
                   21116: 
                   21117:     /**
                   21118:      * Convert a package.xml version 1.0 into version 2.0
                   21119:      *
                   21120:      * Note that this does a basic conversion, to allow more advanced
                   21121:      * features like bundles and multiple releases
                   21122:      * @param string the classname to instantiate and return.  This must be
                   21123:      *               PEAR_PackageFile_v2 or a descendant
                   21124:      * @param boolean if true, only valid, deterministic package.xml 1.0 as defined by the
                   21125:      *                strictest parameters will be converted
                   21126:      * @return PEAR_PackageFile_v2|PEAR_Error
                   21127:      */
                   21128:     function &toV2($class = 'PEAR_PackageFile_v2', $strict = false)
                   21129:     {
                   21130:         if ($strict) {
                   21131:             if (!$this->_packagefile->validate()) {
                   21132:                 $a = PEAR::raiseError('invalid package.xml version 1.0 cannot be converted' .
                   21133:                     ' to version 2.0', null, null, null,
                   21134:                     $this->_packagefile->getValidationWarnings(true));
                   21135:                 return $a;
                   21136:             }
                   21137:         }
                   21138: 
                   21139:         $arr = array(
                   21140:             'attribs' => array(
                   21141:                              'version' => '2.0',
                   21142:                              'xmlns' => 'http://pear.php.net/dtd/package-2.0',
                   21143:                              'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
                   21144:                              'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
                   21145:                              'xsi:schemaLocation' => "http://pear.php.net/dtd/tasks-1.0\n" .
                   21146: "http://pear.php.net/dtd/tasks-1.0.xsd\n" .
                   21147: "http://pear.php.net/dtd/package-2.0\n" .
                   21148: 'http://pear.php.net/dtd/package-2.0.xsd',
                   21149:                          ),
                   21150:             'name' => $this->_packagefile->getPackage(),
                   21151:             'channel' => 'pear.php.net',
                   21152:         );
                   21153:         $arr['summary'] = $this->_packagefile->getSummary();
                   21154:         $arr['description'] = $this->_packagefile->getDescription();
                   21155:         $maintainers = $this->_packagefile->getMaintainers();
                   21156:         foreach ($maintainers as $maintainer) {
                   21157:             if ($maintainer['role'] != 'lead') {
                   21158:                 continue;
                   21159:             }
                   21160:             $new = array(
                   21161:                 'name' => $maintainer['name'],
                   21162:                 'user' => $maintainer['handle'],
                   21163:                 'email' => $maintainer['email'],
                   21164:                 'active' => 'yes',
                   21165:             );
                   21166:             $arr['lead'][] = $new;
                   21167:         }
                   21168: 
                   21169:         if (!isset($arr['lead'])) { // some people... you know?
                   21170:             $arr['lead'] = array(
                   21171:                 'name' => 'unknown',
                   21172:                 'user' => 'unknown',
                   21173:                 'email' => 'noleadmaintainer@example.com',
                   21174:                 'active' => 'no',
                   21175:             );
                   21176:         }
                   21177: 
                   21178:         if (count($arr['lead']) == 1) {
                   21179:             $arr['lead'] = $arr['lead'][0];
                   21180:         }
                   21181: 
                   21182:         foreach ($maintainers as $maintainer) {
                   21183:             if ($maintainer['role'] == 'lead') {
                   21184:                 continue;
                   21185:             }
                   21186:             $new = array(
                   21187:                 'name' => $maintainer['name'],
                   21188:                 'user' => $maintainer['handle'],
                   21189:                 'email' => $maintainer['email'],
                   21190:                 'active' => 'yes',
                   21191:             );
                   21192:             $arr[$maintainer['role']][] = $new;
                   21193:         }
                   21194: 
                   21195:         if (isset($arr['developer']) && count($arr['developer']) == 1) {
                   21196:             $arr['developer'] = $arr['developer'][0];
                   21197:         }
                   21198: 
                   21199:         if (isset($arr['contributor']) && count($arr['contributor']) == 1) {
                   21200:             $arr['contributor'] = $arr['contributor'][0];
                   21201:         }
                   21202: 
                   21203:         if (isset($arr['helper']) && count($arr['helper']) == 1) {
                   21204:             $arr['helper'] = $arr['helper'][0];
                   21205:         }
                   21206: 
                   21207:         $arr['date'] = $this->_packagefile->getDate();
                   21208:         $arr['version'] =
                   21209:             array(
                   21210:                 'release' => $this->_packagefile->getVersion(),
                   21211:                 'api' => $this->_packagefile->getVersion(),
                   21212:             );
                   21213:         $arr['stability'] =
                   21214:             array(
                   21215:                 'release' => $this->_packagefile->getState(),
                   21216:                 'api' => $this->_packagefile->getState(),
                   21217:             );
                   21218:         $licensemap =
                   21219:             array(
                   21220:                 'php' => 'http://www.php.net/license',
                   21221:                 'php license' => 'http://www.php.net/license',
                   21222:                 'lgpl' => 'http://www.gnu.org/copyleft/lesser.html',
                   21223:                 'bsd' => 'http://www.opensource.org/licenses/bsd-license.php',
                   21224:                 'bsd style' => 'http://www.opensource.org/licenses/bsd-license.php',
                   21225:                 'bsd-style' => 'http://www.opensource.org/licenses/bsd-license.php',
                   21226:                 'mit' => 'http://www.opensource.org/licenses/mit-license.php',
                   21227:                 'gpl' => 'http://www.gnu.org/copyleft/gpl.html',
                   21228:                 'apache' => 'http://www.opensource.org/licenses/apache2.0.php'
                   21229:             );
                   21230: 
                   21231:         if (isset($licensemap[strtolower($this->_packagefile->getLicense())])) {
                   21232:             $arr['license'] = array(
                   21233:                 'attribs' => array('uri' =>
                   21234:                     $licensemap[strtolower($this->_packagefile->getLicense())]),
                   21235:                 '_content' => $this->_packagefile->getLicense()
                   21236:                 );
                   21237:         } else {
                   21238:             // don't use bogus uri
                   21239:             $arr['license'] = $this->_packagefile->getLicense();
                   21240:         }
                   21241: 
                   21242:         $arr['notes'] = $this->_packagefile->getNotes();
                   21243:         $temp = array();
                   21244:         $arr['contents'] = $this->_convertFilelist2_0($temp);
                   21245:         $this->_convertDependencies2_0($arr);
                   21246:         $release = ($this->_packagefile->getConfigureOptions() || $this->_isExtension) ?
                   21247:             'extsrcrelease' : 'phprelease';
                   21248:         if ($release == 'extsrcrelease') {
                   21249:             $arr['channel'] = 'pecl.php.net';
                   21250:             $arr['providesextension'] = $arr['name']; // assumption
                   21251:         }
                   21252: 
                   21253:         $arr[$release] = array();
                   21254:         if ($this->_packagefile->getConfigureOptions()) {
                   21255:             $arr[$release]['configureoption'] = $this->_packagefile->getConfigureOptions();
                   21256:             foreach ($arr[$release]['configureoption'] as $i => $opt) {
                   21257:                 $arr[$release]['configureoption'][$i] = array('attribs' => $opt);
                   21258:             }
                   21259:             if (count($arr[$release]['configureoption']) == 1) {
                   21260:                 $arr[$release]['configureoption'] = $arr[$release]['configureoption'][0];
                   21261:             }
                   21262:         }
                   21263: 
                   21264:         $this->_convertRelease2_0($arr[$release], $temp);
                   21265:         if ($release == 'extsrcrelease' && count($arr[$release]) > 1) {
                   21266:             // multiple extsrcrelease tags added in PEAR 1.4.1
                   21267:             $arr['dependencies']['required']['pearinstaller']['min'] = '1.4.1';
                   21268:         }
                   21269: 
                   21270:         if ($cl = $this->_packagefile->getChangelog()) {
                   21271:             foreach ($cl as $release) {
                   21272:                 $rel = array();
                   21273:                 $rel['version'] =
                   21274:                     array(
                   21275:                         'release' => $release['version'],
                   21276:                         'api' => $release['version'],
                   21277:                     );
                   21278:                 if (!isset($release['release_state'])) {
                   21279:                     $release['release_state'] = 'stable';
                   21280:                 }
                   21281: 
                   21282:                 $rel['stability'] =
                   21283:                     array(
                   21284:                         'release' => $release['release_state'],
                   21285:                         'api' => $release['release_state'],
                   21286:                     );
                   21287:                 if (isset($release['release_date'])) {
                   21288:                     $rel['date'] = $release['release_date'];
                   21289:                 } else {
                   21290:                     $rel['date'] = date('Y-m-d');
                   21291:                 }
                   21292: 
                   21293:                 if (isset($release['release_license'])) {
                   21294:                     if (isset($licensemap[strtolower($release['release_license'])])) {
                   21295:                         $uri = $licensemap[strtolower($release['release_license'])];
                   21296:                     } else {
                   21297:                         $uri = 'http://www.example.com';
                   21298:                     }
                   21299:                     $rel['license'] = array(
                   21300:                             'attribs' => array('uri' => $uri),
                   21301:                             '_content' => $release['release_license']
                   21302:                         );
                   21303:                 } else {
                   21304:                     $rel['license'] = $arr['license'];
                   21305:                 }
                   21306: 
                   21307:                 if (!isset($release['release_notes'])) {
                   21308:                     $release['release_notes'] = 'no release notes';
                   21309:                 }
                   21310: 
                   21311:                 $rel['notes'] = $release['release_notes'];
                   21312:                 $arr['changelog']['release'][] = $rel;
                   21313:             }
                   21314:         }
                   21315: 
                   21316:         $ret = new $class;
                   21317:         $ret->setConfig($this->_packagefile->_config);
                   21318:         if (isset($this->_packagefile->_logger) && is_object($this->_packagefile->_logger)) {
                   21319:             $ret->setLogger($this->_packagefile->_logger);
                   21320:         }
                   21321: 
                   21322:         $ret->fromArray($arr);
                   21323:         return $ret;
                   21324:     }
                   21325: 
                   21326:     /**
                   21327:      * @param array
                   21328:      * @param bool
                   21329:      * @access private
                   21330:      */
                   21331:     function _convertDependencies2_0(&$release, $internal = false)
                   21332:     {
                   21333:         $peardep = array('pearinstaller' =>
                   21334:             array('min' => '1.4.0b1')); // this is a lot safer
                   21335:         $required = $optional = array();
                   21336:         $release['dependencies'] = array('required' => array());
                   21337:         if ($this->_packagefile->hasDeps()) {
                   21338:             foreach ($this->_packagefile->getDeps() as $dep) {
                   21339:                 if (!isset($dep['optional']) || $dep['optional'] == 'no') {
                   21340:                     $required[] = $dep;
                   21341:                 } else {
                   21342:                     $optional[] = $dep;
                   21343:                 }
                   21344:             }
                   21345:             foreach (array('required', 'optional') as $arr) {
                   21346:                 $deps = array();
                   21347:                 foreach ($$arr as $dep) {
                   21348:                     // organize deps by dependency type and name
                   21349:                     if (!isset($deps[$dep['type']])) {
                   21350:                         $deps[$dep['type']] = array();
                   21351:                     }
                   21352:                     if (isset($dep['name'])) {
                   21353:                         $deps[$dep['type']][$dep['name']][] = $dep;
                   21354:                     } else {
                   21355:                         $deps[$dep['type']][] = $dep;
                   21356:                     }
                   21357:                 }
                   21358:                 do {
                   21359:                     if (isset($deps['php'])) {
                   21360:                         $php = array();
                   21361:                         if (count($deps['php']) > 1) {
                   21362:                             $php = $this->_processPhpDeps($deps['php']);
                   21363:                         } else {
                   21364:                             if (!isset($deps['php'][0])) {
                   21365:                                 list($key, $blah) = each ($deps['php']); // stupid buggy versions
                   21366:                                 $deps['php'] = array($blah[0]);
                   21367:                             }
                   21368:                             $php = $this->_processDep($deps['php'][0]);
                   21369:                             if (!$php) {
                   21370:                                 break; // poor mans throw
                   21371:                             }
                   21372:                         }
                   21373:                         $release['dependencies'][$arr]['php'] = $php;
                   21374:                     }
                   21375:                 } while (false);
                   21376:                 do {
                   21377:                     if (isset($deps['pkg'])) {
                   21378:                         $pkg = array();
                   21379:                         $pkg = $this->_processMultipleDepsName($deps['pkg']);
                   21380:                         if (!$pkg) {
                   21381:                             break; // poor mans throw
                   21382:                         }
                   21383:                         $release['dependencies'][$arr]['package'] = $pkg;
                   21384:                     }
                   21385:                 } while (false);
                   21386:                 do {
                   21387:                     if (isset($deps['ext'])) {
                   21388:                         $pkg = array();
                   21389:                         $pkg = $this->_processMultipleDepsName($deps['ext']);
                   21390:                         $release['dependencies'][$arr]['extension'] = $pkg;
                   21391:                     }
                   21392:                 } while (false);
                   21393:                 // skip sapi - it's not supported so nobody will have used it
                   21394:                 // skip os - it's not supported in 1.0
                   21395:             }
                   21396:         }
                   21397:         if (isset($release['dependencies']['required'])) {
                   21398:             $release['dependencies']['required'] =
                   21399:                 array_merge($peardep, $release['dependencies']['required']);
                   21400:         } else {
                   21401:             $release['dependencies']['required'] = $peardep;
                   21402:         }
                   21403:         if (!isset($release['dependencies']['required']['php'])) {
                   21404:             $release['dependencies']['required']['php'] =
                   21405:                 array('min' => '4.0.0');
                   21406:         }
                   21407:         $order = array();
                   21408:         $bewm = $release['dependencies']['required'];
                   21409:         $order['php'] = $bewm['php'];
                   21410:         $order['pearinstaller'] = $bewm['pearinstaller'];
                   21411:         isset($bewm['package']) ? $order['package'] = $bewm['package'] :0;
                   21412:         isset($bewm['extension']) ? $order['extension'] = $bewm['extension'] :0;
                   21413:         $release['dependencies']['required'] = $order;
                   21414:     }
                   21415: 
                   21416:     /**
                   21417:      * @param array
                   21418:      * @access private
                   21419:      */
                   21420:     function _convertFilelist2_0(&$package)
                   21421:     {
                   21422:         $ret = array('dir' =>
                   21423:                     array(
                   21424:                         'attribs' => array('name' => '/'),
                   21425:                         'file' => array()
                   21426:                         )
                   21427:                     );
                   21428:         $package['platform'] =
                   21429:         $package['install-as'] = array();
                   21430:         $this->_isExtension = false;
                   21431:         foreach ($this->_packagefile->getFilelist() as $name => $file) {
                   21432:             $file['name'] = $name;
                   21433:             if (isset($file['role']) && $file['role'] == 'src') {
                   21434:                 $this->_isExtension = true;
                   21435:             }
                   21436:             if (isset($file['replacements'])) {
                   21437:                 $repl = $file['replacements'];
                   21438:                 unset($file['replacements']);
                   21439:             } else {
                   21440:                 unset($repl);
                   21441:             }
                   21442:             if (isset($file['install-as'])) {
                   21443:                 $package['install-as'][$name] = $file['install-as'];
                   21444:                 unset($file['install-as']);
                   21445:             }
                   21446:             if (isset($file['platform'])) {
                   21447:                 $package['platform'][$name] = $file['platform'];
                   21448:                 unset($file['platform']);
                   21449:             }
                   21450:             $file = array('attribs' => $file);
                   21451:             if (isset($repl)) {
                   21452:                 foreach ($repl as $replace ) {
                   21453:                     $file['tasks:replace'][] = array('attribs' => $replace);
                   21454:                 }
                   21455:                 if (count($repl) == 1) {
                   21456:                     $file['tasks:replace'] = $file['tasks:replace'][0];
                   21457:                 }
                   21458:             }
                   21459:             $ret['dir']['file'][] = $file;
                   21460:         }
                   21461:         return $ret;
                   21462:     }
                   21463: 
                   21464:     /**
                   21465:      * Post-process special files with install-as/platform attributes and
                   21466:      * make the release tag.
                   21467:      *
                   21468:      * This complex method follows this work-flow to create the release tags:
                   21469:      *
                   21470:      * <pre>
                   21471:      * - if any install-as/platform exist, create a generic release and fill it with
                   21472:      *   o <install as=..> tags for <file name=... install-as=...>
                   21473:      *   o <install as=..> tags for <file name=... platform=!... install-as=..>
                   21474:      *   o <ignore> tags for <file name=... platform=...>
                   21475:      *   o <ignore> tags for <file name=... platform=... install-as=..>
                   21476:      * - create a release for each platform encountered and fill with
                   21477:      *   o <install as..> tags for <file name=... install-as=...>
                   21478:      *   o <install as..> tags for <file name=... platform=this platform install-as=..>
                   21479:      *   o <install as..> tags for <file name=... platform=!other platform install-as=..>
                   21480:      *   o <ignore> tags for <file name=... platform=!this platform>
                   21481:      *   o <ignore> tags for <file name=... platform=other platform>
                   21482:      *   o <ignore> tags for <file name=... platform=other platform install-as=..>
                   21483:      *   o <ignore> tags for <file name=... platform=!this platform install-as=..>
                   21484:      * </pre>
                   21485:      *
                   21486:      * It does this by accessing the $package parameter, which contains an array with
                   21487:      * indices:
                   21488:      *
                   21489:      *  - platform: mapping of file => OS the file should be installed on
                   21490:      *  - install-as: mapping of file => installed name
                   21491:      *  - osmap: mapping of OS => list of files that should be installed
                   21492:      *    on that OS
                   21493:      *  - notosmap: mapping of OS => list of files that should not be
                   21494:      *    installed on that OS
                   21495:      *
                   21496:      * @param array
                   21497:      * @param array
                   21498:      * @access private
                   21499:      */
                   21500:     function _convertRelease2_0(&$release, $package)
                   21501:     {
                   21502:         //- if any install-as/platform exist, create a generic release and fill it with
                   21503:         if (count($package['platform']) || count($package['install-as'])) {
                   21504:             $generic = array();
                   21505:             $genericIgnore = array();
                   21506:             foreach ($package['install-as'] as $file => $as) {
                   21507:                 //o <install as=..> tags for <file name=... install-as=...>
                   21508:                 if (!isset($package['platform'][$file])) {
                   21509:                     $generic[] = $file;
                   21510:                     continue;
                   21511:                 }
                   21512:                 //o <install as=..> tags for <file name=... platform=!... install-as=..>
                   21513:                 if (isset($package['platform'][$file]) &&
                   21514:                       $package['platform'][$file]{0} == '!') {
                   21515:                     $generic[] = $file;
                   21516:                     continue;
                   21517:                 }
                   21518:                 //o <ignore> tags for <file name=... platform=... install-as=..>
                   21519:                 if (isset($package['platform'][$file]) &&
                   21520:                       $package['platform'][$file]{0} != '!') {
                   21521:                     $genericIgnore[] = $file;
                   21522:                     continue;
                   21523:                 }
                   21524:             }
                   21525:             foreach ($package['platform'] as $file => $platform) {
                   21526:                 if (isset($package['install-as'][$file])) {
                   21527:                     continue;
                   21528:                 }
                   21529:                 if ($platform{0} != '!') {
                   21530:                     //o <ignore> tags for <file name=... platform=...>
                   21531:                     $genericIgnore[] = $file;
                   21532:                 }
                   21533:             }
                   21534:             if (count($package['platform'])) {
                   21535:                 $oses = $notplatform = $platform = array();
                   21536:                 foreach ($package['platform'] as $file => $os) {
                   21537:                     // get a list of oses
                   21538:                     if ($os{0} == '!') {
                   21539:                         if (isset($oses[substr($os, 1)])) {
                   21540:                             continue;
                   21541:                         }
                   21542:                         $oses[substr($os, 1)] = count($oses);
                   21543:                     } else {
                   21544:                         if (isset($oses[$os])) {
                   21545:                             continue;
                   21546:                         }
                   21547:                         $oses[$os] = count($oses);
                   21548:                     }
                   21549:                 }
                   21550:                 //- create a release for each platform encountered and fill with
                   21551:                 foreach ($oses as $os => $releaseNum) {
                   21552:                     $release[$releaseNum]['installconditions']['os']['name'] = $os;
                   21553:                     $release[$releaseNum]['filelist'] = array('install' => array(),
                   21554:                         'ignore' => array());
                   21555:                     foreach ($package['install-as'] as $file => $as) {
                   21556:                         //o <install as=..> tags for <file name=... install-as=...>
                   21557:                         if (!isset($package['platform'][$file])) {
                   21558:                             $release[$releaseNum]['filelist']['install'][] =
                   21559:                                 array(
                   21560:                                     'attribs' => array(
                   21561:                                         'name' => $file,
                   21562:                                         'as' => $as,
                   21563:                                     ),
                   21564:                                 );
                   21565:                             continue;
                   21566:                         }
                   21567:                         //o <install as..> tags for
                   21568:                         //  <file name=... platform=this platform install-as=..>
                   21569:                         if (isset($package['platform'][$file]) &&
                   21570:                               $package['platform'][$file] == $os) {
                   21571:                             $release[$releaseNum]['filelist']['install'][] =
                   21572:                                 array(
                   21573:                                     'attribs' => array(
                   21574:                                         'name' => $file,
                   21575:                                         'as' => $as,
                   21576:                                     ),
                   21577:                                 );
                   21578:                             continue;
                   21579:                         }
                   21580:                         //o <install as..> tags for
                   21581:                         //  <file name=... platform=!other platform install-as=..>
                   21582:                         if (isset($package['platform'][$file]) &&
                   21583:                               $package['platform'][$file] != "!$os" &&
                   21584:                               $package['platform'][$file]{0} == '!') {
                   21585:                             $release[$releaseNum]['filelist']['install'][] =
                   21586:                                 array(
                   21587:                                     'attribs' => array(
                   21588:                                         'name' => $file,
                   21589:                                         'as' => $as,
                   21590:                                     ),
                   21591:                                 );
                   21592:                             continue;
                   21593:                         }
                   21594:                         //o <ignore> tags for
                   21595:                         //  <file name=... platform=!this platform install-as=..>
                   21596:                         if (isset($package['platform'][$file]) &&
                   21597:                               $package['platform'][$file] == "!$os") {
                   21598:                             $release[$releaseNum]['filelist']['ignore'][] =
                   21599:                                 array(
                   21600:                                     'attribs' => array(
                   21601:                                         'name' => $file,
                   21602:                                     ),
                   21603:                                 );
                   21604:                             continue;
                   21605:                         }
                   21606:                         //o <ignore> tags for
                   21607:                         //  <file name=... platform=other platform install-as=..>
                   21608:                         if (isset($package['platform'][$file]) &&
                   21609:                               $package['platform'][$file]{0} != '!' &&
                   21610:                               $package['platform'][$file] != $os) {
                   21611:                             $release[$releaseNum]['filelist']['ignore'][] =
                   21612:                                 array(
                   21613:                                     'attribs' => array(
                   21614:                                         'name' => $file,
                   21615:                                     ),
                   21616:                                 );
                   21617:                             continue;
                   21618:                         }
                   21619:                     }
                   21620:                     foreach ($package['platform'] as $file => $platform) {
                   21621:                         if (isset($package['install-as'][$file])) {
                   21622:                             continue;
                   21623:                         }
                   21624:                         //o <ignore> tags for <file name=... platform=!this platform>
                   21625:                         if ($platform == "!$os") {
                   21626:                             $release[$releaseNum]['filelist']['ignore'][] =
                   21627:                                 array(
                   21628:                                     'attribs' => array(
                   21629:                                         'name' => $file,
                   21630:                                     ),
                   21631:                                 );
                   21632:                             continue;
                   21633:                         }
                   21634:                         //o <ignore> tags for <file name=... platform=other platform>
                   21635:                         if ($platform{0} != '!' && $platform != $os) {
                   21636:                             $release[$releaseNum]['filelist']['ignore'][] =
                   21637:                                 array(
                   21638:                                     'attribs' => array(
                   21639:                                         'name' => $file,
                   21640:                                     ),
                   21641:                                 );
                   21642:                         }
                   21643:                     }
                   21644:                     if (!count($release[$releaseNum]['filelist']['install'])) {
                   21645:                         unset($release[$releaseNum]['filelist']['install']);
                   21646:                     }
                   21647:                     if (!count($release[$releaseNum]['filelist']['ignore'])) {
                   21648:                         unset($release[$releaseNum]['filelist']['ignore']);
                   21649:                     }
                   21650:                 }
                   21651:                 if (count($generic) || count($genericIgnore)) {
                   21652:                     $release[count($oses)] = array();
                   21653:                     if (count($generic)) {
                   21654:                         foreach ($generic as $file) {
                   21655:                             if (isset($package['install-as'][$file])) {
                   21656:                                 $installas = $package['install-as'][$file];
                   21657:                             } else {
                   21658:                                 $installas = $file;
                   21659:                             }
                   21660:                             $release[count($oses)]['filelist']['install'][] =
                   21661:                                 array(
                   21662:                                     'attribs' => array(
                   21663:                                         'name' => $file,
                   21664:                                         'as' => $installas,
                   21665:                                     )
                   21666:                                 );
                   21667:                         }
                   21668:                     }
                   21669:                     if (count($genericIgnore)) {
                   21670:                         foreach ($genericIgnore as $file) {
                   21671:                             $release[count($oses)]['filelist']['ignore'][] =
                   21672:                                 array(
                   21673:                                     'attribs' => array(
                   21674:                                         'name' => $file,
                   21675:                                     )
                   21676:                                 );
                   21677:                         }
                   21678:                     }
                   21679:                 }
                   21680:                 // cleanup
                   21681:                 foreach ($release as $i => $rel) {
                   21682:                     if (isset($rel['filelist']['install']) &&
                   21683:                           count($rel['filelist']['install']) == 1) {
                   21684:                         $release[$i]['filelist']['install'] =
                   21685:                             $release[$i]['filelist']['install'][0];
                   21686:                     }
                   21687:                     if (isset($rel['filelist']['ignore']) &&
                   21688:                           count($rel['filelist']['ignore']) == 1) {
                   21689:                         $release[$i]['filelist']['ignore'] =
                   21690:                             $release[$i]['filelist']['ignore'][0];
                   21691:                     }
                   21692:                 }
                   21693:                 if (count($release) == 1) {
                   21694:                     $release = $release[0];
                   21695:                 }
                   21696:             } else {
                   21697:                 // no platform atts, but some install-as atts
                   21698:                 foreach ($package['install-as'] as $file => $value) {
                   21699:                     $release['filelist']['install'][] =
                   21700:                         array(
                   21701:                             'attribs' => array(
                   21702:                                 'name' => $file,
                   21703:                                 'as' => $value
                   21704:                             )
                   21705:                         );
                   21706:                 }
                   21707:                 if (count($release['filelist']['install']) == 1) {
                   21708:                     $release['filelist']['install'] = $release['filelist']['install'][0];
                   21709:                 }
                   21710:             }
                   21711:         }
                   21712:     }
                   21713: 
                   21714:     /**
                   21715:      * @param array
                   21716:      * @return array
                   21717:      * @access private
                   21718:      */
                   21719:     function _processDep($dep)
                   21720:     {
                   21721:         if ($dep['type'] == 'php') {
                   21722:             if ($dep['rel'] == 'has') {
                   21723:                 // come on - everyone has php!
                   21724:                 return false;
                   21725:             }
                   21726:         }
                   21727:         $php = array();
                   21728:         if ($dep['type'] != 'php') {
                   21729:             $php['name'] = $dep['name'];
                   21730:             if ($dep['type'] == 'pkg') {
                   21731:                 $php['channel'] = 'pear.php.net';
                   21732:             }
                   21733:         }
                   21734:         switch ($dep['rel']) {
                   21735:             case 'gt' :
                   21736:                 $php['min'] = $dep['version'];
                   21737:                 $php['exclude'] = $dep['version'];
                   21738:             break;
                   21739:             case 'ge' :
                   21740:                 if (!isset($dep['version'])) {
                   21741:                     if ($dep['type'] == 'php') {
                   21742:                         if (isset($dep['name'])) {
                   21743:                             $dep['version'] = $dep['name'];
                   21744:                         }
                   21745:                     }
                   21746:                 }
                   21747:                 $php['min'] = $dep['version'];
                   21748:             break;
                   21749:             case 'lt' :
                   21750:                 $php['max'] = $dep['version'];
                   21751:                 $php['exclude'] = $dep['version'];
                   21752:             break;
                   21753:             case 'le' :
                   21754:                 $php['max'] = $dep['version'];
                   21755:             break;
                   21756:             case 'eq' :
                   21757:                 $php['min'] = $dep['version'];
                   21758:                 $php['max'] = $dep['version'];
                   21759:             break;
                   21760:             case 'ne' :
                   21761:                 $php['exclude'] = $dep['version'];
                   21762:             break;
                   21763:             case 'not' :
                   21764:                 $php['conflicts'] = 'yes';
                   21765:             break;
                   21766:         }
                   21767:         return $php;
                   21768:     }
                   21769: 
                   21770:     /**
                   21771:      * @param array
                   21772:      * @return array
                   21773:      */
                   21774:     function _processPhpDeps($deps)
                   21775:     {
                   21776:         $test = array();
                   21777:         foreach ($deps as $dep) {
                   21778:             $test[] = $this->_processDep($dep);
                   21779:         }
                   21780:         $min = array();
                   21781:         $max = array();
                   21782:         foreach ($test as $dep) {
                   21783:             if (!$dep) {
                   21784:                 continue;
                   21785:             }
                   21786:             if (isset($dep['min'])) {
                   21787:                 $min[$dep['min']] = count($min);
                   21788:             }
                   21789:             if (isset($dep['max'])) {
                   21790:                 $max[$dep['max']] = count($max);
                   21791:             }
                   21792:         }
                   21793:         if (count($min) > 0) {
                   21794:             uksort($min, 'version_compare');
                   21795:         }
                   21796:         if (count($max) > 0) {
                   21797:             uksort($max, 'version_compare');
                   21798:         }
                   21799:         if (count($min)) {
                   21800:             // get the highest minimum
                   21801:             $min = array_pop($a = array_flip($min));
                   21802:         } else {
                   21803:             $min = false;
                   21804:         }
                   21805:         if (count($max)) {
                   21806:             // get the lowest maximum
                   21807:             $max = array_shift($a = array_flip($max));
                   21808:         } else {
                   21809:             $max = false;
                   21810:         }
                   21811:         if ($min) {
                   21812:             $php['min'] = $min;
                   21813:         }
                   21814:         if ($max) {
                   21815:             $php['max'] = $max;
                   21816:         }
                   21817:         $exclude = array();
                   21818:         foreach ($test as $dep) {
                   21819:             if (!isset($dep['exclude'])) {
                   21820:                 continue;
                   21821:             }
                   21822:             $exclude[] = $dep['exclude'];
                   21823:         }
                   21824:         if (count($exclude)) {
                   21825:             $php['exclude'] = $exclude;
                   21826:         }
                   21827:         return $php;
                   21828:     }
                   21829: 
                   21830:     /**
                   21831:      * process multiple dependencies that have a name, like package deps
                   21832:      * @param array
                   21833:      * @return array
                   21834:      * @access private
                   21835:      */
                   21836:     function _processMultipleDepsName($deps)
                   21837:     {
                   21838:         $ret = $tests = array();
                   21839:         foreach ($deps as $name => $dep) {
                   21840:             foreach ($dep as $d) {
                   21841:                 $tests[$name][] = $this->_processDep($d);
                   21842:             }
                   21843:         }
                   21844: 
                   21845:         foreach ($tests as $name => $test) {
                   21846:             $max = $min = $php = array();
                   21847:             $php['name'] = $name;
                   21848:             foreach ($test as $dep) {
                   21849:                 if (!$dep) {
                   21850:                     continue;
                   21851:                 }
                   21852:                 if (isset($dep['channel'])) {
                   21853:                     $php['channel'] = 'pear.php.net';
                   21854:                 }
                   21855:                 if (isset($dep['conflicts']) && $dep['conflicts'] == 'yes') {
                   21856:                     $php['conflicts'] = 'yes';
                   21857:                 }
                   21858:                 if (isset($dep['min'])) {
                   21859:                     $min[$dep['min']] = count($min);
                   21860:                 }
                   21861:                 if (isset($dep['max'])) {
                   21862:                     $max[$dep['max']] = count($max);
                   21863:                 }
                   21864:             }
                   21865:             if (count($min) > 0) {
                   21866:                 uksort($min, 'version_compare');
                   21867:             }
                   21868:             if (count($max) > 0) {
                   21869:                 uksort($max, 'version_compare');
                   21870:             }
                   21871:             if (count($min)) {
                   21872:                 // get the highest minimum
                   21873:                 $min = array_pop($a = array_flip($min));
                   21874:             } else {
                   21875:                 $min = false;
                   21876:             }
                   21877:             if (count($max)) {
                   21878:                 // get the lowest maximum
                   21879:                 $max = array_shift($a = array_flip($max));
                   21880:             } else {
                   21881:                 $max = false;
                   21882:             }
                   21883:             if ($min) {
                   21884:                 $php['min'] = $min;
                   21885:             }
                   21886:             if ($max) {
                   21887:                 $php['max'] = $max;
                   21888:             }
                   21889:             $exclude = array();
                   21890:             foreach ($test as $dep) {
                   21891:                 if (!isset($dep['exclude'])) {
                   21892:                     continue;
                   21893:                 }
                   21894:                 $exclude[] = $dep['exclude'];
                   21895:             }
                   21896:             if (count($exclude)) {
                   21897:                 $php['exclude'] = $exclude;
                   21898:             }
                   21899:             $ret[] = $php;
                   21900:         }
                   21901:         return $ret;
                   21902:     }
                   21903: }
1.1.1.2 ! misho    21904: ?>PEAR-1.9.4/PEAR/PackageFile/Generator/v2.php0000644000076500000240000010136011605156614017105 0ustar  helgistaff<?php
1.1       misho    21905: /**
                   21906:  * package.xml generation class, package.xml version 2.0
                   21907:  *
                   21908:  * PHP versions 4 and 5
                   21909:  *
                   21910:  * @category   pear
                   21911:  * @package    PEAR
                   21912:  * @author     Greg Beaver <cellog@php.net>
                   21913:  * @author     Stephan Schmidt (original XML_Serializer code)
                   21914:  * @copyright  1997-2009 The Authors
                   21915:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   21916:  * @version    CVS: $Id: v2.php 313023 2011-07-06 19:17:11Z dufuz $
                   21917:  * @link       http://pear.php.net/package/PEAR
                   21918:  * @since      File available since Release 1.4.0a1
                   21919:  */
                   21920: /**
                   21921:  * file/dir manipulation routines
                   21922:  */
                   21923: require_once 'System.php';
                   21924: require_once 'XML/Util.php';
                   21925: 
                   21926: /**
                   21927:  * This class converts a PEAR_PackageFile_v2 object into any output format.
                   21928:  *
                   21929:  * Supported output formats include array, XML string (using S. Schmidt's
                   21930:  * XML_Serializer, slightly customized)
                   21931:  * @category   pear
                   21932:  * @package    PEAR
                   21933:  * @author     Greg Beaver <cellog@php.net>
                   21934:  * @author     Stephan Schmidt (original XML_Serializer code)
                   21935:  * @copyright  1997-2009 The Authors
                   21936:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   21937:  * @version    Release: 1.9.4
                   21938:  * @link       http://pear.php.net/package/PEAR
                   21939:  * @since      Class available since Release 1.4.0a1
                   21940:  */
                   21941: class PEAR_PackageFile_Generator_v2
                   21942: {
                   21943:    /**
                   21944:     * default options for the serialization
                   21945:     * @access private
                   21946:     * @var array $_defaultOptions
                   21947:     */
                   21948:     var $_defaultOptions = array(
                   21949:         'indent'             => ' ',                    // string used for indentation
                   21950:         'linebreak'          => "\n",                  // string used for newlines
                   21951:         'typeHints'          => false,                 // automatically add type hin attributes
                   21952:         'addDecl'            => true,                 // add an XML declaration
                   21953:         'defaultTagName'     => 'XML_Serializer_Tag',  // tag used for indexed arrays or invalid names
                   21954:         'classAsTagName'     => false,                 // use classname for objects in indexed arrays
                   21955:         'keyAttribute'       => '_originalKey',        // attribute where original key is stored
                   21956:         'typeAttribute'      => '_type',               // attribute for type (only if typeHints => true)
                   21957:         'classAttribute'     => '_class',              // attribute for class of objects (only if typeHints => true)
                   21958:         'scalarAsAttributes' => false,                 // scalar values (strings, ints,..) will be serialized as attribute
                   21959:         'prependAttributes'  => '',                    // prepend string for attributes
                   21960:         'indentAttributes'   => false,                 // indent the attributes, if set to '_auto', it will indent attributes so they all start at the same column
                   21961:         'mode'               => 'simplexml',             // use 'simplexml' to use parent name as tagname if transforming an indexed array
                   21962:         'addDoctype'         => false,                 // add a doctype declaration
                   21963:         'doctype'            => null,                  // supply a string or an array with id and uri ({@see XML_Util::getDoctypeDeclaration()}
                   21964:         'rootName'           => 'package',                  // name of the root tag
                   21965:         'rootAttributes'     => array(
                   21966:             'version' => '2.0',
                   21967:             'xmlns' => 'http://pear.php.net/dtd/package-2.0',
                   21968:             'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
                   21969:             'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
                   21970:             'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
                   21971: http://pear.php.net/dtd/tasks-1.0.xsd
                   21972: http://pear.php.net/dtd/package-2.0
                   21973: http://pear.php.net/dtd/package-2.0.xsd',
                   21974:         ),               // attributes of the root tag
                   21975:         'attributesArray'    => 'attribs',                  // all values in this key will be treated as attributes
                   21976:         'contentName'        => '_content',                   // this value will be used directly as content, instead of creating a new tag, may only be used in conjuction with attributesArray
                   21977:         'beautifyFilelist'   => false,
                   21978:         'encoding' => 'UTF-8',
                   21979:     );
                   21980: 
                   21981:    /**
                   21982:     * options for the serialization
                   21983:     * @access private
                   21984:     * @var array $options
                   21985:     */
                   21986:     var $options = array();
                   21987: 
                   21988:    /**
                   21989:     * current tag depth
                   21990:     * @var integer $_tagDepth
                   21991:     */
                   21992:     var $_tagDepth = 0;
                   21993: 
                   21994:    /**
                   21995:     * serilialized representation of the data
                   21996:     * @var string $_serializedData
                   21997:     */
                   21998:     var $_serializedData = null;
                   21999:     /**
                   22000:      * @var PEAR_PackageFile_v2
                   22001:      */
                   22002:     var $_packagefile;
                   22003:     /**
                   22004:      * @param PEAR_PackageFile_v2
                   22005:      */
                   22006:     function PEAR_PackageFile_Generator_v2(&$packagefile)
                   22007:     {
                   22008:         $this->_packagefile = &$packagefile;
                   22009:         if (isset($this->_packagefile->encoding)) {
                   22010:             $this->_defaultOptions['encoding'] = $this->_packagefile->encoding;
                   22011:         }
                   22012:     }
                   22013: 
                   22014:     /**
                   22015:      * @return string
                   22016:      */
                   22017:     function getPackagerVersion()
                   22018:     {
                   22019:         return '1.9.4';
                   22020:     }
                   22021: 
                   22022:     /**
                   22023:      * @param PEAR_Packager
                   22024:      * @param bool generate a .tgz or a .tar
                   22025:      * @param string|null temporary directory to package in
                   22026:      */
                   22027:     function toTgz(&$packager, $compress = true, $where = null)
                   22028:     {
                   22029:         $a = null;
                   22030:         return $this->toTgz2($packager, $a, $compress, $where);
                   22031:     }
                   22032: 
                   22033:     /**
                   22034:      * Package up both a package.xml and package2.xml for the same release
                   22035:      * @param PEAR_Packager
                   22036:      * @param PEAR_PackageFile_v1
                   22037:      * @param bool generate a .tgz or a .tar
                   22038:      * @param string|null temporary directory to package in
                   22039:      */
                   22040:     function toTgz2(&$packager, &$pf1, $compress = true, $where = null)
                   22041:     {
                   22042:         require_once 'Archive/Tar.php';
                   22043:         if (!$this->_packagefile->isEquivalent($pf1)) {
                   22044:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' .
                   22045:                 basename($pf1->getPackageFile()) .
                   22046:                 '" is not equivalent to "' . basename($this->_packagefile->getPackageFile())
                   22047:                 . '"');
                   22048:         }
                   22049: 
                   22050:         if ($where === null) {
                   22051:             if (!($where = System::mktemp(array('-d')))) {
                   22052:                 return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: mktemp failed');
                   22053:             }
                   22054:         } elseif (!@System::mkDir(array('-p', $where))) {
                   22055:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' . $where . '" could' .
                   22056:                 ' not be created');
                   22057:         }
                   22058: 
                   22059:         $file = $where . DIRECTORY_SEPARATOR . 'package.xml';
                   22060:         if (file_exists($file) && !is_file($file)) {
                   22061:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: unable to save package.xml as' .
                   22062:                 ' "' . $file  .'"');
                   22063:         }
                   22064: 
                   22065:         if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) {
                   22066:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: invalid package.xml');
                   22067:         }
                   22068: 
                   22069:         $ext = $compress ? '.tgz' : '.tar';
                   22070:         $pkgver = $this->_packagefile->getPackage() . '-' . $this->_packagefile->getVersion();
                   22071:         $dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext;
                   22072:         if (file_exists($dest_package) && !is_file($dest_package)) {
                   22073:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: cannot create tgz file "' .
                   22074:                 $dest_package . '"');
                   22075:         }
                   22076: 
                   22077:         $pkgfile = $this->_packagefile->getPackageFile();
                   22078:         if (!$pkgfile) {
                   22079:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: package file object must ' .
                   22080:                 'be created from a real file');
                   22081:         }
                   22082: 
                   22083:         $pkgdir  = dirname(realpath($pkgfile));
                   22084:         $pkgfile = basename($pkgfile);
                   22085: 
                   22086:         // {{{ Create the package file list
                   22087:         $filelist = array();
                   22088:         $i = 0;
                   22089:         $this->_packagefile->flattenFilelist();
                   22090:         $contents = $this->_packagefile->getContents();
                   22091:         if (isset($contents['bundledpackage'])) { // bundles of packages
                   22092:             $contents = $contents['bundledpackage'];
                   22093:             if (!isset($contents[0])) {
                   22094:                 $contents = array($contents);
                   22095:             }
                   22096: 
                   22097:             $packageDir = $where;
                   22098:             foreach ($contents as $i => $package) {
                   22099:                 $fname = $package;
                   22100:                 $file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
                   22101:                 if (!file_exists($file)) {
                   22102:                     return $packager->raiseError("File does not exist: $fname");
                   22103:                 }
                   22104: 
                   22105:                 $tfile = $packageDir . DIRECTORY_SEPARATOR . $fname;
                   22106:                 System::mkdir(array('-p', dirname($tfile)));
                   22107:                 copy($file, $tfile);
                   22108:                 $filelist[$i++] = $tfile;
                   22109:                 $packager->log(2, "Adding package $fname");
                   22110:             }
                   22111:         } else { // normal packages
                   22112:             $contents = $contents['dir']['file'];
                   22113:             if (!isset($contents[0])) {
                   22114:                 $contents = array($contents);
                   22115:             }
                   22116: 
                   22117:             $packageDir = $where;
                   22118:             foreach ($contents as $i => $file) {
                   22119:                 $fname = $file['attribs']['name'];
                   22120:                 $atts = $file['attribs'];
                   22121:                 $orig = $file;
                   22122:                 $file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
                   22123:                 if (!file_exists($file)) {
                   22124:                     return $packager->raiseError("File does not exist: $fname");
                   22125:                 }
                   22126: 
                   22127:                 $origperms = fileperms($file);
                   22128:                 $tfile = $packageDir . DIRECTORY_SEPARATOR . $fname;
                   22129:                 unset($orig['attribs']);
                   22130:                 if (count($orig)) { // file with tasks
                   22131:                     // run any package-time tasks
                   22132:                     $contents = file_get_contents($file);
                   22133:                     foreach ($orig as $tag => $raw) {
                   22134:                         $tag = str_replace(
                   22135:                             array($this->_packagefile->getTasksNs() . ':', '-'),
                   22136:                             array('', '_'), $tag);
                   22137:                         $task = "PEAR_Task_$tag";
                   22138:                         $task = &new $task($this->_packagefile->_config,
                   22139:                             $this->_packagefile->_logger,
                   22140:                             PEAR_TASK_PACKAGE);
                   22141:                         $task->init($raw, $atts, null);
                   22142:                         $res = $task->startSession($this->_packagefile, $contents, $tfile);
                   22143:                         if (!$res) {
                   22144:                             continue; // skip this task
                   22145:                         }
                   22146: 
                   22147:                         if (PEAR::isError($res)) {
                   22148:                             return $res;
                   22149:                         }
                   22150: 
                   22151:                         $contents = $res; // save changes
                   22152:                         System::mkdir(array('-p', dirname($tfile)));
                   22153:                         $wp = fopen($tfile, "wb");
                   22154:                         fwrite($wp, $contents);
                   22155:                         fclose($wp);
                   22156:                     }
                   22157:                 }
                   22158: 
                   22159:                 if (!file_exists($tfile)) {
                   22160:                     System::mkdir(array('-p', dirname($tfile)));
                   22161:                     copy($file, $tfile);
                   22162:                 }
                   22163: 
                   22164:                 chmod($tfile, $origperms);
                   22165:                 $filelist[$i++] = $tfile;
                   22166:                 $this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($tfile), $i - 1);
                   22167:                 $packager->log(2, "Adding file $fname");
                   22168:             }
                   22169:         }
                   22170:             // }}}
                   22171: 
                   22172:         $name       = $pf1 !== null ? 'package2.xml' : 'package.xml';
                   22173:         $packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, $name);
                   22174:         if ($packagexml) {
                   22175:             $tar =& new Archive_Tar($dest_package, $compress);
                   22176:             $tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors
                   22177:             // ----- Creates with the package.xml file
                   22178:             $ok = $tar->createModify(array($packagexml), '', $where);
                   22179:             if (PEAR::isError($ok)) {
                   22180:                 return $packager->raiseError($ok);
                   22181:             } elseif (!$ok) {
                   22182:                 return $packager->raiseError('PEAR_Packagefile_v2::toTgz(): adding ' . $name .
                   22183:                     ' failed');
                   22184:             }
                   22185: 
                   22186:             // ----- Add the content of the package
                   22187:             if (!$tar->addModify($filelist, $pkgver, $where)) {
                   22188:                 return $packager->raiseError(
                   22189:                     'PEAR_Packagefile_v2::toTgz(): tarball creation failed');
                   22190:             }
                   22191: 
                   22192:             // add the package.xml version 1.0
                   22193:             if ($pf1 !== null) {
                   22194:                 $pfgen = &$pf1->getDefaultGenerator();
                   22195:                 $packagexml1 = $pfgen->toPackageFile($where, PEAR_VALIDATE_PACKAGING, 'package.xml', true);
                   22196:                 if (!$tar->addModify(array($packagexml1), '', $where)) {
                   22197:                     return $packager->raiseError(
                   22198:                         'PEAR_Packagefile_v2::toTgz(): adding package.xml failed');
                   22199:                 }
                   22200:             }
                   22201: 
                   22202:             return $dest_package;
                   22203:         }
                   22204:     }
                   22205: 
                   22206:     function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml')
                   22207:     {
                   22208:         if (!$this->_packagefile->validate($state)) {
                   22209:             return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: invalid package.xml',
                   22210:                 null, null, null, $this->_packagefile->getValidationWarnings());
                   22211:         }
                   22212: 
                   22213:         if ($where === null) {
                   22214:             if (!($where = System::mktemp(array('-d')))) {
                   22215:                 return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: mktemp failed');
                   22216:             }
                   22217:         } elseif (!@System::mkDir(array('-p', $where))) {
                   22218:             return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: "' . $where . '" could' .
                   22219:                 ' not be created');
                   22220:         }
                   22221: 
                   22222:         $newpkgfile = $where . DIRECTORY_SEPARATOR . $name;
                   22223:         $np = @fopen($newpkgfile, 'wb');
                   22224:         if (!$np) {
                   22225:             return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: unable to save ' .
                   22226:                "$name as $newpkgfile");
                   22227:         }
                   22228:         fwrite($np, $this->toXml($state));
                   22229:         fclose($np);
                   22230:         return $newpkgfile;
                   22231:     }
                   22232: 
                   22233:     function &toV2()
                   22234:     {
                   22235:         return $this->_packagefile;
                   22236:     }
                   22237: 
                   22238:     /**
                   22239:      * Return an XML document based on the package info (as returned
                   22240:      * by the PEAR_Common::infoFrom* methods).
                   22241:      *
                   22242:      * @return string XML data
                   22243:      */
                   22244:     function toXml($state = PEAR_VALIDATE_NORMAL, $options = array())
                   22245:     {
                   22246:         $this->_packagefile->setDate(date('Y-m-d'));
                   22247:         $this->_packagefile->setTime(date('H:i:s'));
                   22248:         if (!$this->_packagefile->validate($state)) {
                   22249:             return false;
                   22250:         }
                   22251: 
                   22252:         if (is_array($options)) {
                   22253:             $this->options = array_merge($this->_defaultOptions, $options);
                   22254:         } else {
                   22255:             $this->options = $this->_defaultOptions;
                   22256:         }
                   22257: 
                   22258:         $arr = $this->_packagefile->getArray();
                   22259:         if (isset($arr['filelist'])) {
                   22260:             unset($arr['filelist']);
                   22261:         }
                   22262: 
                   22263:         if (isset($arr['_lastversion'])) {
                   22264:             unset($arr['_lastversion']);
                   22265:         }
                   22266: 
                   22267:         // Fix the notes a little bit
                   22268:         if (isset($arr['notes'])) {
                   22269:             // This trims out the indenting, needs fixing
                   22270:             $arr['notes'] = "\n" . trim($arr['notes']) . "\n";
                   22271:         }
                   22272: 
                   22273:         if (isset($arr['changelog']) && !empty($arr['changelog'])) {
                   22274:             // Fix for inconsistency how the array is filled depending on the changelog release amount
                   22275:             if (!isset($arr['changelog']['release'][0])) {
                   22276:                 $release = $arr['changelog']['release'];
                   22277:                 unset($arr['changelog']['release']);
                   22278: 
                   22279:                 $arr['changelog']['release']    = array();
                   22280:                 $arr['changelog']['release'][0] = $release;
                   22281:             }
                   22282: 
                   22283:             foreach (array_keys($arr['changelog']['release']) as $key) {
                   22284:                 $c =& $arr['changelog']['release'][$key];
                   22285:                 if (isset($c['notes'])) {
                   22286:                     // This trims out the indenting, needs fixing
                   22287:                     $c['notes'] = "\n" . trim($c['notes']) . "\n";
                   22288:                 }
                   22289:             }
                   22290:         }
                   22291: 
                   22292:         if ($state ^ PEAR_VALIDATE_PACKAGING && !isset($arr['bundle'])) {
                   22293:             $use = $this->_recursiveXmlFilelist($arr['contents']['dir']['file']);
                   22294:             unset($arr['contents']['dir']['file']);
                   22295:             if (isset($use['dir'])) {
                   22296:                 $arr['contents']['dir']['dir'] = $use['dir'];
                   22297:             }
                   22298:             if (isset($use['file'])) {
                   22299:                 $arr['contents']['dir']['file'] = $use['file'];
                   22300:             }
                   22301:             $this->options['beautifyFilelist'] = true;
                   22302:         }
                   22303: 
                   22304:         $arr['attribs']['packagerversion'] = '1.9.4';
                   22305:         if ($this->serialize($arr, $options)) {
                   22306:             return $this->_serializedData . "\n";
                   22307:         }
                   22308: 
                   22309:         return false;
                   22310:     }
                   22311: 
                   22312: 
                   22313:     function _recursiveXmlFilelist($list)
                   22314:     {
                   22315:         $dirs = array();
                   22316:         if (isset($list['attribs'])) {
                   22317:             $file = $list['attribs']['name'];
                   22318:             unset($list['attribs']['name']);
                   22319:             $attributes = $list['attribs'];
                   22320:             $this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes);
                   22321:         } else {
                   22322:             foreach ($list as $a) {
                   22323:                 $file = $a['attribs']['name'];
                   22324:                 $attributes = $a['attribs'];
                   22325:                 unset($a['attribs']);
                   22326:                 $this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes, $a);
                   22327:             }
                   22328:         }
                   22329:         $this->_formatDir($dirs);
                   22330:         $this->_deFormat($dirs);
                   22331:         return $dirs;
                   22332:     }
                   22333: 
                   22334:     function _addDir(&$dirs, $dir, $file = null, $attributes = null, $tasks = null)
                   22335:     {
                   22336:         if (!$tasks) {
                   22337:             $tasks = array();
                   22338:         }
                   22339:         if ($dir == array() || $dir == array('.')) {
                   22340:             $dirs['file'][basename($file)] = $tasks;
                   22341:             $attributes['name'] = basename($file);
                   22342:             $dirs['file'][basename($file)]['attribs'] = $attributes;
                   22343:             return;
                   22344:         }
                   22345:         $curdir = array_shift($dir);
                   22346:         if (!isset($dirs['dir'][$curdir])) {
                   22347:             $dirs['dir'][$curdir] = array();
                   22348:         }
                   22349:         $this->_addDir($dirs['dir'][$curdir], $dir, $file, $attributes, $tasks);
                   22350:     }
                   22351: 
                   22352:     function _formatDir(&$dirs)
                   22353:     {
                   22354:         if (!count($dirs)) {
                   22355:             return array();
                   22356:         }
                   22357:         $newdirs = array();
                   22358:         if (isset($dirs['dir'])) {
                   22359:             $newdirs['dir'] = $dirs['dir'];
                   22360:         }
                   22361:         if (isset($dirs['file'])) {
                   22362:             $newdirs['file'] = $dirs['file'];
                   22363:         }
                   22364:         $dirs = $newdirs;
                   22365:         if (isset($dirs['dir'])) {
                   22366:             uksort($dirs['dir'], 'strnatcasecmp');
                   22367:             foreach ($dirs['dir'] as $dir => $contents) {
                   22368:                 $this->_formatDir($dirs['dir'][$dir]);
                   22369:             }
                   22370:         }
                   22371:         if (isset($dirs['file'])) {
                   22372:             uksort($dirs['file'], 'strnatcasecmp');
                   22373:         };
                   22374:     }
                   22375: 
                   22376:     function _deFormat(&$dirs)
                   22377:     {
                   22378:         if (!count($dirs)) {
                   22379:             return array();
                   22380:         }
                   22381:         $newdirs = array();
                   22382:         if (isset($dirs['dir'])) {
                   22383:             foreach ($dirs['dir'] as $dir => $contents) {
                   22384:                 $newdir = array();
                   22385:                 $newdir['attribs']['name'] = $dir;
                   22386:                 $this->_deFormat($contents);
                   22387:                 foreach ($contents as $tag => $val) {
                   22388:                     $newdir[$tag] = $val;
                   22389:                 }
                   22390:                 $newdirs['dir'][] = $newdir;
                   22391:             }
                   22392:             if (count($newdirs['dir']) == 1) {
                   22393:                 $newdirs['dir'] = $newdirs['dir'][0];
                   22394:             }
                   22395:         }
                   22396:         if (isset($dirs['file'])) {
                   22397:             foreach ($dirs['file'] as $name => $file) {
                   22398:                 $newdirs['file'][] = $file;
                   22399:             }
                   22400:             if (count($newdirs['file']) == 1) {
                   22401:                 $newdirs['file'] = $newdirs['file'][0];
                   22402:             }
                   22403:         }
                   22404:         $dirs = $newdirs;
                   22405:     }
                   22406: 
                   22407:     /**
                   22408:     * reset all options to default options
                   22409:     *
                   22410:     * @access   public
                   22411:     * @see      setOption(), XML_Unserializer()
                   22412:     */
                   22413:     function resetOptions()
                   22414:     {
                   22415:         $this->options = $this->_defaultOptions;
                   22416:     }
                   22417: 
                   22418:    /**
                   22419:     * set an option
                   22420:     *
                   22421:     * You can use this method if you do not want to set all options in the constructor
                   22422:     *
                   22423:     * @access   public
                   22424:     * @see      resetOption(), XML_Serializer()
                   22425:     */
                   22426:     function setOption($name, $value)
                   22427:     {
                   22428:         $this->options[$name] = $value;
                   22429:     }
                   22430: 
                   22431:    /**
                   22432:     * sets several options at once
                   22433:     *
                   22434:     * You can use this method if you do not want to set all options in the constructor
                   22435:     *
                   22436:     * @access   public
                   22437:     * @see      resetOption(), XML_Unserializer(), setOption()
                   22438:     */
                   22439:     function setOptions($options)
                   22440:     {
                   22441:         $this->options = array_merge($this->options, $options);
                   22442:     }
                   22443: 
                   22444:    /**
                   22445:     * serialize data
                   22446:     *
                   22447:     * @access   public
                   22448:     * @param    mixed    $data data to serialize
                   22449:     * @return   boolean  true on success, pear error on failure
                   22450:     */
                   22451:     function serialize($data, $options = null)
                   22452:     {
                   22453:         // if options have been specified, use them instead
                   22454:         // of the previously defined ones
                   22455:         if (is_array($options)) {
                   22456:             $optionsBak = $this->options;
                   22457:             if (isset($options['overrideOptions']) && $options['overrideOptions'] == true) {
                   22458:                 $this->options = array_merge($this->_defaultOptions, $options);
                   22459:             } else {
                   22460:                 $this->options = array_merge($this->options, $options);
                   22461:             }
                   22462:         } else {
                   22463:             $optionsBak = null;
                   22464:         }
                   22465: 
                   22466:         //  start depth is zero
                   22467:         $this->_tagDepth = 0;
                   22468:         $this->_serializedData = '';
                   22469:         // serialize an array
                   22470:         if (is_array($data)) {
                   22471:             $tagName = isset($this->options['rootName']) ? $this->options['rootName'] : 'array';
                   22472:             $this->_serializedData .= $this->_serializeArray($data, $tagName, $this->options['rootAttributes']);
                   22473:         }
                   22474: 
                   22475:         // add doctype declaration
                   22476:         if ($this->options['addDoctype'] === true) {
                   22477:             $this->_serializedData = XML_Util::getDoctypeDeclaration($tagName, $this->options['doctype'])
                   22478:                                    . $this->options['linebreak']
                   22479:                                    . $this->_serializedData;
                   22480:         }
                   22481: 
                   22482:         //  build xml declaration
                   22483:         if ($this->options['addDecl']) {
                   22484:             $atts = array();
                   22485:             $encoding = isset($this->options['encoding']) ? $this->options['encoding'] : null;
                   22486:             $this->_serializedData = XML_Util::getXMLDeclaration('1.0', $encoding)
                   22487:                                    . $this->options['linebreak']
                   22488:                                    . $this->_serializedData;
                   22489:         }
                   22490: 
                   22491: 
                   22492:         if ($optionsBak !== null) {
                   22493:             $this->options = $optionsBak;
                   22494:         }
                   22495: 
                   22496:         return  true;
                   22497:     }
                   22498: 
                   22499:    /**
                   22500:     * get the result of the serialization
                   22501:     *
                   22502:     * @access public
                   22503:     * @return string serialized XML
                   22504:     */
                   22505:     function getSerializedData()
                   22506:     {
                   22507:         if ($this->_serializedData === null) {
                   22508:             return  $this->raiseError('No serialized data available. Use XML_Serializer::serialize() first.', XML_SERIALIZER_ERROR_NO_SERIALIZATION);
                   22509:         }
                   22510:         return $this->_serializedData;
                   22511:     }
                   22512: 
                   22513:    /**
                   22514:     * serialize any value
                   22515:     *
                   22516:     * This method checks for the type of the value and calls the appropriate method
                   22517:     *
                   22518:     * @access private
                   22519:     * @param  mixed     $value
                   22520:     * @param  string    $tagName
                   22521:     * @param  array     $attributes
                   22522:     * @return string
                   22523:     */
                   22524:     function _serializeValue($value, $tagName = null, $attributes = array())
                   22525:     {
                   22526:         if (is_array($value)) {
                   22527:             $xml = $this->_serializeArray($value, $tagName, $attributes);
                   22528:         } elseif (is_object($value)) {
                   22529:             $xml = $this->_serializeObject($value, $tagName);
                   22530:         } else {
                   22531:             $tag = array(
                   22532:                           'qname'      => $tagName,
                   22533:                           'attributes' => $attributes,
                   22534:                           'content'    => $value
                   22535:                         );
                   22536:             $xml = $this->_createXMLTag($tag);
                   22537:         }
                   22538:         return $xml;
                   22539:     }
                   22540: 
                   22541:    /**
                   22542:     * serialize an array
                   22543:     *
                   22544:     * @access   private
                   22545:     * @param    array   $array       array to serialize
                   22546:     * @param    string  $tagName     name of the root tag
                   22547:     * @param    array   $attributes  attributes for the root tag
                   22548:     * @return   string  $string      serialized data
                   22549:     * @uses     XML_Util::isValidName() to check, whether key has to be substituted
                   22550:     */
                   22551:     function _serializeArray(&$array, $tagName = null, $attributes = array())
                   22552:     {
                   22553:         $_content = null;
                   22554: 
                   22555:         /**
                   22556:          * check for special attributes
                   22557:          */
                   22558:         if ($this->options['attributesArray'] !== null) {
                   22559:             if (isset($array[$this->options['attributesArray']])) {
                   22560:                 $attributes = $array[$this->options['attributesArray']];
                   22561:                 unset($array[$this->options['attributesArray']]);
                   22562:             }
                   22563:             /**
                   22564:              * check for special content
                   22565:              */
                   22566:             if ($this->options['contentName'] !== null) {
                   22567:                 if (isset($array[$this->options['contentName']])) {
                   22568:                     $_content = $array[$this->options['contentName']];
                   22569:                     unset($array[$this->options['contentName']]);
                   22570:                 }
                   22571:             }
                   22572:         }
                   22573: 
                   22574:         /*
                   22575:         * if mode is set to simpleXML, check whether
                   22576:         * the array is associative or indexed
                   22577:         */
                   22578:         if (is_array($array) && $this->options['mode'] == 'simplexml') {
                   22579:             $indexed = true;
                   22580:             if (!count($array)) {
                   22581:                 $indexed = false;
                   22582:             }
                   22583:             foreach ($array as $key => $val) {
                   22584:                 if (!is_int($key)) {
                   22585:                     $indexed = false;
                   22586:                     break;
                   22587:                 }
                   22588:             }
                   22589: 
                   22590:             if ($indexed && $this->options['mode'] == 'simplexml') {
                   22591:                 $string = '';
                   22592:                 foreach ($array as $key => $val) {
                   22593:                     if ($this->options['beautifyFilelist'] && $tagName == 'dir') {
                   22594:                         if (!isset($this->_curdir)) {
                   22595:                             $this->_curdir = '';
                   22596:                         }
                   22597:                         $savedir = $this->_curdir;
                   22598:                         if (isset($val['attribs'])) {
                   22599:                             if ($val['attribs']['name'] == '/') {
                   22600:                                 $this->_curdir = '/';
                   22601:                             } else {
                   22602:                                 if ($this->_curdir == '/') {
                   22603:                                     $this->_curdir = '';
                   22604:                                 }
                   22605:                                 $this->_curdir .= '/' . $val['attribs']['name'];
                   22606:                             }
                   22607:                         }
                   22608:                     }
                   22609:                     $string .= $this->_serializeValue( $val, $tagName, $attributes);
                   22610:                     if ($this->options['beautifyFilelist'] && $tagName == 'dir') {
                   22611:                         $string .= ' <!-- ' . $this->_curdir . ' -->';
                   22612:                         if (empty($savedir)) {
                   22613:                             unset($this->_curdir);
                   22614:                         } else {
                   22615:                             $this->_curdir = $savedir;
                   22616:                         }
                   22617:                     }
                   22618: 
                   22619:                     $string .= $this->options['linebreak'];
                   22620:                     // do indentation
                   22621:                     if ($this->options['indent'] !== null && $this->_tagDepth > 0) {
                   22622:                         $string .= str_repeat($this->options['indent'], $this->_tagDepth);
                   22623:                     }
                   22624:                 }
                   22625:                 return rtrim($string);
                   22626:             }
                   22627:         }
                   22628: 
                   22629:         if ($this->options['scalarAsAttributes'] === true) {
                   22630:             foreach ($array as $key => $value) {
                   22631:                 if (is_scalar($value) && (XML_Util::isValidName($key) === true)) {
                   22632:                     unset($array[$key]);
                   22633:                     $attributes[$this->options['prependAttributes'].$key] = $value;
                   22634:                 }
                   22635:             }
                   22636:         }
                   22637: 
                   22638:         // check for empty array => create empty tag
                   22639:         if (empty($array)) {
                   22640:             $tag = array(
                   22641:                             'qname'      => $tagName,
                   22642:                             'content'    => $_content,
                   22643:                             'attributes' => $attributes
                   22644:                         );
                   22645: 
                   22646:         } else {
                   22647:             $this->_tagDepth++;
                   22648:             $tmp = $this->options['linebreak'];
                   22649:             foreach ($array as $key => $value) {
                   22650:                 // do indentation
                   22651:                 if ($this->options['indent'] !== null && $this->_tagDepth > 0) {
                   22652:                     $tmp .= str_repeat($this->options['indent'], $this->_tagDepth);
                   22653:                 }
                   22654: 
                   22655:                 // copy key
                   22656:                 $origKey = $key;
                   22657:                 // key cannot be used as tagname => use default tag
                   22658:                 $valid = XML_Util::isValidName($key);
                   22659:                 if (PEAR::isError($valid)) {
                   22660:                     if ($this->options['classAsTagName'] && is_object($value)) {
                   22661:                         $key = get_class($value);
                   22662:                     } else {
                   22663:                         $key = $this->options['defaultTagName'];
                   22664:                     }
                   22665:                 }
                   22666:                 $atts = array();
                   22667:                 if ($this->options['typeHints'] === true) {
                   22668:                     $atts[$this->options['typeAttribute']] = gettype($value);
                   22669:                     if ($key !== $origKey) {
                   22670:                         $atts[$this->options['keyAttribute']] = (string)$origKey;
                   22671:                     }
                   22672: 
                   22673:                 }
                   22674:                 if ($this->options['beautifyFilelist'] && $key == 'dir') {
                   22675:                     if (!isset($this->_curdir)) {
                   22676:                         $this->_curdir = '';
                   22677:                     }
                   22678:                     $savedir = $this->_curdir;
                   22679:                     if (isset($value['attribs'])) {
                   22680:                         if ($value['attribs']['name'] == '/') {
                   22681:                             $this->_curdir = '/';
                   22682:                         } else {
                   22683:                             $this->_curdir .= '/' . $value['attribs']['name'];
                   22684:                         }
                   22685:                     }
                   22686:                 }
                   22687: 
                   22688:                 if (is_string($value) && $value && ($value{strlen($value) - 1} == "\n")) {
                   22689:                     $value .= str_repeat($this->options['indent'], $this->_tagDepth);
                   22690:                 }
                   22691:                 $tmp .= $this->_createXMLTag(array(
                   22692:                                                     'qname'      => $key,
                   22693:                                                     'attributes' => $atts,
                   22694:                                                     'content'    => $value )
                   22695:                                             );
                   22696:                 if ($this->options['beautifyFilelist'] && $key == 'dir') {
                   22697:                     if (isset($value['attribs'])) {
                   22698:                         $tmp .= ' <!-- ' . $this->_curdir . ' -->';
                   22699:                         if (empty($savedir)) {
                   22700:                             unset($this->_curdir);
                   22701:                         } else {
                   22702:                             $this->_curdir = $savedir;
                   22703:                         }
                   22704:                     }
                   22705:                 }
                   22706:                 $tmp .= $this->options['linebreak'];
                   22707:             }
                   22708: 
                   22709:             $this->_tagDepth--;
                   22710:             if ($this->options['indent']!==null && $this->_tagDepth>0) {
                   22711:                 $tmp .= str_repeat($this->options['indent'], $this->_tagDepth);
                   22712:             }
                   22713: 
                   22714:             if (trim($tmp) === '') {
                   22715:                 $tmp = null;
                   22716:             }
                   22717: 
                   22718:             $tag = array(
                   22719:                 'qname'      => $tagName,
                   22720:                 'content'    => $tmp,
                   22721:                 'attributes' => $attributes
                   22722:             );
                   22723:         }
                   22724:         if ($this->options['typeHints'] === true) {
                   22725:             if (!isset($tag['attributes'][$this->options['typeAttribute']])) {
                   22726:                 $tag['attributes'][$this->options['typeAttribute']] = 'array';
                   22727:             }
                   22728:         }
                   22729: 
                   22730:         $string = $this->_createXMLTag($tag, false);
                   22731:         return $string;
                   22732:     }
                   22733: 
                   22734:    /**
                   22735:     * create a tag from an array
                   22736:     * this method awaits an array in the following format
                   22737:     * array(
                   22738:     *       'qname'        => $tagName,
                   22739:     *       'attributes'   => array(),
                   22740:     *       'content'      => $content,      // optional
                   22741:     *       'namespace'    => $namespace     // optional
                   22742:     *       'namespaceUri' => $namespaceUri  // optional
                   22743:     *   )
                   22744:     *
                   22745:     * @access   private
                   22746:     * @param    array   $tag tag definition
                   22747:     * @param    boolean $replaceEntities whether to replace XML entities in content or not
                   22748:     * @return   string  $string XML tag
                   22749:     */
                   22750:     function _createXMLTag($tag, $replaceEntities = true)
                   22751:     {
                   22752:         if ($this->options['indentAttributes'] !== false) {
                   22753:             $multiline = true;
                   22754:             $indent    = str_repeat($this->options['indent'], $this->_tagDepth);
                   22755: 
                   22756:             if ($this->options['indentAttributes'] == '_auto') {
                   22757:                 $indent .= str_repeat(' ', (strlen($tag['qname'])+2));
                   22758: 
                   22759:             } else {
                   22760:                 $indent .= $this->options['indentAttributes'];
                   22761:             }
                   22762:         } else {
                   22763:             $indent = $multiline = false;
                   22764:         }
                   22765: 
                   22766:         if (is_array($tag['content'])) {
                   22767:             if (empty($tag['content'])) {
                   22768:                 $tag['content'] = '';
                   22769:             }
                   22770:         } elseif(is_scalar($tag['content']) && (string)$tag['content'] == '') {
                   22771:             $tag['content'] = '';
                   22772:         }
                   22773: 
                   22774:         if (is_scalar($tag['content']) || is_null($tag['content'])) {
                   22775:             if ($this->options['encoding'] == 'UTF-8' &&
                   22776:                   version_compare(phpversion(), '5.0.0', 'lt')
                   22777:             ) {
                   22778:                 $tag['content'] = utf8_encode($tag['content']);
                   22779:             }
                   22780: 
                   22781:             if ($replaceEntities === true) {
                   22782:                 $replaceEntities = XML_UTIL_ENTITIES_XML;
                   22783:             }
                   22784: 
                   22785:             $tag = XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $this->options['linebreak']);
                   22786:         } elseif (is_array($tag['content'])) {
                   22787:             $tag = $this->_serializeArray($tag['content'], $tag['qname'], $tag['attributes']);
                   22788:         } elseif (is_object($tag['content'])) {
                   22789:             $tag = $this->_serializeObject($tag['content'], $tag['qname'], $tag['attributes']);
                   22790:         } elseif (is_resource($tag['content'])) {
                   22791:             settype($tag['content'], 'string');
                   22792:             $tag = XML_Util::createTagFromArray($tag, $replaceEntities);
                   22793:         }
                   22794:         return  $tag;
                   22795:     }
1.1.1.2 ! misho    22796: }PEAR-1.9.4/PEAR/PackageFile/Parser/v1.php0000644000076500000240000004031411605156614016413 0ustar  helgistaff<?php
1.1       misho    22797: /**
                   22798:  * package.xml parsing class, package.xml version 1.0
                   22799:  *
                   22800:  * PHP versions 4 and 5
                   22801:  *
                   22802:  * @category   pear
                   22803:  * @package    PEAR
                   22804:  * @author     Greg Beaver <cellog@php.net>
                   22805:  * @copyright  1997-2009 The Authors
                   22806:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   22807:  * @version    CVS: $Id: v1.php 313023 2011-07-06 19:17:11Z dufuz $
                   22808:  * @link       http://pear.php.net/package/PEAR
                   22809:  * @since      File available since Release 1.4.0a1
                   22810:  */
                   22811: /**
                   22812:  * package.xml abstraction class
                   22813:  */
                   22814: require_once 'PEAR/PackageFile/v1.php';
                   22815: /**
                   22816:  * Parser for package.xml version 1.0
                   22817:  * @category   pear
                   22818:  * @package    PEAR
                   22819:  * @author     Greg Beaver <cellog@php.net>
                   22820:  * @copyright  1997-2009 The Authors
                   22821:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   22822:  * @version    Release: @PEAR-VER@
                   22823:  * @link       http://pear.php.net/package/PEAR
                   22824:  * @since      Class available since Release 1.4.0a1
                   22825:  */
                   22826: class PEAR_PackageFile_Parser_v1
                   22827: {
                   22828:     var $_registry;
                   22829:     var $_config;
                   22830:     var $_logger;
                   22831:     /**
                   22832:      * BC hack to allow PEAR_Common::infoFromString() to sort of
                   22833:      * work with the version 2.0 format - there's no filelist though
                   22834:      * @param PEAR_PackageFile_v2
                   22835:      */
                   22836:     function fromV2($packagefile)
                   22837:     {
                   22838:         $info = $packagefile->getArray(true);
                   22839:         $ret = new PEAR_PackageFile_v1;
                   22840:         $ret->fromArray($info['old']);
                   22841:     }
                   22842: 
                   22843:     function setConfig(&$c)
                   22844:     {
                   22845:         $this->_config = &$c;
                   22846:         $this->_registry = &$c->getRegistry();
                   22847:     }
                   22848: 
                   22849:     function setLogger(&$l)
                   22850:     {
                   22851:         $this->_logger = &$l;
                   22852:     }
                   22853: 
                   22854:     /**
                   22855:      * @param string contents of package.xml file, version 1.0
                   22856:      * @return bool success of parsing
                   22857:      */
                   22858:     function &parse($data, $file, $archive = false)
                   22859:     {
                   22860:         if (!extension_loaded('xml')) {
                   22861:             return PEAR::raiseError('Cannot create xml parser for parsing package.xml, no xml extension');
                   22862:         }
                   22863:         $xp = xml_parser_create();
                   22864:         if (!$xp) {
                   22865:             $a = &PEAR::raiseError('Cannot create xml parser for parsing package.xml');
                   22866:             return $a;
                   22867:         }
                   22868:         xml_set_object($xp, $this);
                   22869:         xml_set_element_handler($xp, '_element_start_1_0', '_element_end_1_0');
                   22870:         xml_set_character_data_handler($xp, '_pkginfo_cdata_1_0');
                   22871:         xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, false);
                   22872: 
                   22873:         $this->element_stack = array();
                   22874:         $this->_packageInfo = array('provides' => array());
                   22875:         $this->current_element = false;
                   22876:         unset($this->dir_install);
                   22877:         $this->_packageInfo['filelist'] = array();
                   22878:         $this->filelist =& $this->_packageInfo['filelist'];
                   22879:         $this->dir_names = array();
                   22880:         $this->in_changelog = false;
                   22881:         $this->d_i = 0;
                   22882:         $this->cdata = '';
                   22883:         $this->_isValid = true;
                   22884: 
                   22885:         if (!xml_parse($xp, $data, 1)) {
                   22886:             $code = xml_get_error_code($xp);
                   22887:             $line = xml_get_current_line_number($xp);
                   22888:             xml_parser_free($xp);
                   22889:             $a = &PEAR::raiseError(sprintf("XML error: %s at line %d",
                   22890:                            $str = xml_error_string($code), $line), 2);
                   22891:             return $a;
                   22892:         }
                   22893: 
                   22894:         xml_parser_free($xp);
                   22895: 
                   22896:         $pf = new PEAR_PackageFile_v1;
                   22897:         $pf->setConfig($this->_config);
                   22898:         if (isset($this->_logger)) {
                   22899:             $pf->setLogger($this->_logger);
                   22900:         }
                   22901:         $pf->setPackagefile($file, $archive);
                   22902:         $pf->fromArray($this->_packageInfo);
                   22903:         return $pf;
                   22904:     }
                   22905:     // {{{ _unIndent()
                   22906: 
                   22907:     /**
                   22908:      * Unindent given string
                   22909:      *
                   22910:      * @param string $str The string that has to be unindented.
                   22911:      * @return string
                   22912:      * @access private
                   22913:      */
                   22914:     function _unIndent($str)
                   22915:     {
                   22916:         // remove leading newlines
                   22917:         $str = preg_replace('/^[\r\n]+/', '', $str);
                   22918:         // find whitespace at the beginning of the first line
                   22919:         $indent_len = strspn($str, " \t");
                   22920:         $indent = substr($str, 0, $indent_len);
                   22921:         $data = '';
                   22922:         // remove the same amount of whitespace from following lines
                   22923:         foreach (explode("\n", $str) as $line) {
                   22924:             if (substr($line, 0, $indent_len) == $indent) {
                   22925:                 $data .= substr($line, $indent_len) . "\n";
                   22926:             } elseif (trim(substr($line, 0, $indent_len))) {
                   22927:                 $data .= ltrim($line);
                   22928:             }
                   22929:         }
                   22930:         return $data;
                   22931:     }
                   22932: 
                   22933:     // Support for package DTD v1.0:
                   22934:     // {{{ _element_start_1_0()
                   22935: 
                   22936:     /**
                   22937:      * XML parser callback for ending elements.  Used for version 1.0
                   22938:      * packages.
                   22939:      *
                   22940:      * @param resource  $xp    XML parser resource
                   22941:      * @param string    $name  name of ending element
                   22942:      *
                   22943:      * @return void
                   22944:      *
                   22945:      * @access private
                   22946:      */
                   22947:     function _element_start_1_0($xp, $name, $attribs)
                   22948:     {
                   22949:         array_push($this->element_stack, $name);
                   22950:         $this->current_element = $name;
                   22951:         $spos = sizeof($this->element_stack) - 2;
                   22952:         $this->prev_element = ($spos >= 0) ? $this->element_stack[$spos] : '';
                   22953:         $this->current_attributes = $attribs;
                   22954:         $this->cdata = '';
                   22955:         switch ($name) {
                   22956:             case 'dir':
                   22957:                 if ($this->in_changelog) {
                   22958:                     break;
                   22959:                 }
                   22960:                 if (array_key_exists('name', $attribs) && $attribs['name'] != '/') {
                   22961:                     $attribs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
                   22962:                         $attribs['name']);
                   22963:                     if (strrpos($attribs['name'], '/') === strlen($attribs['name']) - 1) {
                   22964:                         $attribs['name'] = substr($attribs['name'], 0,
                   22965:                             strlen($attribs['name']) - 1);
                   22966:                     }
                   22967:                     if (strpos($attribs['name'], '/') === 0) {
                   22968:                         $attribs['name'] = substr($attribs['name'], 1);
                   22969:                     }
                   22970:                     $this->dir_names[] = $attribs['name'];
                   22971:                 }
                   22972:                 if (isset($attribs['baseinstalldir'])) {
                   22973:                     $this->dir_install = $attribs['baseinstalldir'];
                   22974:                 }
                   22975:                 if (isset($attribs['role'])) {
                   22976:                     $this->dir_role = $attribs['role'];
                   22977:                 }
                   22978:                 break;
                   22979:             case 'file':
                   22980:                 if ($this->in_changelog) {
                   22981:                     break;
                   22982:                 }
                   22983:                 if (isset($attribs['name'])) {
                   22984:                     $path = '';
                   22985:                     if (count($this->dir_names)) {
                   22986:                         foreach ($this->dir_names as $dir) {
                   22987:                             $path .= $dir . '/';
                   22988:                         }
                   22989:                     }
                   22990:                     $path .= preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
                   22991:                         $attribs['name']);
                   22992:                     unset($attribs['name']);
                   22993:                     $this->current_path = $path;
                   22994:                     $this->filelist[$path] = $attribs;
                   22995:                     // Set the baseinstalldir only if the file don't have this attrib
                   22996:                     if (!isset($this->filelist[$path]['baseinstalldir']) &&
                   22997:                         isset($this->dir_install))
                   22998:                     {
                   22999:                         $this->filelist[$path]['baseinstalldir'] = $this->dir_install;
                   23000:                     }
                   23001:                     // Set the Role
                   23002:                     if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) {
                   23003:                         $this->filelist[$path]['role'] = $this->dir_role;
                   23004:                     }
                   23005:                 }
                   23006:                 break;
                   23007:             case 'replace':
                   23008:                 if (!$this->in_changelog) {
                   23009:                     $this->filelist[$this->current_path]['replacements'][] = $attribs;
                   23010:                 }
                   23011:                 break;
                   23012:             case 'maintainers':
                   23013:                 $this->_packageInfo['maintainers'] = array();
                   23014:                 $this->m_i = 0; // maintainers array index
                   23015:                 break;
                   23016:             case 'maintainer':
                   23017:                 // compatibility check
                   23018:                 if (!isset($this->_packageInfo['maintainers'])) {
                   23019:                     $this->_packageInfo['maintainers'] = array();
                   23020:                     $this->m_i = 0;
                   23021:                 }
                   23022:                 $this->_packageInfo['maintainers'][$this->m_i] = array();
                   23023:                 $this->current_maintainer =& $this->_packageInfo['maintainers'][$this->m_i];
                   23024:                 break;
                   23025:             case 'changelog':
                   23026:                 $this->_packageInfo['changelog'] = array();
                   23027:                 $this->c_i = 0; // changelog array index
                   23028:                 $this->in_changelog = true;
                   23029:                 break;
                   23030:             case 'release':
                   23031:                 if ($this->in_changelog) {
                   23032:                     $this->_packageInfo['changelog'][$this->c_i] = array();
                   23033:                     $this->current_release = &$this->_packageInfo['changelog'][$this->c_i];
                   23034:                 } else {
                   23035:                     $this->current_release = &$this->_packageInfo;
                   23036:                 }
                   23037:                 break;
                   23038:             case 'deps':
                   23039:                 if (!$this->in_changelog) {
                   23040:                     $this->_packageInfo['release_deps'] = array();
                   23041:                 }
                   23042:                 break;
                   23043:             case 'dep':
                   23044:                 // dependencies array index
                   23045:                 if (!$this->in_changelog) {
                   23046:                     $this->d_i++;
                   23047:                     isset($attribs['type']) ? ($attribs['type'] = strtolower($attribs['type'])) : false;
                   23048:                     $this->_packageInfo['release_deps'][$this->d_i] = $attribs;
                   23049:                 }
                   23050:                 break;
                   23051:             case 'configureoptions':
                   23052:                 if (!$this->in_changelog) {
                   23053:                     $this->_packageInfo['configure_options'] = array();
                   23054:                 }
                   23055:                 break;
                   23056:             case 'configureoption':
                   23057:                 if (!$this->in_changelog) {
                   23058:                     $this->_packageInfo['configure_options'][] = $attribs;
                   23059:                 }
                   23060:                 break;
                   23061:             case 'provides':
                   23062:                 if (empty($attribs['type']) || empty($attribs['name'])) {
                   23063:                     break;
                   23064:                 }
                   23065:                 $attribs['explicit'] = true;
                   23066:                 $this->_packageInfo['provides']["$attribs[type];$attribs[name]"] = $attribs;
                   23067:                 break;
                   23068:             case 'package' :
                   23069:                 if (isset($attribs['version'])) {
                   23070:                     $this->_packageInfo['xsdversion'] = trim($attribs['version']);
                   23071:                 } else {
                   23072:                     $this->_packageInfo['xsdversion'] = '1.0';
                   23073:                 }
                   23074:                 if (isset($attribs['packagerversion'])) {
                   23075:                     $this->_packageInfo['packagerversion'] = $attribs['packagerversion'];
                   23076:                 }
                   23077:                 break;
                   23078:         }
                   23079:     }
                   23080: 
                   23081:     // }}}
                   23082:     // {{{ _element_end_1_0()
                   23083: 
                   23084:     /**
                   23085:      * XML parser callback for ending elements.  Used for version 1.0
                   23086:      * packages.
                   23087:      *
                   23088:      * @param resource  $xp    XML parser resource
                   23089:      * @param string    $name  name of ending element
                   23090:      *
                   23091:      * @return void
                   23092:      *
                   23093:      * @access private
                   23094:      */
                   23095:     function _element_end_1_0($xp, $name)
                   23096:     {
                   23097:         $data = trim($this->cdata);
                   23098:         switch ($name) {
                   23099:             case 'name':
                   23100:                 switch ($this->prev_element) {
                   23101:                     case 'package':
                   23102:                         $this->_packageInfo['package'] = $data;
                   23103:                         break;
                   23104:                     case 'maintainer':
                   23105:                         $this->current_maintainer['name'] = $data;
                   23106:                         break;
                   23107:                 }
                   23108:                 break;
                   23109:             case 'extends' :
                   23110:                 $this->_packageInfo['extends'] = $data;
                   23111:                 break;
                   23112:             case 'summary':
                   23113:                 $this->_packageInfo['summary'] = $data;
                   23114:                 break;
                   23115:             case 'description':
                   23116:                 $data = $this->_unIndent($this->cdata);
                   23117:                 $this->_packageInfo['description'] = $data;
                   23118:                 break;
                   23119:             case 'user':
                   23120:                 $this->current_maintainer['handle'] = $data;
                   23121:                 break;
                   23122:             case 'email':
                   23123:                 $this->current_maintainer['email'] = $data;
                   23124:                 break;
                   23125:             case 'role':
                   23126:                 $this->current_maintainer['role'] = $data;
                   23127:                 break;
                   23128:             case 'version':
                   23129:                 if ($this->in_changelog) {
                   23130:                     $this->current_release['version'] = $data;
                   23131:                 } else {
                   23132:                     $this->_packageInfo['version'] = $data;
                   23133:                 }
                   23134:                 break;
                   23135:             case 'date':
                   23136:                 if ($this->in_changelog) {
                   23137:                     $this->current_release['release_date'] = $data;
                   23138:                 } else {
                   23139:                     $this->_packageInfo['release_date'] = $data;
                   23140:                 }
                   23141:                 break;
                   23142:             case 'notes':
                   23143:                 // try to "de-indent" release notes in case someone
                   23144:                 // has been over-indenting their xml ;-)
                   23145:                 // Trim only on the right side
                   23146:                 $data = rtrim($this->_unIndent($this->cdata));
                   23147:                 if ($this->in_changelog) {
                   23148:                     $this->current_release['release_notes'] = $data;
                   23149:                 } else {
                   23150:                     $this->_packageInfo['release_notes'] = $data;
                   23151:                 }
                   23152:                 break;
                   23153:             case 'warnings':
                   23154:                 if ($this->in_changelog) {
                   23155:                     $this->current_release['release_warnings'] = $data;
                   23156:                 } else {
                   23157:                     $this->_packageInfo['release_warnings'] = $data;
                   23158:                 }
                   23159:                 break;
                   23160:             case 'state':
                   23161:                 if ($this->in_changelog) {
                   23162:                     $this->current_release['release_state'] = $data;
                   23163:                 } else {
                   23164:                     $this->_packageInfo['release_state'] = $data;
                   23165:                 }
                   23166:                 break;
                   23167:             case 'license':
                   23168:                 if ($this->in_changelog) {
                   23169:                     $this->current_release['release_license'] = $data;
                   23170:                 } else {
                   23171:                     $this->_packageInfo['release_license'] = $data;
                   23172:                 }
                   23173:                 break;
                   23174:             case 'dep':
                   23175:                 if ($data && !$this->in_changelog) {
                   23176:                     $this->_packageInfo['release_deps'][$this->d_i]['name'] = $data;
                   23177:                 }
                   23178:                 break;
                   23179:             case 'dir':
                   23180:                 if ($this->in_changelog) {
                   23181:                     break;
                   23182:                 }
                   23183:                 array_pop($this->dir_names);
                   23184:                 break;
                   23185:             case 'file':
                   23186:                 if ($this->in_changelog) {
                   23187:                     break;
                   23188:                 }
                   23189:                 if ($data) {
                   23190:                     $path = '';
                   23191:                     if (count($this->dir_names)) {
                   23192:                         foreach ($this->dir_names as $dir) {
                   23193:                             $path .= $dir . '/';
                   23194:                         }
                   23195:                     }
                   23196:                     $path .= $data;
                   23197:                     $this->filelist[$path] = $this->current_attributes;
                   23198:                     // Set the baseinstalldir only if the file don't have this attrib
                   23199:                     if (!isset($this->filelist[$path]['baseinstalldir']) &&
                   23200:                         isset($this->dir_install))
                   23201:                     {
                   23202:                         $this->filelist[$path]['baseinstalldir'] = $this->dir_install;
                   23203:                     }
                   23204:                     // Set the Role
                   23205:                     if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) {
                   23206:                         $this->filelist[$path]['role'] = $this->dir_role;
                   23207:                     }
                   23208:                 }
                   23209:                 break;
                   23210:             case 'maintainer':
                   23211:                 if (empty($this->_packageInfo['maintainers'][$this->m_i]['role'])) {
                   23212:                     $this->_packageInfo['maintainers'][$this->m_i]['role'] = 'lead';
                   23213:                 }
                   23214:                 $this->m_i++;
                   23215:                 break;
                   23216:             case 'release':
                   23217:                 if ($this->in_changelog) {
                   23218:                     $this->c_i++;
                   23219:                 }
                   23220:                 break;
                   23221:             case 'changelog':
                   23222:                 $this->in_changelog = false;
                   23223:                 break;
                   23224:         }
                   23225:         array_pop($this->element_stack);
                   23226:         $spos = sizeof($this->element_stack) - 1;
                   23227:         $this->current_element = ($spos > 0) ? $this->element_stack[$spos] : '';
                   23228:         $this->cdata = '';
                   23229:     }
                   23230: 
                   23231:     // }}}
                   23232:     // {{{ _pkginfo_cdata_1_0()
                   23233: 
                   23234:     /**
                   23235:      * XML parser callback for character data.  Used for version 1.0
                   23236:      * packages.
                   23237:      *
                   23238:      * @param resource  $xp    XML parser resource
                   23239:      * @param string    $name  character data
                   23240:      *
                   23241:      * @return void
                   23242:      *
                   23243:      * @access private
                   23244:      */
                   23245:     function _pkginfo_cdata_1_0($xp, $data)
                   23246:     {
                   23247:         if (isset($this->cdata)) {
                   23248:             $this->cdata .= $data;
                   23249:         }
                   23250:     }
                   23251: 
                   23252:     // }}}
                   23253: }
1.1.1.2 ! misho    23254: ?>PEAR-1.9.4/PEAR/PackageFile/Parser/v2.php0000644000076500000240000000621511605156614016416 0ustar  helgistaff<?php
1.1       misho    23255: /**
                   23256:  * package.xml parsing class, package.xml version 2.0
                   23257:  *
                   23258:  * PHP versions 4 and 5
                   23259:  *
                   23260:  * @category   pear
                   23261:  * @package    PEAR
                   23262:  * @author     Greg Beaver <cellog@php.net>
                   23263:  * @copyright  1997-2009 The Authors
                   23264:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   23265:  * @version    CVS: $Id: v2.php 313023 2011-07-06 19:17:11Z dufuz $
                   23266:  * @link       http://pear.php.net/package/PEAR
                   23267:  * @since      File available since Release 1.4.0a1
                   23268:  */
                   23269: /**
                   23270:  * base xml parser class
                   23271:  */
                   23272: require_once 'PEAR/XMLParser.php';
                   23273: require_once 'PEAR/PackageFile/v2.php';
                   23274: /**
                   23275:  * Parser for package.xml version 2.0
                   23276:  * @category   pear
                   23277:  * @package    PEAR
                   23278:  * @author     Greg Beaver <cellog@php.net>
                   23279:  * @copyright  1997-2009 The Authors
                   23280:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   23281:  * @version    Release: @PEAR-VER@
                   23282:  * @link       http://pear.php.net/package/PEAR
                   23283:  * @since      Class available since Release 1.4.0a1
                   23284:  */
                   23285: class PEAR_PackageFile_Parser_v2 extends PEAR_XMLParser
                   23286: {
                   23287:     var $_config;
                   23288:     var $_logger;
                   23289:     var $_registry;
                   23290: 
                   23291:     function setConfig(&$c)
                   23292:     {
                   23293:         $this->_config = &$c;
                   23294:         $this->_registry = &$c->getRegistry();
                   23295:     }
                   23296: 
                   23297:     function setLogger(&$l)
                   23298:     {
                   23299:         $this->_logger = &$l;
                   23300:     }
                   23301:     /**
                   23302:      * Unindent given string
                   23303:      *
                   23304:      * @param string $str The string that has to be unindented.
                   23305:      * @return string
                   23306:      * @access private
                   23307:      */
                   23308:     function _unIndent($str)
                   23309:     {
                   23310:         // remove leading newlines
                   23311:         $str = preg_replace('/^[\r\n]+/', '', $str);
                   23312:         // find whitespace at the beginning of the first line
                   23313:         $indent_len = strspn($str, " \t");
                   23314:         $indent = substr($str, 0, $indent_len);
                   23315:         $data = '';
                   23316:         // remove the same amount of whitespace from following lines
                   23317:         foreach (explode("\n", $str) as $line) {
                   23318:             if (substr($line, 0, $indent_len) == $indent) {
                   23319:                 $data .= substr($line, $indent_len) . "\n";
                   23320:             } else {
                   23321:                 $data .= $line . "\n";
                   23322:             }
                   23323:         }
                   23324:         return $data;
                   23325:     }
                   23326: 
                   23327:     /**
                   23328:      * post-process data
                   23329:      *
                   23330:      * @param string $data
                   23331:      * @param string $element element name
                   23332:      */
                   23333:     function postProcess($data, $element)
                   23334:     {
                   23335:         if ($element == 'notes') {
                   23336:             return trim($this->_unIndent($data));
                   23337:         }
                   23338:         return trim($data);
                   23339:     }
                   23340: 
                   23341:     /**
                   23342:      * @param string
                   23343:      * @param string file name of the package.xml
                   23344:      * @param string|false name of the archive this package.xml came from, if any
                   23345:      * @param string class name to instantiate and return.  This must be PEAR_PackageFile_v2 or
                   23346:      *               a subclass
                   23347:      * @return PEAR_PackageFile_v2
                   23348:      */
                   23349:     function &parse($data, $file, $archive = false, $class = 'PEAR_PackageFile_v2')
                   23350:     {
                   23351:         if (PEAR::isError($err = parent::parse($data, $file))) {
                   23352:             return $err;
                   23353:         }
                   23354: 
                   23355:         $ret = new $class;
                   23356:         $ret->encoding = $this->encoding;
                   23357:         $ret->setConfig($this->_config);
                   23358:         if (isset($this->_logger)) {
                   23359:             $ret->setLogger($this->_logger);
                   23360:         }
                   23361: 
                   23362:         $ret->fromArray($this->_unserializedData);
                   23363:         $ret->setPackagefile($file, $archive);
                   23364:         return $ret;
                   23365:     }
1.1.1.2 ! misho    23366: }PEAR-1.9.4/PEAR/PackageFile/v2/rw.php0000644000076500000240000017321011605156614015612 0ustar  helgistaff<?php
1.1       misho    23367: /**
                   23368:  * PEAR_PackageFile_v2, package.xml version 2.0, read/write version
                   23369:  *
                   23370:  * PHP versions 4 and 5
                   23371:  *
                   23372:  * @category   pear
                   23373:  * @package    PEAR
                   23374:  * @author     Greg Beaver <cellog@php.net>
                   23375:  * @copyright  1997-2009 The Authors
                   23376:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   23377:  * @version    CVS: $Id: rw.php 313023 2011-07-06 19:17:11Z dufuz $
                   23378:  * @link       http://pear.php.net/package/PEAR
                   23379:  * @since      File available since Release 1.4.0a8
                   23380:  */
                   23381: /**
                   23382:  * For base class
                   23383:  */
                   23384: require_once 'PEAR/PackageFile/v2.php';
                   23385: /**
                   23386:  * @category   pear
                   23387:  * @package    PEAR
                   23388:  * @author     Greg Beaver <cellog@php.net>
                   23389:  * @copyright  1997-2009 The Authors
                   23390:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   23391:  * @version    Release: 1.9.4
                   23392:  * @link       http://pear.php.net/package/PEAR
                   23393:  * @since      Class available since Release 1.4.0a8
                   23394:  */
                   23395: class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
                   23396: {
                   23397:     /**
                   23398:      * @param string Extension name
                   23399:      * @return bool success of operation
                   23400:      */
                   23401:     function setProvidesExtension($extension)
                   23402:     {
                   23403:         if (in_array($this->getPackageType(),
                   23404:               array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
                   23405:             if (!isset($this->_packageInfo['providesextension'])) {
                   23406:                 // ensure that the channel tag is set up in the right location
                   23407:                 $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   23408:                     array('usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease',
                   23409:                     'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23410:                     'bundle', 'changelog'),
                   23411:                     $extension, 'providesextension');
                   23412:             }
                   23413:             $this->_packageInfo['providesextension'] = $extension;
                   23414:             return true;
                   23415:         }
                   23416:         return false;
                   23417:     }
                   23418: 
                   23419:     function setPackage($package)
                   23420:     {
                   23421:         $this->_isValid = 0;
                   23422:         if (!isset($this->_packageInfo['attribs'])) {
                   23423:             $this->_packageInfo = array_merge(array('attribs' => array(
                   23424:                                  'version' => '2.0',
                   23425:                                  'xmlns' => 'http://pear.php.net/dtd/package-2.0',
                   23426:                                  'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
                   23427:                                  'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
                   23428:                                  'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
                   23429:     http://pear.php.net/dtd/tasks-1.0.xsd
                   23430:     http://pear.php.net/dtd/package-2.0
                   23431:     http://pear.php.net/dtd/package-2.0.xsd',
                   23432:                              )), $this->_packageInfo);
                   23433:         }
                   23434:         if (!isset($this->_packageInfo['name'])) {
                   23435:             return $this->_packageInfo = array_merge(array('name' => $package),
                   23436:                 $this->_packageInfo);
                   23437:         }
                   23438:         $this->_packageInfo['name'] = $package;
                   23439:     }
                   23440: 
                   23441:     /**
                   23442:      * set this as a package.xml version 2.1
                   23443:      * @access private
                   23444:      */
                   23445:     function _setPackageVersion2_1()
                   23446:     {
                   23447:         $info = array(
                   23448:                                  'version' => '2.1',
                   23449:                                  'xmlns' => 'http://pear.php.net/dtd/package-2.1',
                   23450:                                  'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
                   23451:                                  'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
                   23452:                                  'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
                   23453:     http://pear.php.net/dtd/tasks-1.0.xsd
                   23454:     http://pear.php.net/dtd/package-2.1
                   23455:     http://pear.php.net/dtd/package-2.1.xsd',
                   23456:                              );
                   23457:         if (!isset($this->_packageInfo['attribs'])) {
                   23458:             $this->_packageInfo = array_merge(array('attribs' => $info), $this->_packageInfo);
                   23459:         } else {
                   23460:             $this->_packageInfo['attribs'] = $info;
                   23461:         }
                   23462:     }
                   23463: 
                   23464:     function setUri($uri)
                   23465:     {
                   23466:         unset($this->_packageInfo['channel']);
                   23467:         $this->_isValid = 0;
                   23468:         if (!isset($this->_packageInfo['uri'])) {
                   23469:             // ensure that the uri tag is set up in the right location
                   23470:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   23471:                 array('extends', 'summary', 'description', 'lead',
                   23472:                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
                   23473:                 'stability', 'license', 'notes', 'contents', 'compatible',
                   23474:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23475:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23476:                 'extbinrelease', 'bundle', 'changelog'), $uri, 'uri');
                   23477:         }
                   23478:         $this->_packageInfo['uri'] = $uri;
                   23479:     }
                   23480: 
                   23481:     function setChannel($channel)
                   23482:     {
                   23483:         unset($this->_packageInfo['uri']);
                   23484:         $this->_isValid = 0;
                   23485:         if (!isset($this->_packageInfo['channel'])) {
                   23486:             // ensure that the channel tag is set up in the right location
                   23487:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   23488:                 array('extends', 'summary', 'description', 'lead',
                   23489:                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
                   23490:                 'stability', 'license', 'notes', 'contents', 'compatible',
                   23491:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23492:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23493:                 'extbinrelease', 'bundle', 'changelog'), $channel, 'channel');
                   23494:         }
                   23495:         $this->_packageInfo['channel'] = $channel;
                   23496:     }
                   23497: 
                   23498:     function setExtends($extends)
                   23499:     {
                   23500:         $this->_isValid = 0;
                   23501:         if (!isset($this->_packageInfo['extends'])) {
                   23502:             // ensure that the extends tag is set up in the right location
                   23503:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   23504:                 array('summary', 'description', 'lead',
                   23505:                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
                   23506:                 'stability', 'license', 'notes', 'contents', 'compatible',
                   23507:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23508:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23509:                 'extbinrelease', 'bundle', 'changelog'), $extends, 'extends');
                   23510:         }
                   23511:         $this->_packageInfo['extends'] = $extends;
                   23512:     }
                   23513: 
                   23514:     function setSummary($summary)
                   23515:     {
                   23516:         $this->_isValid = 0;
                   23517:         if (!isset($this->_packageInfo['summary'])) {
                   23518:             // ensure that the summary tag is set up in the right location
                   23519:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   23520:                 array('description', 'lead',
                   23521:                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
                   23522:                 'stability', 'license', 'notes', 'contents', 'compatible',
                   23523:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23524:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23525:                 'extbinrelease', 'bundle', 'changelog'), $summary, 'summary');
                   23526:         }
                   23527:         $this->_packageInfo['summary'] = $summary;
                   23528:     }
                   23529: 
                   23530:     function setDescription($desc)
                   23531:     {
                   23532:         $this->_isValid = 0;
                   23533:         if (!isset($this->_packageInfo['description'])) {
                   23534:             // ensure that the description tag is set up in the right location
                   23535:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   23536:                 array('lead',
                   23537:                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
                   23538:                 'stability', 'license', 'notes', 'contents', 'compatible',
                   23539:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23540:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23541:                 'extbinrelease', 'bundle', 'changelog'), $desc, 'description');
                   23542:         }
                   23543:         $this->_packageInfo['description'] = $desc;
                   23544:     }
                   23545: 
                   23546:     /**
                   23547:      * Adds a new maintainer - no checking of duplicates is performed, use
                   23548:      * updatemaintainer for that purpose.
                   23549:      */
                   23550:     function addMaintainer($role, $handle, $name, $email, $active = 'yes')
                   23551:     {
                   23552:         if (!in_array($role, array('lead', 'developer', 'contributor', 'helper'))) {
                   23553:             return false;
                   23554:         }
                   23555:         if (isset($this->_packageInfo[$role])) {
                   23556:             if (!isset($this->_packageInfo[$role][0])) {
                   23557:                 $this->_packageInfo[$role] = array($this->_packageInfo[$role]);
                   23558:             }
                   23559:             $this->_packageInfo[$role][] =
                   23560:                 array(
                   23561:                     'name' => $name,
                   23562:                     'user' => $handle,
                   23563:                     'email' => $email,
                   23564:                     'active' => $active,
                   23565:                 );
                   23566:         } else {
                   23567:             $testarr = array('lead',
                   23568:                     'developer', 'contributor', 'helper', 'date', 'time', 'version',
                   23569:                     'stability', 'license', 'notes', 'contents', 'compatible',
                   23570:                     'dependencies', 'providesextension', 'usesrole', 'usestask',
                   23571:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
                   23572:                     'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog');
                   23573:             foreach (array('lead', 'developer', 'contributor', 'helper') as $testrole) {
                   23574:                 array_shift($testarr);
                   23575:                 if ($role == $testrole) {
                   23576:                     break;
                   23577:                 }
                   23578:             }
                   23579:             if (!isset($this->_packageInfo[$role])) {
                   23580:                 // ensure that the extends tag is set up in the right location
                   23581:                 $this->_packageInfo = $this->_insertBefore($this->_packageInfo, $testarr,
                   23582:                     array(), $role);
                   23583:             }
                   23584:             $this->_packageInfo[$role] =
                   23585:                 array(
                   23586:                     'name' => $name,
                   23587:                     'user' => $handle,
                   23588:                     'email' => $email,
                   23589:                     'active' => $active,
                   23590:                 );
                   23591:         }
                   23592:         $this->_isValid = 0;
                   23593:     }
                   23594: 
                   23595:     function updateMaintainer($newrole, $handle, $name, $email, $active = 'yes')
                   23596:     {
                   23597:         $found = false;
                   23598:         foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
                   23599:             if (!isset($this->_packageInfo[$role])) {
                   23600:                 continue;
                   23601:             }
                   23602:             $info = $this->_packageInfo[$role];
                   23603:             if (!isset($info[0])) {
                   23604:                 if ($info['user'] == $handle) {
                   23605:                     $found = true;
                   23606:                     break;
                   23607:                 }
                   23608:             }
                   23609:             foreach ($info as $i => $maintainer) {
                   23610:                 if ($maintainer['user'] == $handle) {
                   23611:                     $found = $i;
                   23612:                     break 2;
                   23613:                 }
                   23614:             }
                   23615:         }
                   23616:         if ($found === false) {
                   23617:             return $this->addMaintainer($newrole, $handle, $name, $email, $active);
                   23618:         }
                   23619:         if ($found !== false) {
                   23620:             if ($found === true) {
                   23621:                 unset($this->_packageInfo[$role]);
                   23622:             } else {
                   23623:                 unset($this->_packageInfo[$role][$found]);
                   23624:                 $this->_packageInfo[$role] = array_values($this->_packageInfo[$role]);
                   23625:             }
                   23626:         }
                   23627:         $this->addMaintainer($newrole, $handle, $name, $email, $active);
                   23628:         $this->_isValid = 0;
                   23629:     }
                   23630: 
                   23631:     function deleteMaintainer($handle)
                   23632:     {
                   23633:         $found = false;
                   23634:         foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
                   23635:             if (!isset($this->_packageInfo[$role])) {
                   23636:                 continue;
                   23637:             }
                   23638:             if (!isset($this->_packageInfo[$role][0])) {
                   23639:                 $this->_packageInfo[$role] = array($this->_packageInfo[$role]);
                   23640:             }
                   23641:             foreach ($this->_packageInfo[$role] as $i => $maintainer) {
                   23642:                 if ($maintainer['user'] == $handle) {
                   23643:                     $found = $i;
                   23644:                     break;
                   23645:                 }
                   23646:             }
                   23647:             if ($found !== false) {
                   23648:                 unset($this->_packageInfo[$role][$found]);
                   23649:                 if (!count($this->_packageInfo[$role]) && $role == 'lead') {
                   23650:                     $this->_isValid = 0;
                   23651:                 }
                   23652:                 if (!count($this->_packageInfo[$role])) {
                   23653:                     unset($this->_packageInfo[$role]);
                   23654:                     return true;
                   23655:                 }
                   23656:                 $this->_packageInfo[$role] =
                   23657:                     array_values($this->_packageInfo[$role]);
                   23658:                 if (count($this->_packageInfo[$role]) == 1) {
                   23659:                     $this->_packageInfo[$role] = $this->_packageInfo[$role][0];
                   23660:                 }
                   23661:                 return true;
                   23662:             }
                   23663:             if (count($this->_packageInfo[$role]) == 1) {
                   23664:                 $this->_packageInfo[$role] = $this->_packageInfo[$role][0];
                   23665:             }
                   23666:         }
                   23667:         return false;
                   23668:     }
                   23669: 
                   23670:     function setReleaseVersion($version)
                   23671:     {
                   23672:         if (isset($this->_packageInfo['version']) &&
                   23673:               isset($this->_packageInfo['version']['release'])) {
                   23674:             unset($this->_packageInfo['version']['release']);
                   23675:         }
                   23676:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array(
                   23677:             'version' => array('stability', 'license', 'notes', 'contents', 'compatible',
                   23678:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23679:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23680:                 'extbinrelease', 'bundle', 'changelog'),
                   23681:             'release' => array('api')));
                   23682:         $this->_isValid = 0;
                   23683:     }
                   23684: 
                   23685:     function setAPIVersion($version)
                   23686:     {
                   23687:         if (isset($this->_packageInfo['version']) &&
                   23688:               isset($this->_packageInfo['version']['api'])) {
                   23689:             unset($this->_packageInfo['version']['api']);
                   23690:         }
                   23691:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array(
                   23692:             'version' => array('stability', 'license', 'notes', 'contents', 'compatible',
                   23693:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23694:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23695:                 'extbinrelease', 'bundle', 'changelog'),
                   23696:             'api' => array()));
                   23697:         $this->_isValid = 0;
                   23698:     }
                   23699: 
                   23700:     /**
                   23701:      * snapshot|devel|alpha|beta|stable
                   23702:      */
                   23703:     function setReleaseStability($state)
                   23704:     {
                   23705:         if (isset($this->_packageInfo['stability']) &&
                   23706:               isset($this->_packageInfo['stability']['release'])) {
                   23707:             unset($this->_packageInfo['stability']['release']);
                   23708:         }
                   23709:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array(
                   23710:             'stability' => array('license', 'notes', 'contents', 'compatible',
                   23711:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23712:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23713:                 'extbinrelease', 'bundle', 'changelog'),
                   23714:             'release' => array('api')));
                   23715:         $this->_isValid = 0;
                   23716:     }
                   23717: 
                   23718:     /**
                   23719:      * @param devel|alpha|beta|stable
                   23720:      */
                   23721:     function setAPIStability($state)
                   23722:     {
                   23723:         if (isset($this->_packageInfo['stability']) &&
                   23724:               isset($this->_packageInfo['stability']['api'])) {
                   23725:             unset($this->_packageInfo['stability']['api']);
                   23726:         }
                   23727:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array(
                   23728:             'stability' => array('license', 'notes', 'contents', 'compatible',
                   23729:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23730:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23731:                 'extbinrelease', 'bundle', 'changelog'),
                   23732:             'api' => array()));
                   23733:         $this->_isValid = 0;
                   23734:     }
                   23735: 
                   23736:     function setLicense($license, $uri = false, $filesource = false)
                   23737:     {
                   23738:         if (!isset($this->_packageInfo['license'])) {
                   23739:             // ensure that the license tag is set up in the right location
                   23740:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   23741:                 array('notes', 'contents', 'compatible',
                   23742:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23743:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23744:                 'extbinrelease', 'bundle', 'changelog'), 0, 'license');
                   23745:         }
                   23746:         if ($uri || $filesource) {
                   23747:             $attribs = array();
                   23748:             if ($uri) {
                   23749:                 $attribs['uri'] = $uri;
                   23750:             }
                   23751:             $uri = true; // for test below
                   23752:             if ($filesource) {
                   23753:                 $attribs['filesource'] = $filesource;
                   23754:             }
                   23755:         }
                   23756:         $license = $uri ? array('attribs' => $attribs, '_content' => $license) : $license;
                   23757:         $this->_packageInfo['license'] = $license;
                   23758:         $this->_isValid = 0;
                   23759:     }
                   23760: 
                   23761:     function setNotes($notes)
                   23762:     {
                   23763:         $this->_isValid = 0;
                   23764:         if (!isset($this->_packageInfo['notes'])) {
                   23765:             // ensure that the notes tag is set up in the right location
                   23766:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   23767:                 array('contents', 'compatible',
                   23768:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
                   23769:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23770:                 'extbinrelease', 'bundle', 'changelog'), $notes, 'notes');
                   23771:         }
                   23772:         $this->_packageInfo['notes'] = $notes;
                   23773:     }
                   23774: 
                   23775:     /**
                   23776:      * This is only used at install-time, after all serialization
                   23777:      * is over.
                   23778:      * @param string file name
                   23779:      * @param string installed path
                   23780:      */
                   23781:     function setInstalledAs($file, $path)
                   23782:     {
                   23783:         if ($path) {
                   23784:             return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
                   23785:         }
                   23786:         unset($this->_packageInfo['filelist'][$file]['installed_as']);
                   23787:     }
                   23788: 
                   23789:     /**
                   23790:      * This is only used at install-time, after all serialization
                   23791:      * is over.
                   23792:      */
                   23793:     function installedFile($file, $atts)
                   23794:     {
                   23795:         if (isset($this->_packageInfo['filelist'][$file])) {
                   23796:             $this->_packageInfo['filelist'][$file] =
                   23797:                 array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']);
                   23798:         } else {
                   23799:             $this->_packageInfo['filelist'][$file] = $atts['attribs'];
                   23800:         }
                   23801:     }
                   23802: 
                   23803:     /**
                   23804:      * Reset the listing of package contents
                   23805:      * @param string base installation dir for the whole package, if any
                   23806:      */
                   23807:     function clearContents($baseinstall = false)
                   23808:     {
                   23809:         $this->_filesValid = false;
                   23810:         $this->_isValid = 0;
                   23811:         if (!isset($this->_packageInfo['contents'])) {
                   23812:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   23813:                 array('compatible',
                   23814:                     'dependencies', 'providesextension', 'usesrole', 'usestask',
                   23815:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
                   23816:                     'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23817:                     'bundle', 'changelog'), array(), 'contents');
                   23818:         }
                   23819:         if ($this->getPackageType() != 'bundle') {
                   23820:             $this->_packageInfo['contents'] =
                   23821:                 array('dir' => array('attribs' => array('name' => '/')));
                   23822:             if ($baseinstall) {
                   23823:                 $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'] = $baseinstall;
                   23824:             }
                   23825:         } else {
                   23826:             $this->_packageInfo['contents'] = array('bundledpackage' => array());
                   23827:         }
                   23828:     }
                   23829: 
                   23830:     /**
                   23831:      * @param string relative path of the bundled package.
                   23832:      */
                   23833:     function addBundledPackage($path)
                   23834:     {
                   23835:         if ($this->getPackageType() != 'bundle') {
                   23836:             return false;
                   23837:         }
                   23838:         $this->_filesValid = false;
                   23839:         $this->_isValid = 0;
                   23840:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $path, array(
                   23841:                 'contents' => array('compatible', 'dependencies', 'providesextension',
                   23842:                 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease',
                   23843:                 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23844:                 'bundle', 'changelog'),
                   23845:                 'bundledpackage' => array()));
                   23846:     }
                   23847: 
                   23848:     /**
                   23849:      * @param string file name
                   23850:      * @param PEAR_Task_Common a read/write task
                   23851:      */
                   23852:     function addTaskToFile($filename, $task)
                   23853:     {
                   23854:         if (!method_exists($task, 'getXml')) {
                   23855:             return false;
                   23856:         }
                   23857:         if (!method_exists($task, 'getName')) {
                   23858:             return false;
                   23859:         }
                   23860:         if (!method_exists($task, 'validate')) {
                   23861:             return false;
                   23862:         }
                   23863:         if (!$task->validate()) {
                   23864:             return false;
                   23865:         }
                   23866:         if (!isset($this->_packageInfo['contents']['dir']['file'])) {
                   23867:             return false;
                   23868:         }
                   23869:         $this->getTasksNs(); // discover the tasks namespace if not done already
                   23870:         $files = $this->_packageInfo['contents']['dir']['file'];
                   23871:         if (!isset($files[0])) {
                   23872:             $files = array($files);
                   23873:             $ind = false;
                   23874:         } else {
                   23875:             $ind = true;
                   23876:         }
                   23877:         foreach ($files as $i => $file) {
                   23878:             if (isset($file['attribs'])) {
                   23879:                 if ($file['attribs']['name'] == $filename) {
                   23880:                     if ($ind) {
                   23881:                         $t = isset($this->_packageInfo['contents']['dir']['file'][$i]
                   23882:                               ['attribs'][$this->_tasksNs .
                   23883:                               ':' . $task->getName()]) ?
                   23884:                               $this->_packageInfo['contents']['dir']['file'][$i]
                   23885:                               ['attribs'][$this->_tasksNs .
                   23886:                               ':' . $task->getName()] : false;
                   23887:                         if ($t && !isset($t[0])) {
                   23888:                             $this->_packageInfo['contents']['dir']['file'][$i]
                   23889:                                 [$this->_tasksNs . ':' . $task->getName()] = array($t);
                   23890:                         }
                   23891:                         $this->_packageInfo['contents']['dir']['file'][$i][$this->_tasksNs .
                   23892:                             ':' . $task->getName()][] = $task->getXml();
                   23893:                     } else {
                   23894:                         $t = isset($this->_packageInfo['contents']['dir']['file']
                   23895:                               ['attribs'][$this->_tasksNs .
                   23896:                               ':' . $task->getName()]) ? $this->_packageInfo['contents']['dir']['file']
                   23897:                               ['attribs'][$this->_tasksNs .
                   23898:                               ':' . $task->getName()] : false;
                   23899:                         if ($t && !isset($t[0])) {
                   23900:                             $this->_packageInfo['contents']['dir']['file']
                   23901:                                 [$this->_tasksNs . ':' . $task->getName()] = array($t);
                   23902:                         }
                   23903:                         $this->_packageInfo['contents']['dir']['file'][$this->_tasksNs .
                   23904:                             ':' . $task->getName()][] = $task->getXml();
                   23905:                     }
                   23906:                     return true;
                   23907:                 }
                   23908:             }
                   23909:         }
                   23910:         return false;
                   23911:     }
                   23912: 
                   23913:     /**
                   23914:      * @param string path to the file
                   23915:      * @param string filename
                   23916:      * @param array extra attributes
                   23917:      */
                   23918:     function addFile($dir, $file, $attrs)
                   23919:     {
                   23920:         if ($this->getPackageType() == 'bundle') {
                   23921:             return false;
                   23922:         }
                   23923:         $this->_filesValid = false;
                   23924:         $this->_isValid = 0;
                   23925:         $dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir);
                   23926:         if ($dir == '/' || $dir == '') {
                   23927:             $dir = '';
                   23928:         } else {
                   23929:             $dir .= '/';
                   23930:         }
                   23931:         $attrs['name'] = $dir . $file;
                   23932:         if (!isset($this->_packageInfo['contents'])) {
                   23933:             // ensure that the contents tag is set up
                   23934:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   23935:                 array('compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask',
                   23936:                 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
                   23937:                 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   23938:                 'bundle', 'changelog'), array(), 'contents');
                   23939:         }
                   23940:         if (isset($this->_packageInfo['contents']['dir']['file'])) {
                   23941:             if (!isset($this->_packageInfo['contents']['dir']['file'][0])) {
                   23942:                 $this->_packageInfo['contents']['dir']['file'] =
                   23943:                     array($this->_packageInfo['contents']['dir']['file']);
                   23944:             }
                   23945:             $this->_packageInfo['contents']['dir']['file'][]['attribs'] = $attrs;
                   23946:         } else {
                   23947:             $this->_packageInfo['contents']['dir']['file']['attribs'] = $attrs;
                   23948:         }
                   23949:     }
                   23950: 
                   23951:     /**
                   23952:      * @param string Dependent package name
                   23953:      * @param string Dependent package's channel name
                   23954:      * @param string minimum version of specified package that this release is guaranteed to be
                   23955:      *               compatible with
                   23956:      * @param string maximum version of specified package that this release is guaranteed to be
                   23957:      *               compatible with
                   23958:      * @param string versions of specified package that this release is not compatible with
                   23959:      */
                   23960:     function addCompatiblePackage($name, $channel, $min, $max, $exclude = false)
                   23961:     {
                   23962:         $this->_isValid = 0;
                   23963:         $set = array(
                   23964:             'name' => $name,
                   23965:             'channel' => $channel,
                   23966:             'min' => $min,
                   23967:             'max' => $max,
                   23968:         );
                   23969:         if ($exclude) {
                   23970:             $set['exclude'] = $exclude;
                   23971:         }
                   23972:         $this->_isValid = 0;
                   23973:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
                   23974:                 'compatible' => array('dependencies', 'providesextension', 'usesrole', 'usestask',
                   23975:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   23976:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
                   23977:             ));
                   23978:     }
                   23979: 
                   23980:     /**
                   23981:      * Removes the <usesrole> tag entirely
                   23982:      */
                   23983:     function resetUsesrole()
                   23984:     {
                   23985:         if (isset($this->_packageInfo['usesrole'])) {
                   23986:             unset($this->_packageInfo['usesrole']);
                   23987:         }
                   23988:     }
                   23989: 
                   23990:     /**
                   23991:      * @param string
                   23992:      * @param string package name or uri
                   23993:      * @param string channel name if non-uri
                   23994:      */
                   23995:     function addUsesrole($role, $packageOrUri, $channel = false) {
                   23996:         $set = array('role' => $role);
                   23997:         if ($channel) {
                   23998:             $set['package'] = $packageOrUri;
                   23999:             $set['channel'] = $channel;
                   24000:         } else {
                   24001:             $set['uri'] = $packageOrUri;
                   24002:         }
                   24003:         $this->_isValid = 0;
                   24004:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
                   24005:                 'usesrole' => array('usestask', 'srcpackage', 'srcuri',
                   24006:                     'phprelease', 'extsrcrelease', 'extbinrelease',
                   24007:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
                   24008:             ));
                   24009:     }
                   24010: 
                   24011:     /**
                   24012:      * Removes the <usestask> tag entirely
                   24013:      */
                   24014:     function resetUsestask()
                   24015:     {
                   24016:         if (isset($this->_packageInfo['usestask'])) {
                   24017:             unset($this->_packageInfo['usestask']);
                   24018:         }
                   24019:     }
                   24020: 
                   24021: 
                   24022:     /**
                   24023:      * @param string
                   24024:      * @param string package name or uri
                   24025:      * @param string channel name if non-uri
                   24026:      */
                   24027:     function addUsestask($task, $packageOrUri, $channel = false) {
                   24028:         $set = array('task' => $task);
                   24029:         if ($channel) {
                   24030:             $set['package'] = $packageOrUri;
                   24031:             $set['channel'] = $channel;
                   24032:         } else {
                   24033:             $set['uri'] = $packageOrUri;
                   24034:         }
                   24035:         $this->_isValid = 0;
                   24036:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
                   24037:                 'usestask' => array('srcpackage', 'srcuri',
                   24038:                     'phprelease', 'extsrcrelease', 'extbinrelease',
                   24039:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
                   24040:             ));
                   24041:     }
                   24042: 
                   24043:     /**
                   24044:      * Remove all compatible tags
                   24045:      */
                   24046:     function clearCompatible()
                   24047:     {
                   24048:         unset($this->_packageInfo['compatible']);
                   24049:     }
                   24050: 
                   24051:     /**
                   24052:      * Reset dependencies prior to adding new ones
                   24053:      */
                   24054:     function clearDeps()
                   24055:     {
                   24056:         if (!isset($this->_packageInfo['dependencies'])) {
                   24057:             $this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(),
                   24058:                 array(
                   24059:                     'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   24060:                         'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   24061:                         'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')));
                   24062:         }
                   24063:         $this->_packageInfo['dependencies'] = array();
                   24064:     }
                   24065: 
                   24066:     /**
                   24067:      * @param string minimum PHP version allowed
                   24068:      * @param string maximum PHP version allowed
                   24069:      * @param array $exclude incompatible PHP versions
                   24070:      */
                   24071:     function setPhpDep($min, $max = false, $exclude = false)
                   24072:     {
                   24073:         $this->_isValid = 0;
                   24074:         $dep =
                   24075:             array(
                   24076:                 'min' => $min,
                   24077:             );
                   24078:         if ($max) {
                   24079:             $dep['max'] = $max;
                   24080:         }
                   24081:         if ($exclude) {
                   24082:             if (count($exclude) == 1) {
                   24083:                 $exclude = $exclude[0];
                   24084:             }
                   24085:             $dep['exclude'] = $exclude;
                   24086:         }
                   24087:         if (isset($this->_packageInfo['dependencies']['required']['php'])) {
                   24088:             $this->_stack->push(__FUNCTION__, 'warning', array('dep' =>
                   24089:             $this->_packageInfo['dependencies']['required']['php']),
                   24090:                 'warning: PHP dependency already exists, overwriting');
                   24091:             unset($this->_packageInfo['dependencies']['required']['php']);
                   24092:         }
                   24093:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   24094:             array(
                   24095:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   24096:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   24097:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   24098:                 'required' => array('optional', 'group'),
                   24099:                 'php' => array('pearinstaller', 'package', 'subpackage', 'extension', 'os', 'arch')
                   24100:             ));
                   24101:         return true;
                   24102:     }
                   24103: 
                   24104:     /**
                   24105:      * @param string minimum allowed PEAR installer version
                   24106:      * @param string maximum allowed PEAR installer version
                   24107:      * @param string recommended PEAR installer version
                   24108:      * @param array incompatible version of the PEAR installer
                   24109:      */
                   24110:     function setPearinstallerDep($min, $max = false, $recommended = false, $exclude = false)
                   24111:     {
                   24112:         $this->_isValid = 0;
                   24113:         $dep =
                   24114:             array(
                   24115:                 'min' => $min,
                   24116:             );
                   24117:         if ($max) {
                   24118:             $dep['max'] = $max;
                   24119:         }
                   24120:         if ($recommended) {
                   24121:             $dep['recommended'] = $recommended;
                   24122:         }
                   24123:         if ($exclude) {
                   24124:             if (count($exclude) == 1) {
                   24125:                 $exclude = $exclude[0];
                   24126:             }
                   24127:             $dep['exclude'] = $exclude;
                   24128:         }
                   24129:         if (isset($this->_packageInfo['dependencies']['required']['pearinstaller'])) {
                   24130:             $this->_stack->push(__FUNCTION__, 'warning', array('dep' =>
                   24131:             $this->_packageInfo['dependencies']['required']['pearinstaller']),
                   24132:                 'warning: PEAR Installer dependency already exists, overwriting');
                   24133:             unset($this->_packageInfo['dependencies']['required']['pearinstaller']);
                   24134:         }
                   24135:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   24136:             array(
                   24137:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   24138:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   24139:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   24140:                 'required' => array('optional', 'group'),
                   24141:                 'pearinstaller' => array('package', 'subpackage', 'extension', 'os', 'arch')
                   24142:             ));
                   24143:     }
                   24144: 
                   24145:     /**
                   24146:      * Mark a package as conflicting with this package
                   24147:      * @param string package name
                   24148:      * @param string package channel
                   24149:      * @param string extension this package provides, if any
                   24150:      * @param string|false minimum version required
                   24151:      * @param string|false maximum version allowed
                   24152:      * @param array|false versions to exclude from installation
                   24153:      */
                   24154:     function addConflictingPackageDepWithChannel($name, $channel,
                   24155:                 $providesextension = false, $min = false, $max = false, $exclude = false)
                   24156:     {
                   24157:         $this->_isValid = 0;
                   24158:         $dep = $this->_constructDep($name, $channel, false, $min, $max, false,
                   24159:             $exclude, $providesextension, false, true);
                   24160:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   24161:             array(
                   24162:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   24163:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   24164:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   24165:                 'required' => array('optional', 'group'),
                   24166:                 'package' => array('subpackage', 'extension', 'os', 'arch')
                   24167:             ));
                   24168:     }
                   24169: 
                   24170:     /**
                   24171:      * Mark a package as conflicting with this package
                   24172:      * @param string package name
                   24173:      * @param string package channel
                   24174:      * @param string extension this package provides, if any
                   24175:      */
                   24176:     function addConflictingPackageDepWithUri($name, $uri, $providesextension = false)
                   24177:     {
                   24178:         $this->_isValid = 0;
                   24179:         $dep =
                   24180:             array(
                   24181:                 'name' => $name,
                   24182:                 'uri' => $uri,
                   24183:                 'conflicts' => '',
                   24184:             );
                   24185:         if ($providesextension) {
                   24186:             $dep['providesextension'] = $providesextension;
                   24187:         }
                   24188:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   24189:             array(
                   24190:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   24191:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   24192:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   24193:                 'required' => array('optional', 'group'),
                   24194:                 'package' => array('subpackage', 'extension', 'os', 'arch')
                   24195:             ));
                   24196:     }
                   24197: 
                   24198:     function addDependencyGroup($name, $hint)
                   24199:     {
                   24200:         $this->_isValid = 0;
                   24201:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo,
                   24202:             array('attribs' => array('name' => $name, 'hint' => $hint)),
                   24203:             array(
                   24204:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   24205:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   24206:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   24207:                 'group' => array(),
                   24208:             ));
                   24209:     }
                   24210: 
                   24211:     /**
                   24212:      * @param string package name
                   24213:      * @param string|false channel name, false if this is a uri
                   24214:      * @param string|false uri name, false if this is a channel
                   24215:      * @param string|false minimum version required
                   24216:      * @param string|false maximum version allowed
                   24217:      * @param string|false recommended installation version
                   24218:      * @param array|false versions to exclude from installation
                   24219:      * @param string extension this package provides, if any
                   24220:      * @param bool if true, tells the installer to ignore the default optional dependency group
                   24221:      *             when installing this package
                   24222:      * @param bool if true, tells the installer to negate this dependency (conflicts)
                   24223:      * @return array
                   24224:      * @access private
                   24225:      */
                   24226:     function _constructDep($name, $channel, $uri, $min, $max, $recommended, $exclude,
                   24227:                            $providesextension = false, $nodefault = false,
                   24228:                            $conflicts = false)
                   24229:     {
                   24230:         $dep =
                   24231:             array(
                   24232:                 'name' => $name,
                   24233:             );
                   24234:         if ($channel) {
                   24235:             $dep['channel'] = $channel;
                   24236:         } elseif ($uri) {
                   24237:             $dep['uri'] = $uri;
                   24238:         }
                   24239:         if ($min) {
                   24240:             $dep['min'] = $min;
                   24241:         }
                   24242:         if ($max) {
                   24243:             $dep['max'] = $max;
                   24244:         }
                   24245:         if ($recommended) {
                   24246:             $dep['recommended'] = $recommended;
                   24247:         }
                   24248:         if ($exclude) {
                   24249:             if (is_array($exclude) && count($exclude) == 1) {
                   24250:                 $exclude = $exclude[0];
                   24251:             }
                   24252:             $dep['exclude'] = $exclude;
                   24253:         }
                   24254:         if ($conflicts) {
                   24255:             $dep['conflicts'] = '';
                   24256:         }
                   24257:         if ($nodefault) {
                   24258:             $dep['nodefault'] = '';
                   24259:         }
                   24260:         if ($providesextension) {
                   24261:             $dep['providesextension'] = $providesextension;
                   24262:         }
                   24263:         return $dep;
                   24264:     }
                   24265: 
                   24266:     /**
                   24267:      * @param package|subpackage
                   24268:      * @param string group name
                   24269:      * @param string package name
                   24270:      * @param string package channel
                   24271:      * @param string minimum version
                   24272:      * @param string maximum version
                   24273:      * @param string recommended version
                   24274:      * @param array|false optional excluded versions
                   24275:      * @param string extension this package provides, if any
                   24276:      * @param bool if true, tells the installer to ignore the default optional dependency group
                   24277:      *             when installing this package
                   24278:      * @return bool false if the dependency group has not been initialized with
                   24279:      *              {@link addDependencyGroup()}, or a subpackage is added with
                   24280:      *              a providesextension
                   24281:      */
                   24282:     function addGroupPackageDepWithChannel($type, $groupname, $name, $channel, $min = false,
                   24283:                                       $max = false, $recommended = false, $exclude = false,
                   24284:                                       $providesextension = false, $nodefault = false)
                   24285:     {
                   24286:         if ($type == 'subpackage' && $providesextension) {
                   24287:             return false; // subpackages must be php packages
                   24288:         }
                   24289:         $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
                   24290:             $providesextension, $nodefault);
                   24291:         return $this->_addGroupDependency($type, $dep, $groupname);
                   24292:     }
                   24293: 
                   24294:     /**
                   24295:      * @param package|subpackage
                   24296:      * @param string group name
                   24297:      * @param string package name
                   24298:      * @param string package uri
                   24299:      * @param string extension this package provides, if any
                   24300:      * @param bool if true, tells the installer to ignore the default optional dependency group
                   24301:      *             when installing this package
                   24302:      * @return bool false if the dependency group has not been initialized with
                   24303:      *              {@link addDependencyGroup()}
                   24304:      */
                   24305:     function addGroupPackageDepWithURI($type, $groupname, $name, $uri, $providesextension = false,
                   24306:                                        $nodefault = false)
                   24307:     {
                   24308:         if ($type == 'subpackage' && $providesextension) {
                   24309:             return false; // subpackages must be php packages
                   24310:         }
                   24311:         $dep = $this->_constructDep($name, false, $uri, false, false, false, false,
                   24312:             $providesextension, $nodefault);
                   24313:         return $this->_addGroupDependency($type, $dep, $groupname);
                   24314:     }
                   24315: 
                   24316:     /**
                   24317:      * @param string group name (must be pre-existing)
                   24318:      * @param string extension name
                   24319:      * @param string minimum version allowed
                   24320:      * @param string maximum version allowed
                   24321:      * @param string recommended version
                   24322:      * @param array incompatible versions
                   24323:      */
                   24324:     function addGroupExtensionDep($groupname, $name, $min = false, $max = false,
                   24325:                                          $recommended = false, $exclude = false)
                   24326:     {
                   24327:         $this->_isValid = 0;
                   24328:         $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
                   24329:         return $this->_addGroupDependency('extension', $dep, $groupname);
                   24330:     }
                   24331: 
                   24332:     /**
                   24333:      * @param package|subpackage|extension
                   24334:      * @param array dependency contents
                   24335:      * @param string name of the dependency group to add this to
                   24336:      * @return boolean
                   24337:      * @access private
                   24338:      */
                   24339:     function _addGroupDependency($type, $dep, $groupname)
                   24340:     {
                   24341:         $arr = array('subpackage', 'extension');
                   24342:         if ($type != 'package') {
                   24343:             array_shift($arr);
                   24344:         }
                   24345:         if ($type == 'extension') {
                   24346:             array_shift($arr);
                   24347:         }
                   24348:         if (!isset($this->_packageInfo['dependencies']['group'])) {
                   24349:             return false;
                   24350:         } else {
                   24351:             if (!isset($this->_packageInfo['dependencies']['group'][0])) {
                   24352:                 if ($this->_packageInfo['dependencies']['group']['attribs']['name'] == $groupname) {
                   24353:                     $this->_packageInfo['dependencies']['group'] = $this->_mergeTag(
                   24354:                         $this->_packageInfo['dependencies']['group'], $dep,
                   24355:                         array(
                   24356:                             $type => $arr
                   24357:                         ));
                   24358:                     $this->_isValid = 0;
                   24359:                     return true;
                   24360:                 } else {
                   24361:                     return false;
                   24362:                 }
                   24363:             } else {
                   24364:                 foreach ($this->_packageInfo['dependencies']['group'] as $i => $group) {
                   24365:                     if ($group['attribs']['name'] == $groupname) {
                   24366:                     $this->_packageInfo['dependencies']['group'][$i] = $this->_mergeTag(
                   24367:                         $this->_packageInfo['dependencies']['group'][$i], $dep,
                   24368:                         array(
                   24369:                             $type => $arr
                   24370:                         ));
                   24371:                         $this->_isValid = 0;
                   24372:                         return true;
                   24373:                     }
                   24374:                 }
                   24375:                 return false;
                   24376:             }
                   24377:         }
                   24378:     }
                   24379: 
                   24380:     /**
                   24381:      * @param optional|required
                   24382:      * @param string package name
                   24383:      * @param string package channel
                   24384:      * @param string minimum version
                   24385:      * @param string maximum version
                   24386:      * @param string recommended version
                   24387:      * @param string extension this package provides, if any
                   24388:      * @param bool if true, tells the installer to ignore the default optional dependency group
                   24389:      *             when installing this package
                   24390:      * @param array|false optional excluded versions
                   24391:      */
                   24392:     function addPackageDepWithChannel($type, $name, $channel, $min = false, $max = false,
                   24393:                                       $recommended = false, $exclude = false,
                   24394:                                       $providesextension = false, $nodefault = false)
                   24395:     {
                   24396:         if (!in_array($type, array('optional', 'required'), true)) {
                   24397:             $type = 'required';
                   24398:         }
                   24399:         $this->_isValid = 0;
                   24400:         $arr = array('optional', 'group');
                   24401:         if ($type != 'required') {
                   24402:             array_shift($arr);
                   24403:         }
                   24404:         $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
                   24405:             $providesextension, $nodefault);
                   24406:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   24407:             array(
                   24408:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   24409:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   24410:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   24411:                 $type => $arr,
                   24412:                 'package' => array('subpackage', 'extension', 'os', 'arch')
                   24413:             ));
                   24414:     }
                   24415: 
                   24416:     /**
                   24417:      * @param optional|required
                   24418:      * @param string name of the package
                   24419:      * @param string uri of the package
                   24420:      * @param string extension this package provides, if any
                   24421:      * @param bool if true, tells the installer to ignore the default optional dependency group
                   24422:      *             when installing this package
                   24423:      */
                   24424:     function addPackageDepWithUri($type, $name, $uri, $providesextension = false,
                   24425:                                   $nodefault = false)
                   24426:     {
                   24427:         $this->_isValid = 0;
                   24428:         $arr = array('optional', 'group');
                   24429:         if ($type != 'required') {
                   24430:             array_shift($arr);
                   24431:         }
                   24432:         $dep = $this->_constructDep($name, false, $uri, false, false, false, false,
                   24433:             $providesextension, $nodefault);
                   24434:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   24435:             array(
                   24436:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   24437:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   24438:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   24439:                 $type => $arr,
                   24440:                 'package' => array('subpackage', 'extension', 'os', 'arch')
                   24441:             ));
                   24442:     }
                   24443: 
                   24444:     /**
                   24445:      * @param optional|required optional, required
                   24446:      * @param string package name
                   24447:      * @param string package channel
                   24448:      * @param string minimum version
                   24449:      * @param string maximum version
                   24450:      * @param string recommended version
                   24451:      * @param array incompatible versions
                   24452:      * @param bool if true, tells the installer to ignore the default optional dependency group
                   24453:      *             when installing this package
                   24454:      */
                   24455:     function addSubpackageDepWithChannel($type, $name, $channel, $min = false, $max = false,
                   24456:                                          $recommended = false, $exclude = false,
                   24457:                                          $nodefault = false)
                   24458:     {
                   24459:         $this->_isValid = 0;
                   24460:         $arr = array('optional', 'group');
                   24461:         if ($type != 'required') {
                   24462:             array_shift($arr);
                   24463:         }
                   24464:         $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
                   24465:             $nodefault);
                   24466:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   24467:             array(
                   24468:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   24469:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   24470:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   24471:                 $type => $arr,
                   24472:                 'subpackage' => array('extension', 'os', 'arch')
                   24473:             ));
                   24474:     }
                   24475: 
                   24476:     /**
                   24477:      * @param optional|required optional, required
                   24478:      * @param string package name
                   24479:      * @param string package uri for download
                   24480:      * @param bool if true, tells the installer to ignore the default optional dependency group
                   24481:      *             when installing this package
                   24482:      */
                   24483:     function addSubpackageDepWithUri($type, $name, $uri, $nodefault = false)
                   24484:     {
                   24485:         $this->_isValid = 0;
                   24486:         $arr = array('optional', 'group');
                   24487:         if ($type != 'required') {
                   24488:             array_shift($arr);
                   24489:         }
                   24490:         $dep = $this->_constructDep($name, false, $uri, false, false, false, false, $nodefault);
                   24491:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   24492:             array(
                   24493:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   24494:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   24495:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   24496:                 $type => $arr,
                   24497:                 'subpackage' => array('extension', 'os', 'arch')
                   24498:             ));
                   24499:     }
                   24500: 
                   24501:     /**
                   24502:      * @param optional|required optional, required
                   24503:      * @param string extension name
                   24504:      * @param string minimum version
                   24505:      * @param string maximum version
                   24506:      * @param string recommended version
                   24507:      * @param array incompatible versions
                   24508:      */
                   24509:     function addExtensionDep($type, $name, $min = false, $max = false, $recommended = false,
                   24510:                              $exclude = false)
                   24511:     {
                   24512:         $this->_isValid = 0;
                   24513:         $arr = array('optional', 'group');
                   24514:         if ($type != 'required') {
                   24515:             array_shift($arr);
                   24516:         }
                   24517:         $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
                   24518:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   24519:             array(
                   24520:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   24521:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   24522:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   24523:                 $type => $arr,
                   24524:                 'extension' => array('os', 'arch')
                   24525:             ));
                   24526:     }
                   24527: 
                   24528:     /**
                   24529:      * @param string Operating system name
                   24530:      * @param boolean true if this package cannot be installed on this OS
                   24531:      */
                   24532:     function addOsDep($name, $conflicts = false)
                   24533:     {
                   24534:         $this->_isValid = 0;
                   24535:         $dep = array('name' => $name);
                   24536:         if ($conflicts) {
                   24537:             $dep['conflicts'] = '';
                   24538:         }
                   24539:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   24540:             array(
                   24541:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   24542:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   24543:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   24544:                 'required' => array('optional', 'group'),
                   24545:                 'os' => array('arch')
                   24546:             ));
                   24547:     }
                   24548: 
                   24549:     /**
                   24550:      * @param string Architecture matching pattern
                   24551:      * @param boolean true if this package cannot be installed on this architecture
                   24552:      */
                   24553:     function addArchDep($pattern, $conflicts = false)
                   24554:     {
                   24555:         $this->_isValid = 0;
                   24556:         $dep = array('pattern' => $pattern);
                   24557:         if ($conflicts) {
                   24558:             $dep['conflicts'] = '';
                   24559:         }
                   24560:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
                   24561:             array(
                   24562:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
                   24563:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
                   24564:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
                   24565:                 'required' => array('optional', 'group'),
                   24566:                 'arch' => array()
                   24567:             ));
                   24568:     }
                   24569: 
                   24570:     /**
                   24571:      * Set the kind of package, and erase all release tags
                   24572:      *
                   24573:      * - a php package is a PEAR-style package
                   24574:      * - an extbin package is a PECL-style extension binary
                   24575:      * - an extsrc package is a PECL-style source for a binary
                   24576:      * - an zendextbin package is a PECL-style zend extension binary
                   24577:      * - an zendextsrc package is a PECL-style source for a zend extension binary
                   24578:      * - a bundle package is a collection of other pre-packaged packages
                   24579:      * @param php|extbin|extsrc|zendextsrc|zendextbin|bundle
                   24580:      * @return bool success
                   24581:      */
                   24582:     function setPackageType($type)
                   24583:     {
                   24584:         $this->_isValid = 0;
                   24585:         if (!in_array($type, array('php', 'extbin', 'extsrc', 'zendextsrc',
                   24586:                                    'zendextbin', 'bundle'))) {
                   24587:             return false;
                   24588:         }
                   24589: 
                   24590:         if (in_array($type, array('zendextsrc', 'zendextbin'))) {
                   24591:             $this->_setPackageVersion2_1();
                   24592:         }
                   24593: 
                   24594:         if ($type != 'bundle') {
                   24595:             $type .= 'release';
                   24596:         }
                   24597: 
                   24598:         foreach (array('phprelease', 'extbinrelease', 'extsrcrelease',
                   24599:                        'zendextsrcrelease', 'zendextbinrelease', 'bundle') as $test) {
                   24600:             unset($this->_packageInfo[$test]);
                   24601:         }
                   24602: 
                   24603:         if (!isset($this->_packageInfo[$type])) {
                   24604:             // ensure that the release tag is set up
                   24605:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('changelog'),
                   24606:                 array(), $type);
                   24607:         }
                   24608: 
                   24609:         $this->_packageInfo[$type] = array();
                   24610:         return true;
                   24611:     }
                   24612: 
                   24613:     /**
                   24614:      * @return bool true if package type is set up
                   24615:      */
                   24616:     function addRelease()
                   24617:     {
                   24618:         if ($type = $this->getPackageType()) {
                   24619:             if ($type != 'bundle') {
                   24620:                 $type .= 'release';
                   24621:             }
                   24622:             $this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(),
                   24623:                 array($type => array('changelog')));
                   24624:             return true;
                   24625:         }
                   24626:         return false;
                   24627:     }
                   24628: 
                   24629:     /**
                   24630:      * Get the current release tag in order to add to it
                   24631:      * @param bool returns only releases that have installcondition if true
                   24632:      * @return array|null
                   24633:      */
                   24634:     function &_getCurrentRelease($strict = true)
                   24635:     {
                   24636:         if ($p = $this->getPackageType()) {
                   24637:             if ($strict) {
                   24638:                 if ($p == 'extsrc' || $p == 'zendextsrc') {
                   24639:                     $a = null;
                   24640:                     return $a;
                   24641:                 }
                   24642:             }
                   24643:             if ($p != 'bundle') {
                   24644:                 $p .= 'release';
                   24645:             }
                   24646:             if (isset($this->_packageInfo[$p][0])) {
                   24647:                 return $this->_packageInfo[$p][count($this->_packageInfo[$p]) - 1];
                   24648:             } else {
                   24649:                 return $this->_packageInfo[$p];
                   24650:             }
                   24651:         } else {
                   24652:             $a = null;
                   24653:             return $a;
                   24654:         }
                   24655:     }
                   24656: 
                   24657:     /**
                   24658:      * Add a file to the current release that should be installed under a different name
                   24659:      * @param string <contents> path to file
                   24660:      * @param string name the file should be installed as
                   24661:      */
                   24662:     function addInstallAs($path, $as)
                   24663:     {
                   24664:         $r = &$this->_getCurrentRelease();
                   24665:         if ($r === null) {
                   24666:             return false;
                   24667:         }
                   24668:         $this->_isValid = 0;
                   24669:         $r = $this->_mergeTag($r, array('attribs' => array('name' => $path, 'as' => $as)),
                   24670:             array(
                   24671:                 'filelist' => array(),
                   24672:                 'install' => array('ignore')
                   24673:             ));
                   24674:     }
                   24675: 
                   24676:     /**
                   24677:      * Add a file to the current release that should be ignored
                   24678:      * @param string <contents> path to file
                   24679:      * @return bool success of operation
                   24680:      */
                   24681:     function addIgnore($path)
                   24682:     {
                   24683:         $r = &$this->_getCurrentRelease();
                   24684:         if ($r === null) {
                   24685:             return false;
                   24686:         }
                   24687:         $this->_isValid = 0;
                   24688:         $r = $this->_mergeTag($r, array('attribs' => array('name' => $path)),
                   24689:             array(
                   24690:                 'filelist' => array(),
                   24691:                 'ignore' => array()
                   24692:             ));
                   24693:     }
                   24694: 
                   24695:     /**
                   24696:      * Add an extension binary package for this extension source code release
                   24697:      *
                   24698:      * Note that the package must be from the same channel as the extension source package
                   24699:      * @param string
                   24700:      */
                   24701:     function addBinarypackage($package)
                   24702:     {
                   24703:         if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
                   24704:             return false;
                   24705:         }
                   24706:         $r = &$this->_getCurrentRelease(false);
                   24707:         if ($r === null) {
                   24708:             return false;
                   24709:         }
                   24710:         $this->_isValid = 0;
                   24711:         $r = $this->_mergeTag($r, $package,
                   24712:             array(
                   24713:                 'binarypackage' => array('filelist'),
                   24714:             ));
                   24715:     }
                   24716: 
                   24717:     /**
                   24718:      * Add a configureoption to an extension source package
                   24719:      * @param string
                   24720:      * @param string
                   24721:      * @param string
                   24722:      */
                   24723:     function addConfigureOption($name, $prompt, $default = null)
                   24724:     {
                   24725:         if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
                   24726:             return false;
                   24727:         }
                   24728: 
                   24729:         $r = &$this->_getCurrentRelease(false);
                   24730:         if ($r === null) {
                   24731:             return false;
                   24732:         }
                   24733: 
                   24734:         $opt = array('attribs' => array('name' => $name, 'prompt' => $prompt));
                   24735:         if ($default !== null) {
                   24736:             $opt['attribs']['default'] = $default;
                   24737:         }
                   24738: 
                   24739:         $this->_isValid = 0;
                   24740:         $r = $this->_mergeTag($r, $opt,
                   24741:             array(
                   24742:                 'configureoption' => array('binarypackage', 'filelist'),
                   24743:             ));
                   24744:     }
                   24745: 
                   24746:     /**
                   24747:      * Set an installation condition based on php version for the current release set
                   24748:      * @param string minimum version
                   24749:      * @param string maximum version
                   24750:      * @param false|array incompatible versions of PHP
                   24751:      */
                   24752:     function setPhpInstallCondition($min, $max, $exclude = false)
                   24753:     {
                   24754:         $r = &$this->_getCurrentRelease();
                   24755:         if ($r === null) {
                   24756:             return false;
                   24757:         }
                   24758:         $this->_isValid = 0;
                   24759:         if (isset($r['installconditions']['php'])) {
                   24760:             unset($r['installconditions']['php']);
                   24761:         }
                   24762:         $dep = array('min' => $min, 'max' => $max);
                   24763:         if ($exclude) {
                   24764:             if (is_array($exclude) && count($exclude) == 1) {
                   24765:                 $exclude = $exclude[0];
                   24766:             }
                   24767:             $dep['exclude'] = $exclude;
                   24768:         }
                   24769:         if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
                   24770:             $r = $this->_mergeTag($r, $dep,
                   24771:                 array(
                   24772:                     'installconditions' => array('configureoption', 'binarypackage',
                   24773:                         'filelist'),
                   24774:                     'php' => array('extension', 'os', 'arch')
                   24775:                 ));
                   24776:         } else {
                   24777:             $r = $this->_mergeTag($r, $dep,
                   24778:                 array(
                   24779:                     'installconditions' => array('filelist'),
                   24780:                     'php' => array('extension', 'os', 'arch')
                   24781:                 ));
                   24782:         }
                   24783:     }
                   24784: 
                   24785:     /**
                   24786:      * @param optional|required optional, required
                   24787:      * @param string extension name
                   24788:      * @param string minimum version
                   24789:      * @param string maximum version
                   24790:      * @param string recommended version
                   24791:      * @param array incompatible versions
                   24792:      */
                   24793:     function addExtensionInstallCondition($name, $min = false, $max = false, $recommended = false,
                   24794:                                           $exclude = false)
                   24795:     {
                   24796:         $r = &$this->_getCurrentRelease();
                   24797:         if ($r === null) {
                   24798:             return false;
                   24799:         }
                   24800:         $this->_isValid = 0;
                   24801:         $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
                   24802:         if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
                   24803:             $r = $this->_mergeTag($r, $dep,
                   24804:                 array(
                   24805:                     'installconditions' => array('configureoption', 'binarypackage',
                   24806:                         'filelist'),
                   24807:                     'extension' => array('os', 'arch')
                   24808:                 ));
                   24809:         } else {
                   24810:             $r = $this->_mergeTag($r, $dep,
                   24811:                 array(
                   24812:                     'installconditions' => array('filelist'),
                   24813:                     'extension' => array('os', 'arch')
                   24814:                 ));
                   24815:         }
                   24816:     }
                   24817: 
                   24818:     /**
                   24819:      * Set an installation condition based on operating system for the current release set
                   24820:      * @param string OS name
                   24821:      * @param bool whether this OS is incompatible with the current release
                   24822:      */
                   24823:     function setOsInstallCondition($name, $conflicts = false)
                   24824:     {
                   24825:         $r = &$this->_getCurrentRelease();
                   24826:         if ($r === null) {
                   24827:             return false;
                   24828:         }
                   24829:         $this->_isValid = 0;
                   24830:         if (isset($r['installconditions']['os'])) {
                   24831:             unset($r['installconditions']['os']);
                   24832:         }
                   24833:         $dep = array('name' => $name);
                   24834:         if ($conflicts) {
                   24835:             $dep['conflicts'] = '';
                   24836:         }
                   24837:         if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
                   24838:             $r = $this->_mergeTag($r, $dep,
                   24839:                 array(
                   24840:                     'installconditions' => array('configureoption', 'binarypackage',
                   24841:                         'filelist'),
                   24842:                     'os' => array('arch')
                   24843:                 ));
                   24844:         } else {
                   24845:             $r = $this->_mergeTag($r, $dep,
                   24846:                 array(
                   24847:                     'installconditions' => array('filelist'),
                   24848:                     'os' => array('arch')
                   24849:                 ));
                   24850:         }
                   24851:     }
                   24852: 
                   24853:     /**
                   24854:      * Set an installation condition based on architecture for the current release set
                   24855:      * @param string architecture pattern
                   24856:      * @param bool whether this arch is incompatible with the current release
                   24857:      */
                   24858:     function setArchInstallCondition($pattern, $conflicts = false)
                   24859:     {
                   24860:         $r = &$this->_getCurrentRelease();
                   24861:         if ($r === null) {
                   24862:             return false;
                   24863:         }
                   24864:         $this->_isValid = 0;
                   24865:         if (isset($r['installconditions']['arch'])) {
                   24866:             unset($r['installconditions']['arch']);
                   24867:         }
                   24868:         $dep = array('pattern' => $pattern);
                   24869:         if ($conflicts) {
                   24870:             $dep['conflicts'] = '';
                   24871:         }
                   24872:         if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
                   24873:             $r = $this->_mergeTag($r, $dep,
                   24874:                 array(
                   24875:                     'installconditions' => array('configureoption', 'binarypackage',
                   24876:                         'filelist'),
                   24877:                     'arch' => array()
                   24878:                 ));
                   24879:         } else {
                   24880:             $r = $this->_mergeTag($r, $dep,
                   24881:                 array(
                   24882:                     'installconditions' => array('filelist'),
                   24883:                     'arch' => array()
                   24884:                 ));
                   24885:         }
                   24886:     }
                   24887: 
                   24888:     /**
                   24889:      * For extension binary releases, this is used to specify either the
                   24890:      * static URI to a source package, or the package name and channel of the extsrc/zendextsrc
                   24891:      * package it is based on.
                   24892:      * @param string Package name, or full URI to source package (extsrc/zendextsrc type)
                   24893:      */
                   24894:     function setSourcePackage($packageOrUri)
                   24895:     {
                   24896:         $this->_isValid = 0;
                   24897:         if (isset($this->_packageInfo['channel'])) {
                   24898:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease',
                   24899:                 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   24900:                 'bundle', 'changelog'),
                   24901:                 $packageOrUri, 'srcpackage');
                   24902:         } else {
                   24903:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease',
                   24904:                 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
                   24905:                 'bundle', 'changelog'), $packageOrUri, 'srcuri');
                   24906:         }
                   24907:     }
                   24908: 
                   24909:     /**
                   24910:      * Generate a valid change log entry from the current package.xml
                   24911:      * @param string|false
                   24912:      */
                   24913:     function generateChangeLogEntry($notes = false)
                   24914:     {
                   24915:         return array(
                   24916:             'version' =>
                   24917:                 array(
                   24918:                     'release' => $this->getVersion('release'),
                   24919:                     'api' => $this->getVersion('api'),
                   24920:                     ),
                   24921:             'stability' =>
                   24922:                 $this->getStability(),
                   24923:             'date' => $this->getDate(),
                   24924:             'license' => $this->getLicense(true),
                   24925:             'notes' => $notes ? $notes : $this->getNotes()
                   24926:             );
                   24927:     }
                   24928: 
                   24929:     /**
                   24930:      * @param string release version to set change log notes for
                   24931:      * @param array output of {@link generateChangeLogEntry()}
                   24932:      */
                   24933:     function setChangelogEntry($releaseversion, $contents)
                   24934:     {
                   24935:         if (!isset($this->_packageInfo['changelog'])) {
                   24936:             $this->_packageInfo['changelog']['release'] = $contents;
                   24937:             return;
                   24938:         }
                   24939:         if (!isset($this->_packageInfo['changelog']['release'][0])) {
                   24940:             if ($this->_packageInfo['changelog']['release']['version']['release'] == $releaseversion) {
                   24941:                 $this->_packageInfo['changelog']['release'] = array(
                   24942:                     $this->_packageInfo['changelog']['release']);
                   24943:             } else {
                   24944:                 $this->_packageInfo['changelog']['release'] = array(
                   24945:                     $this->_packageInfo['changelog']['release']);
                   24946:                 return $this->_packageInfo['changelog']['release'][] = $contents;
                   24947:             }
                   24948:         }
                   24949:         foreach($this->_packageInfo['changelog']['release'] as $index => $changelog) {
                   24950:             if (isset($changelog['version']) &&
                   24951:                   strnatcasecmp($changelog['version']['release'], $releaseversion) == 0) {
                   24952:                 $curlog = $index;
                   24953:             }
                   24954:         }
                   24955:         if (isset($curlog)) {
                   24956:             $this->_packageInfo['changelog']['release'][$curlog] = $contents;
                   24957:         } else {
                   24958:             $this->_packageInfo['changelog']['release'][] = $contents;
                   24959:         }
                   24960:     }
                   24961: 
                   24962:     /**
                   24963:      * Remove the changelog entirely
                   24964:      */
                   24965:     function clearChangeLog()
                   24966:     {
                   24967:         unset($this->_packageInfo['changelog']);
                   24968:     }
1.1.1.2 ! misho    24969: }PEAR-1.9.4/PEAR/PackageFile/v2/Validator.php0000644000076500000240000025015111605156614017107 0ustar  helgistaff<?php
1.1       misho    24970: /**
                   24971:  * PEAR_PackageFile_v2, package.xml version 2.0, read/write version
                   24972:  *
                   24973:  * PHP versions 4 and 5
                   24974:  *
                   24975:  * @category   pear
                   24976:  * @package    PEAR
                   24977:  * @author     Greg Beaver <cellog@php.net>
                   24978:  * @copyright  1997-2009 The Authors
                   24979:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   24980:  * @version    CVS: $Id: Validator.php 313023 2011-07-06 19:17:11Z dufuz $
                   24981:  * @link       http://pear.php.net/package/PEAR
                   24982:  * @since      File available since Release 1.4.0a8
                   24983:  */
                   24984: /**
                   24985:  * Private validation class used by PEAR_PackageFile_v2 - do not use directly, its
                   24986:  * sole purpose is to split up the PEAR/PackageFile/v2.php file to make it smaller
                   24987:  * @category   pear
                   24988:  * @package    PEAR
                   24989:  * @author     Greg Beaver <cellog@php.net>
                   24990:  * @copyright  1997-2009 The Authors
                   24991:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   24992:  * @version    Release: 1.9.4
                   24993:  * @link       http://pear.php.net/package/PEAR
                   24994:  * @since      Class available since Release 1.4.0a8
                   24995:  * @access private
                   24996:  */
                   24997: class PEAR_PackageFile_v2_Validator
                   24998: {
                   24999:     /**
                   25000:      * @var array
                   25001:      */
                   25002:     var $_packageInfo;
                   25003:     /**
                   25004:      * @var PEAR_PackageFile_v2
                   25005:      */
                   25006:     var $_pf;
                   25007:     /**
                   25008:      * @var PEAR_ErrorStack
                   25009:      */
                   25010:     var $_stack;
                   25011:     /**
                   25012:      * @var int
                   25013:      */
                   25014:     var $_isValid = 0;
                   25015:     /**
                   25016:      * @var int
                   25017:      */
                   25018:     var $_filesValid = 0;
                   25019:     /**
                   25020:      * @var int
                   25021:      */
                   25022:     var $_curState = 0;
                   25023:     /**
                   25024:      * @param PEAR_PackageFile_v2
                   25025:      * @param int
                   25026:      */
                   25027:     function validate(&$pf, $state = PEAR_VALIDATE_NORMAL)
                   25028:     {
                   25029:         $this->_pf = &$pf;
                   25030:         $this->_curState = $state;
                   25031:         $this->_packageInfo = $this->_pf->getArray();
                   25032:         $this->_isValid = $this->_pf->_isValid;
                   25033:         $this->_filesValid = $this->_pf->_filesValid;
                   25034:         $this->_stack = &$pf->_stack;
                   25035:         $this->_stack->getErrors(true);
                   25036:         if (($this->_isValid & $state) == $state) {
                   25037:             return true;
                   25038:         }
                   25039:         if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) {
                   25040:             return false;
                   25041:         }
                   25042:         if (!isset($this->_packageInfo['attribs']['version']) ||
                   25043:               ($this->_packageInfo['attribs']['version'] != '2.0' &&
                   25044:                $this->_packageInfo['attribs']['version'] != '2.1')
                   25045:         ) {
                   25046:             $this->_noPackageVersion();
                   25047:         }
                   25048:         $structure =
                   25049:         array(
                   25050:             'name',
                   25051:             'channel|uri',
                   25052:             '*extends', // can't be multiple, but this works fine
                   25053:             'summary',
                   25054:             'description',
                   25055:             '+lead', // these all need content checks
                   25056:             '*developer',
                   25057:             '*contributor',
                   25058:             '*helper',
                   25059:             'date',
                   25060:             '*time',
                   25061:             'version',
                   25062:             'stability',
                   25063:             'license->?uri->?filesource',
                   25064:             'notes',
                   25065:             'contents', //special validation needed
                   25066:             '*compatible',
                   25067:             'dependencies', //special validation needed
                   25068:             '*usesrole',
                   25069:             '*usestask', // reserve these for 1.4.0a1 to implement
                   25070:                          // this will allow a package.xml to gracefully say it
                   25071:                          // needs a certain package installed in order to implement a role or task
                   25072:             '*providesextension',
                   25073:             '*srcpackage|*srcuri',
                   25074:             '+phprelease|+extsrcrelease|+extbinrelease|' .
                   25075:                 '+zendextsrcrelease|+zendextbinrelease|bundle', //special validation needed
                   25076:             '*changelog',
                   25077:         );
                   25078:         $test = $this->_packageInfo;
                   25079:         if (isset($test['dependencies']) &&
                   25080:               isset($test['dependencies']['required']) &&
                   25081:               isset($test['dependencies']['required']['pearinstaller']) &&
                   25082:               isset($test['dependencies']['required']['pearinstaller']['min']) &&
                   25083:               version_compare('1.9.4',
                   25084:                 $test['dependencies']['required']['pearinstaller']['min'], '<')
                   25085:         ) {
                   25086:             $this->_pearVersionTooLow($test['dependencies']['required']['pearinstaller']['min']);
                   25087:             return false;
                   25088:         }
                   25089:         // ignore post-installation array fields
                   25090:         if (array_key_exists('filelist', $test)) {
                   25091:             unset($test['filelist']);
                   25092:         }
                   25093:         if (array_key_exists('_lastmodified', $test)) {
                   25094:             unset($test['_lastmodified']);
                   25095:         }
                   25096:         if (array_key_exists('#binarypackage', $test)) {
                   25097:             unset($test['#binarypackage']);
                   25098:         }
                   25099:         if (array_key_exists('old', $test)) {
                   25100:             unset($test['old']);
                   25101:         }
                   25102:         if (array_key_exists('_lastversion', $test)) {
                   25103:             unset($test['_lastversion']);
                   25104:         }
                   25105:         if (!$this->_stupidSchemaValidate($structure, $test, '<package>')) {
                   25106:             return false;
                   25107:         }
                   25108:         if (empty($this->_packageInfo['name'])) {
                   25109:             $this->_tagCannotBeEmpty('name');
                   25110:         }
                   25111:         $test = isset($this->_packageInfo['uri']) ? 'uri' :'channel';
                   25112:         if (empty($this->_packageInfo[$test])) {
                   25113:             $this->_tagCannotBeEmpty($test);
                   25114:         }
                   25115:         if (is_array($this->_packageInfo['license']) &&
                   25116:               (!isset($this->_packageInfo['license']['_content']) ||
                   25117:               empty($this->_packageInfo['license']['_content']))) {
                   25118:             $this->_tagCannotBeEmpty('license');
                   25119:         } elseif (empty($this->_packageInfo['license'])) {
                   25120:             $this->_tagCannotBeEmpty('license');
                   25121:         }
                   25122:         if (empty($this->_packageInfo['summary'])) {
                   25123:             $this->_tagCannotBeEmpty('summary');
                   25124:         }
                   25125:         if (empty($this->_packageInfo['description'])) {
                   25126:             $this->_tagCannotBeEmpty('description');
                   25127:         }
                   25128:         if (empty($this->_packageInfo['date'])) {
                   25129:             $this->_tagCannotBeEmpty('date');
                   25130:         }
                   25131:         if (empty($this->_packageInfo['notes'])) {
                   25132:             $this->_tagCannotBeEmpty('notes');
                   25133:         }
                   25134:         if (isset($this->_packageInfo['time']) && empty($this->_packageInfo['time'])) {
                   25135:             $this->_tagCannotBeEmpty('time');
                   25136:         }
                   25137:         if (isset($this->_packageInfo['dependencies'])) {
                   25138:             $this->_validateDependencies();
                   25139:         }
                   25140:         if (isset($this->_packageInfo['compatible'])) {
                   25141:             $this->_validateCompatible();
                   25142:         }
                   25143:         if (!isset($this->_packageInfo['bundle'])) {
                   25144:             if (empty($this->_packageInfo['contents'])) {
                   25145:                 $this->_tagCannotBeEmpty('contents');
                   25146:             }
                   25147:             if (!isset($this->_packageInfo['contents']['dir'])) {
                   25148:                 $this->_filelistMustContainDir('contents');
                   25149:                 return false;
                   25150:             }
                   25151:             if (isset($this->_packageInfo['contents']['file'])) {
                   25152:                 $this->_filelistCannotContainFile('contents');
                   25153:                 return false;
                   25154:             }
                   25155:         }
                   25156:         $this->_validateMaintainers();
                   25157:         $this->_validateStabilityVersion();
                   25158:         $fail = false;
                   25159:         if (array_key_exists('usesrole', $this->_packageInfo)) {
                   25160:             $roles = $this->_packageInfo['usesrole'];
                   25161:             if (!is_array($roles) || !isset($roles[0])) {
                   25162:                 $roles = array($roles);
                   25163:             }
                   25164:             foreach ($roles as $role) {
                   25165:                 if (!isset($role['role'])) {
                   25166:                     $this->_usesroletaskMustHaveRoleTask('usesrole', 'role');
                   25167:                     $fail = true;
                   25168:                 } else {
                   25169:                     if (!isset($role['channel'])) {
                   25170:                         if (!isset($role['uri'])) {
                   25171:                             $this->_usesroletaskMustHaveChannelOrUri($role['role'], 'usesrole');
                   25172:                             $fail = true;
                   25173:                         }
                   25174:                     } elseif (!isset($role['package'])) {
                   25175:                         $this->_usesroletaskMustHavePackage($role['role'], 'usesrole');
                   25176:                         $fail = true;
                   25177:                     }
                   25178:                 }
                   25179:             }
                   25180:         }
                   25181:         if (array_key_exists('usestask', $this->_packageInfo)) {
                   25182:             $roles = $this->_packageInfo['usestask'];
                   25183:             if (!is_array($roles) || !isset($roles[0])) {
                   25184:                 $roles = array($roles);
                   25185:             }
                   25186:             foreach ($roles as $role) {
                   25187:                 if (!isset($role['task'])) {
                   25188:                     $this->_usesroletaskMustHaveRoleTask('usestask', 'task');
                   25189:                     $fail = true;
                   25190:                 } else {
                   25191:                     if (!isset($role['channel'])) {
                   25192:                         if (!isset($role['uri'])) {
                   25193:                             $this->_usesroletaskMustHaveChannelOrUri($role['task'], 'usestask');
                   25194:                             $fail = true;
                   25195:                         }
                   25196:                     } elseif (!isset($role['package'])) {
                   25197:                         $this->_usesroletaskMustHavePackage($role['task'], 'usestask');
                   25198:                         $fail = true;
                   25199:                     }
                   25200:                 }
                   25201:             }
                   25202:         }
                   25203: 
                   25204:         if ($fail) {
                   25205:             return false;
                   25206:         }
                   25207: 
                   25208:         $list = $this->_packageInfo['contents'];
                   25209:         if (isset($list['dir']) && is_array($list['dir']) && isset($list['dir'][0])) {
                   25210:             $this->_multipleToplevelDirNotAllowed();
                   25211:             return $this->_isValid = 0;
                   25212:         }
                   25213: 
                   25214:         $this->_validateFilelist();
                   25215:         $this->_validateRelease();
                   25216:         if (!$this->_stack->hasErrors()) {
                   25217:             $chan = $this->_pf->_registry->getChannel($this->_pf->getChannel(), true);
                   25218:             if (PEAR::isError($chan)) {
                   25219:                 $this->_unknownChannel($this->_pf->getChannel());
                   25220:             } else {
                   25221:                 $valpack = $chan->getValidationPackage();
                   25222:                 // for channel validator packages, always use the default PEAR validator.
                   25223:                 // otherwise, they can't be installed or packaged
                   25224:                 $validator = $chan->getValidationObject($this->_pf->getPackage());
                   25225:                 if (!$validator) {
                   25226:                     $this->_stack->push(__FUNCTION__, 'error',
                   25227:                         array('channel' => $chan->getName(),
                   25228:                               'package' => $this->_pf->getPackage(),
                   25229:                               'name'    => $valpack['_content'],
                   25230:                               'version' => $valpack['attribs']['version']),
                   25231:                         'package "%channel%/%package%" cannot be properly validated without ' .
                   25232:                         'validation package "%channel%/%name%-%version%"');
                   25233:                     return $this->_isValid = 0;
                   25234:                 }
                   25235:                 $validator->setPackageFile($this->_pf);
                   25236:                 $validator->validate($state);
                   25237:                 $failures = $validator->getFailures();
                   25238:                 foreach ($failures['errors'] as $error) {
                   25239:                     $this->_stack->push(__FUNCTION__, 'error', $error,
                   25240:                         'Channel validator error: field "%field%" - %reason%');
                   25241:                 }
                   25242:                 foreach ($failures['warnings'] as $warning) {
                   25243:                     $this->_stack->push(__FUNCTION__, 'warning', $warning,
                   25244:                         'Channel validator warning: field "%field%" - %reason%');
                   25245:                 }
                   25246:             }
                   25247:         }
                   25248: 
                   25249:         $this->_pf->_isValid = $this->_isValid = !$this->_stack->hasErrors('error');
                   25250:         if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$this->_filesValid) {
                   25251:             if ($this->_pf->getPackageType() == 'bundle') {
                   25252:                 if ($this->_analyzeBundledPackages()) {
                   25253:                     $this->_filesValid = $this->_pf->_filesValid = true;
                   25254:                 } else {
                   25255:                     $this->_pf->_isValid = $this->_isValid = 0;
                   25256:                 }
                   25257:             } else {
                   25258:                 if (!$this->_analyzePhpFiles()) {
                   25259:                     $this->_pf->_isValid = $this->_isValid = 0;
                   25260:                 } else {
                   25261:                     $this->_filesValid = $this->_pf->_filesValid = true;
                   25262:                 }
                   25263:             }
                   25264:         }
                   25265: 
                   25266:         if ($this->_isValid) {
                   25267:             return $this->_pf->_isValid = $this->_isValid = $state;
                   25268:         }
                   25269: 
                   25270:         return $this->_pf->_isValid = $this->_isValid = 0;
                   25271:     }
                   25272: 
                   25273:     function _stupidSchemaValidate($structure, $xml, $root)
                   25274:     {
                   25275:         if (!is_array($xml)) {
                   25276:             $xml = array();
                   25277:         }
                   25278:         $keys = array_keys($xml);
                   25279:         reset($keys);
                   25280:         $key = current($keys);
                   25281:         while ($key == 'attribs' || $key == '_contents') {
                   25282:             $key = next($keys);
                   25283:         }
                   25284:         $unfoundtags = $optionaltags = array();
                   25285:         $ret = true;
                   25286:         $mismatch = false;
                   25287:         foreach ($structure as $struc) {
                   25288:             if ($key) {
                   25289:                 $tag = $xml[$key];
                   25290:             }
                   25291:             $test = $this->_processStructure($struc);
                   25292:             if (isset($test['choices'])) {
                   25293:                 $loose = true;
                   25294:                 foreach ($test['choices'] as $choice) {
                   25295:                     if ($key == $choice['tag']) {
                   25296:                         $key = next($keys);
                   25297:                         while ($key == 'attribs' || $key == '_contents') {
                   25298:                             $key = next($keys);
                   25299:                         }
                   25300:                         $unfoundtags = $optionaltags = array();
                   25301:                         $mismatch = false;
                   25302:                         if ($key && $key != $choice['tag'] && isset($choice['multiple'])) {
                   25303:                             $unfoundtags[] = $choice['tag'];
                   25304:                             $optionaltags[] = $choice['tag'];
                   25305:                             if ($key) {
                   25306:                                 $mismatch = true;
                   25307:                             }
                   25308:                         }
                   25309:                         $ret &= $this->_processAttribs($choice, $tag, $root);
                   25310:                         continue 2;
                   25311:                     } else {
                   25312:                         $unfoundtags[] = $choice['tag'];
                   25313:                         $mismatch = true;
                   25314:                     }
                   25315:                     if (!isset($choice['multiple']) || $choice['multiple'] != '*') {
                   25316:                         $loose = false;
                   25317:                     } else {
                   25318:                         $optionaltags[] = $choice['tag'];
                   25319:                     }
                   25320:                 }
                   25321:                 if (!$loose) {
                   25322:                     $this->_invalidTagOrder($unfoundtags, $key, $root);
                   25323:                     return false;
                   25324:                 }
                   25325:             } else {
                   25326:                 if ($key != $test['tag']) {
                   25327:                     if (isset($test['multiple']) && $test['multiple'] != '*') {
                   25328:                         $unfoundtags[] = $test['tag'];
                   25329:                         $this->_invalidTagOrder($unfoundtags, $key, $root);
                   25330:                         return false;
                   25331:                     } else {
                   25332:                         if ($key) {
                   25333:                             $mismatch = true;
                   25334:                         }
                   25335:                         $unfoundtags[] = $test['tag'];
                   25336:                         $optionaltags[] = $test['tag'];
                   25337:                     }
                   25338:                     if (!isset($test['multiple'])) {
                   25339:                         $this->_invalidTagOrder($unfoundtags, $key, $root);
                   25340:                         return false;
                   25341:                     }
                   25342:                     continue;
                   25343:                 } else {
                   25344:                     $unfoundtags = $optionaltags = array();
                   25345:                     $mismatch = false;
                   25346:                 }
                   25347:                 $key = next($keys);
                   25348:                 while ($key == 'attribs' || $key == '_contents') {
                   25349:                     $key = next($keys);
                   25350:                 }
                   25351:                 if ($key && $key != $test['tag'] && isset($test['multiple'])) {
                   25352:                     $unfoundtags[] = $test['tag'];
                   25353:                     $optionaltags[] = $test['tag'];
                   25354:                     $mismatch = true;
                   25355:                 }
                   25356:                 $ret &= $this->_processAttribs($test, $tag, $root);
                   25357:                 continue;
                   25358:             }
                   25359:         }
                   25360:         if (!$mismatch && count($optionaltags)) {
                   25361:             // don't error out on any optional tags
                   25362:             $unfoundtags = array_diff($unfoundtags, $optionaltags);
                   25363:         }
                   25364:         if (count($unfoundtags)) {
                   25365:             $this->_invalidTagOrder($unfoundtags, $key, $root);
                   25366:         } elseif ($key) {
                   25367:             // unknown tags
                   25368:             $this->_invalidTagOrder('*no tags allowed here*', $key, $root);
                   25369:             while ($key = next($keys)) {
                   25370:                 $this->_invalidTagOrder('*no tags allowed here*', $key, $root);
                   25371:             }
                   25372:         }
                   25373:         return $ret;
                   25374:     }
                   25375: 
                   25376:     function _processAttribs($choice, $tag, $context)
                   25377:     {
                   25378:         if (isset($choice['attribs'])) {
                   25379:             if (!is_array($tag)) {
                   25380:                 $tag = array($tag);
                   25381:             }
                   25382:             $tags = $tag;
                   25383:             if (!isset($tags[0])) {
                   25384:                 $tags = array($tags);
                   25385:             }
                   25386:             $ret = true;
                   25387:             foreach ($tags as $i => $tag) {
                   25388:                 if (!is_array($tag) || !isset($tag['attribs'])) {
                   25389:                     foreach ($choice['attribs'] as $attrib) {
                   25390:                         if ($attrib{0} != '?') {
                   25391:                             $ret &= $this->_tagHasNoAttribs($choice['tag'],
                   25392:                                 $context);
                   25393:                             continue 2;
                   25394:                         }
                   25395:                     }
                   25396:                 }
                   25397:                 foreach ($choice['attribs'] as $attrib) {
                   25398:                     if ($attrib{0} != '?') {
                   25399:                         if (!isset($tag['attribs'][$attrib])) {
                   25400:                             $ret &= $this->_tagMissingAttribute($choice['tag'],
                   25401:                                 $attrib, $context);
                   25402:                         }
                   25403:                     }
                   25404:                 }
                   25405:             }
                   25406:             return $ret;
                   25407:         }
                   25408:         return true;
                   25409:     }
                   25410: 
                   25411:     function _processStructure($key)
                   25412:     {
                   25413:         $ret = array();
                   25414:         if (count($pieces = explode('|', $key)) > 1) {
                   25415:             $ret['choices'] = array();
                   25416:             foreach ($pieces as $piece) {
                   25417:                 $ret['choices'][] = $this->_processStructure($piece);
                   25418:             }
                   25419:             return $ret;
                   25420:         }
                   25421:         $multi = $key{0};
                   25422:         if ($multi == '+' || $multi == '*') {
                   25423:             $ret['multiple'] = $key{0};
                   25424:             $key = substr($key, 1);
                   25425:         }
                   25426:         if (count($attrs = explode('->', $key)) > 1) {
                   25427:             $ret['tag'] = array_shift($attrs);
                   25428:             $ret['attribs'] = $attrs;
                   25429:         } else {
                   25430:             $ret['tag'] = $key;
                   25431:         }
                   25432:         return $ret;
                   25433:     }
                   25434: 
                   25435:     function _validateStabilityVersion()
                   25436:     {
                   25437:         $structure = array('release', 'api');
                   25438:         $a = $this->_stupidSchemaValidate($structure, $this->_packageInfo['version'], '<version>');
                   25439:         $a &= $this->_stupidSchemaValidate($structure, $this->_packageInfo['stability'], '<stability>');
                   25440:         if ($a) {
                   25441:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25442:                   $this->_packageInfo['version']['release'])) {
                   25443:                 $this->_invalidVersion('release', $this->_packageInfo['version']['release']);
                   25444:             }
                   25445:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25446:                   $this->_packageInfo['version']['api'])) {
                   25447:                 $this->_invalidVersion('api', $this->_packageInfo['version']['api']);
                   25448:             }
                   25449:             if (!in_array($this->_packageInfo['stability']['release'],
                   25450:                   array('snapshot', 'devel', 'alpha', 'beta', 'stable'))) {
                   25451:                 $this->_invalidState('release', $this->_packageInfo['stability']['release']);
                   25452:             }
                   25453:             if (!in_array($this->_packageInfo['stability']['api'],
                   25454:                   array('devel', 'alpha', 'beta', 'stable'))) {
                   25455:                 $this->_invalidState('api', $this->_packageInfo['stability']['api']);
                   25456:             }
                   25457:         }
                   25458:     }
                   25459: 
                   25460:     function _validateMaintainers()
                   25461:     {
                   25462:         $structure =
                   25463:             array(
                   25464:                 'name',
                   25465:                 'user',
                   25466:                 'email',
                   25467:                 'active',
                   25468:             );
                   25469:         foreach (array('lead', 'developer', 'contributor', 'helper') as $type) {
                   25470:             if (!isset($this->_packageInfo[$type])) {
                   25471:                 continue;
                   25472:             }
                   25473:             if (isset($this->_packageInfo[$type][0])) {
                   25474:                 foreach ($this->_packageInfo[$type] as $lead) {
                   25475:                     $this->_stupidSchemaValidate($structure, $lead, '<' . $type . '>');
                   25476:                 }
                   25477:             } else {
                   25478:                 $this->_stupidSchemaValidate($structure, $this->_packageInfo[$type],
                   25479:                     '<' . $type . '>');
                   25480:             }
                   25481:         }
                   25482:     }
                   25483: 
                   25484:     function _validatePhpDep($dep, $installcondition = false)
                   25485:     {
                   25486:         $structure = array(
                   25487:             'min',
                   25488:             '*max',
                   25489:             '*exclude',
                   25490:         );
                   25491:         $type = $installcondition ? '<installcondition><php>' : '<dependencies><required><php>';
                   25492:         $this->_stupidSchemaValidate($structure, $dep, $type);
                   25493:         if (isset($dep['min'])) {
                   25494:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
                   25495:                   $dep['min'])) {
                   25496:                 $this->_invalidVersion($type . '<min>', $dep['min']);
                   25497:             }
                   25498:         }
                   25499:         if (isset($dep['max'])) {
                   25500:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
                   25501:                   $dep['max'])) {
                   25502:                 $this->_invalidVersion($type . '<max>', $dep['max']);
                   25503:             }
                   25504:         }
                   25505:         if (isset($dep['exclude'])) {
                   25506:             if (!is_array($dep['exclude'])) {
                   25507:                 $dep['exclude'] = array($dep['exclude']);
                   25508:             }
                   25509:             foreach ($dep['exclude'] as $exclude) {
                   25510:                 if (!preg_match(
                   25511:                      '/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
                   25512:                      $exclude)) {
                   25513:                     $this->_invalidVersion($type . '<exclude>', $exclude);
                   25514:                 }
                   25515:             }
                   25516:         }
                   25517:     }
                   25518: 
                   25519:     function _validatePearinstallerDep($dep)
                   25520:     {
                   25521:         $structure = array(
                   25522:             'min',
                   25523:             '*max',
                   25524:             '*recommended',
                   25525:             '*exclude',
                   25526:         );
                   25527:         $this->_stupidSchemaValidate($structure, $dep, '<dependencies><required><pearinstaller>');
                   25528:         if (isset($dep['min'])) {
                   25529:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25530:                   $dep['min'])) {
                   25531:                 $this->_invalidVersion('<dependencies><required><pearinstaller><min>',
                   25532:                     $dep['min']);
                   25533:             }
                   25534:         }
                   25535:         if (isset($dep['max'])) {
                   25536:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25537:                   $dep['max'])) {
                   25538:                 $this->_invalidVersion('<dependencies><required><pearinstaller><max>',
                   25539:                     $dep['max']);
                   25540:             }
                   25541:         }
                   25542:         if (isset($dep['recommended'])) {
                   25543:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25544:                   $dep['recommended'])) {
                   25545:                 $this->_invalidVersion('<dependencies><required><pearinstaller><recommended>',
                   25546:                     $dep['recommended']);
                   25547:             }
                   25548:         }
                   25549:         if (isset($dep['exclude'])) {
                   25550:             if (!is_array($dep['exclude'])) {
                   25551:                 $dep['exclude'] = array($dep['exclude']);
                   25552:             }
                   25553:             foreach ($dep['exclude'] as $exclude) {
                   25554:                 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25555:                       $exclude)) {
                   25556:                     $this->_invalidVersion('<dependencies><required><pearinstaller><exclude>',
                   25557:                         $exclude);
                   25558:                 }
                   25559:             }
                   25560:         }
                   25561:     }
                   25562: 
                   25563:     function _validatePackageDep($dep, $group, $type = '<package>')
                   25564:     {
                   25565:         if (isset($dep['uri'])) {
                   25566:             if (isset($dep['conflicts'])) {
                   25567:                 $structure = array(
                   25568:                     'name',
                   25569:                     'uri',
                   25570:                     'conflicts',
                   25571:                     '*providesextension',
                   25572:                 );
                   25573:             } else {
                   25574:                 $structure = array(
                   25575:                     'name',
                   25576:                     'uri',
                   25577:                     '*providesextension',
                   25578:                 );
                   25579:             }
                   25580:         } else {
                   25581:             if (isset($dep['conflicts'])) {
                   25582:                 $structure = array(
                   25583:                     'name',
                   25584:                     'channel',
                   25585:                     '*min',
                   25586:                     '*max',
                   25587:                     '*exclude',
                   25588:                     'conflicts',
                   25589:                     '*providesextension',
                   25590:                 );
                   25591:             } else {
                   25592:                 $structure = array(
                   25593:                     'name',
                   25594:                     'channel',
                   25595:                     '*min',
                   25596:                     '*max',
                   25597:                     '*recommended',
                   25598:                     '*exclude',
                   25599:                     '*nodefault',
                   25600:                     '*providesextension',
                   25601:                 );
                   25602:             }
                   25603:         }
                   25604:         if (isset($dep['name'])) {
                   25605:             $type .= '<name>' . $dep['name'] . '</name>';
                   25606:         }
                   25607:         $this->_stupidSchemaValidate($structure, $dep, '<dependencies>' . $group . $type);
                   25608:         if (isset($dep['uri']) && (isset($dep['min']) || isset($dep['max']) ||
                   25609:               isset($dep['recommended']) || isset($dep['exclude']))) {
                   25610:             $this->_uriDepsCannotHaveVersioning('<dependencies>' . $group . $type);
                   25611:         }
                   25612:         if (isset($dep['channel']) && strtolower($dep['channel']) == '__uri') {
                   25613:             $this->_DepchannelCannotBeUri('<dependencies>' . $group . $type);
                   25614:         }
                   25615:         if (isset($dep['min'])) {
                   25616:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25617:                   $dep['min'])) {
                   25618:                 $this->_invalidVersion('<dependencies>' . $group . $type . '<min>', $dep['min']);
                   25619:             }
                   25620:         }
                   25621:         if (isset($dep['max'])) {
                   25622:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25623:                   $dep['max'])) {
                   25624:                 $this->_invalidVersion('<dependencies>' . $group . $type . '<max>', $dep['max']);
                   25625:             }
                   25626:         }
                   25627:         if (isset($dep['recommended'])) {
                   25628:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25629:                   $dep['recommended'])) {
                   25630:                 $this->_invalidVersion('<dependencies>' . $group . $type . '<recommended>',
                   25631:                     $dep['recommended']);
                   25632:             }
                   25633:         }
                   25634:         if (isset($dep['exclude'])) {
                   25635:             if (!is_array($dep['exclude'])) {
                   25636:                 $dep['exclude'] = array($dep['exclude']);
                   25637:             }
                   25638:             foreach ($dep['exclude'] as $exclude) {
                   25639:                 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25640:                       $exclude)) {
                   25641:                     $this->_invalidVersion('<dependencies>' . $group . $type . '<exclude>',
                   25642:                         $exclude);
                   25643:                 }
                   25644:             }
                   25645:         }
                   25646:     }
                   25647: 
                   25648:     function _validateSubpackageDep($dep, $group)
                   25649:     {
                   25650:         $this->_validatePackageDep($dep, $group, '<subpackage>');
                   25651:         if (isset($dep['providesextension'])) {
                   25652:             $this->_subpackageCannotProvideExtension(isset($dep['name']) ? $dep['name'] : '');
                   25653:         }
                   25654:         if (isset($dep['conflicts'])) {
                   25655:             $this->_subpackagesCannotConflict(isset($dep['name']) ? $dep['name'] : '');
                   25656:         }
                   25657:     }
                   25658: 
                   25659:     function _validateExtensionDep($dep, $group = false, $installcondition = false)
                   25660:     {
                   25661:         if (isset($dep['conflicts'])) {
                   25662:             $structure = array(
                   25663:                 'name',
                   25664:                 '*min',
                   25665:                 '*max',
                   25666:                 '*exclude',
                   25667:                 'conflicts',
                   25668:             );
                   25669:         } else {
                   25670:             $structure = array(
                   25671:                 'name',
                   25672:                 '*min',
                   25673:                 '*max',
                   25674:                 '*recommended',
                   25675:                 '*exclude',
                   25676:             );
                   25677:         }
                   25678:         if ($installcondition) {
                   25679:             $type = '<installcondition><extension>';
                   25680:         } else {
                   25681:             $type = '<dependencies>' . $group . '<extension>';
                   25682:         }
                   25683:         if (isset($dep['name'])) {
                   25684:             $type .= '<name>' . $dep['name'] . '</name>';
                   25685:         }
                   25686:         $this->_stupidSchemaValidate($structure, $dep, $type);
                   25687:         if (isset($dep['min'])) {
                   25688:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25689:                   $dep['min'])) {
                   25690:                 $this->_invalidVersion(substr($type, 1) . '<min', $dep['min']);
                   25691:             }
                   25692:         }
                   25693:         if (isset($dep['max'])) {
                   25694:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25695:                   $dep['max'])) {
                   25696:                 $this->_invalidVersion(substr($type, 1) . '<max', $dep['max']);
                   25697:             }
                   25698:         }
                   25699:         if (isset($dep['recommended'])) {
                   25700:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25701:                   $dep['recommended'])) {
                   25702:                 $this->_invalidVersion(substr($type, 1) . '<recommended', $dep['recommended']);
                   25703:             }
                   25704:         }
                   25705:         if (isset($dep['exclude'])) {
                   25706:             if (!is_array($dep['exclude'])) {
                   25707:                 $dep['exclude'] = array($dep['exclude']);
                   25708:             }
                   25709:             foreach ($dep['exclude'] as $exclude) {
                   25710:                 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25711:                       $exclude)) {
                   25712:                     $this->_invalidVersion(substr($type, 1) . '<exclude', $exclude);
                   25713:                 }
                   25714:             }
                   25715:         }
                   25716:     }
                   25717: 
                   25718:     function _validateOsDep($dep, $installcondition = false)
                   25719:     {
                   25720:         $structure = array(
                   25721:             'name',
                   25722:             '*conflicts',
                   25723:         );
                   25724:         $type = $installcondition ? '<installcondition><os>' : '<dependencies><required><os>';
                   25725:         if ($this->_stupidSchemaValidate($structure, $dep, $type)) {
                   25726:             if ($dep['name'] == '*') {
                   25727:                 if (array_key_exists('conflicts', $dep)) {
                   25728:                     $this->_cannotConflictWithAllOs($type);
                   25729:                 }
                   25730:             }
                   25731:         }
                   25732:     }
                   25733: 
                   25734:     function _validateArchDep($dep, $installcondition = false)
                   25735:     {
                   25736:         $structure = array(
                   25737:             'pattern',
                   25738:             '*conflicts',
                   25739:         );
                   25740:         $type = $installcondition ? '<installcondition><arch>' : '<dependencies><required><arch>';
                   25741:         $this->_stupidSchemaValidate($structure, $dep, $type);
                   25742:     }
                   25743: 
                   25744:     function _validateInstallConditions($cond, $release)
                   25745:     {
                   25746:         $structure = array(
                   25747:             '*php',
                   25748:             '*extension',
                   25749:             '*os',
                   25750:             '*arch',
                   25751:         );
                   25752:         if (!$this->_stupidSchemaValidate($structure,
                   25753:               $cond, $release)) {
                   25754:             return false;
                   25755:         }
                   25756:         foreach (array('php', 'extension', 'os', 'arch') as $type) {
                   25757:             if (isset($cond[$type])) {
                   25758:                 $iter = $cond[$type];
                   25759:                 if (!is_array($iter) || !isset($iter[0])) {
                   25760:                     $iter = array($iter);
                   25761:                 }
                   25762:                 foreach ($iter as $package) {
                   25763:                     if ($type == 'extension') {
                   25764:                         $this->{"_validate{$type}Dep"}($package, false, true);
                   25765:                     } else {
                   25766:                         $this->{"_validate{$type}Dep"}($package, true);
                   25767:                     }
                   25768:                 }
                   25769:             }
                   25770:         }
                   25771:     }
                   25772: 
                   25773:     function _validateDependencies()
                   25774:     {
                   25775:         $structure = array(
                   25776:             'required',
                   25777:             '*optional',
                   25778:             '*group->name->hint'
                   25779:         );
                   25780:         if (!$this->_stupidSchemaValidate($structure,
                   25781:               $this->_packageInfo['dependencies'], '<dependencies>')) {
                   25782:             return false;
                   25783:         }
                   25784:         foreach (array('required', 'optional') as $simpledep) {
                   25785:             if (isset($this->_packageInfo['dependencies'][$simpledep])) {
                   25786:                 if ($simpledep == 'optional') {
                   25787:                     $structure = array(
                   25788:                         '*package',
                   25789:                         '*subpackage',
                   25790:                         '*extension',
                   25791:                     );
                   25792:                 } else {
                   25793:                     $structure = array(
                   25794:                         'php',
                   25795:                         'pearinstaller',
                   25796:                         '*package',
                   25797:                         '*subpackage',
                   25798:                         '*extension',
                   25799:                         '*os',
                   25800:                         '*arch',
                   25801:                     );
                   25802:                 }
                   25803:                 if ($this->_stupidSchemaValidate($structure,
                   25804:                       $this->_packageInfo['dependencies'][$simpledep],
                   25805:                       "<dependencies><$simpledep>")) {
                   25806:                     foreach (array('package', 'subpackage', 'extension') as $type) {
                   25807:                         if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) {
                   25808:                             $iter = $this->_packageInfo['dependencies'][$simpledep][$type];
                   25809:                             if (!isset($iter[0])) {
                   25810:                                 $iter = array($iter);
                   25811:                             }
                   25812:                             foreach ($iter as $package) {
                   25813:                                 if ($type != 'extension') {
                   25814:                                     if (isset($package['uri'])) {
                   25815:                                         if (isset($package['channel'])) {
                   25816:                                             $this->_UrlOrChannel($type,
                   25817:                                                 $package['name']);
                   25818:                                         }
                   25819:                                     } else {
                   25820:                                         if (!isset($package['channel'])) {
                   25821:                                             $this->_NoChannel($type, $package['name']);
                   25822:                                         }
                   25823:                                     }
                   25824:                                 }
                   25825:                                 $this->{"_validate{$type}Dep"}($package, "<$simpledep>");
                   25826:                             }
                   25827:                         }
                   25828:                     }
                   25829:                     if ($simpledep == 'optional') {
                   25830:                         continue;
                   25831:                     }
                   25832:                     foreach (array('php', 'pearinstaller', 'os', 'arch') as $type) {
                   25833:                         if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) {
                   25834:                             $iter = $this->_packageInfo['dependencies'][$simpledep][$type];
                   25835:                             if (!isset($iter[0])) {
                   25836:                                 $iter = array($iter);
                   25837:                             }
                   25838:                             foreach ($iter as $package) {
                   25839:                                 $this->{"_validate{$type}Dep"}($package);
                   25840:                             }
                   25841:                         }
                   25842:                     }
                   25843:                 }
                   25844:             }
                   25845:         }
                   25846:         if (isset($this->_packageInfo['dependencies']['group'])) {
                   25847:             $groups = $this->_packageInfo['dependencies']['group'];
                   25848:             if (!isset($groups[0])) {
                   25849:                 $groups = array($groups);
                   25850:             }
                   25851:             $structure = array(
                   25852:                 '*package',
                   25853:                 '*subpackage',
                   25854:                 '*extension',
                   25855:             );
                   25856:             foreach ($groups as $group) {
                   25857:                 if ($this->_stupidSchemaValidate($structure, $group, '<group>')) {
                   25858:                     if (!PEAR_Validate::validGroupName($group['attribs']['name'])) {
                   25859:                         $this->_invalidDepGroupName($group['attribs']['name']);
                   25860:                     }
                   25861:                     foreach (array('package', 'subpackage', 'extension') as $type) {
                   25862:                         if (isset($group[$type])) {
                   25863:                             $iter = $group[$type];
                   25864:                             if (!isset($iter[0])) {
                   25865:                                 $iter = array($iter);
                   25866:                             }
                   25867:                             foreach ($iter as $package) {
                   25868:                                 if ($type != 'extension') {
                   25869:                                     if (isset($package['uri'])) {
                   25870:                                         if (isset($package['channel'])) {
                   25871:                                             $this->_UrlOrChannelGroup($type,
                   25872:                                                 $package['name'],
                   25873:                                                 $group['name']);
                   25874:                                         }
                   25875:                                     } else {
                   25876:                                         if (!isset($package['channel'])) {
                   25877:                                             $this->_NoChannelGroup($type,
                   25878:                                                 $package['name'],
                   25879:                                                 $group['name']);
                   25880:                                         }
                   25881:                                     }
                   25882:                                 }
                   25883:                                 $this->{"_validate{$type}Dep"}($package, '<group name="' .
                   25884:                                     $group['attribs']['name'] . '">');
                   25885:                             }
                   25886:                         }
                   25887:                     }
                   25888:                 }
                   25889:             }
                   25890:         }
                   25891:     }
                   25892: 
                   25893:     function _validateCompatible()
                   25894:     {
                   25895:         $compat = $this->_packageInfo['compatible'];
                   25896:         if (!isset($compat[0])) {
                   25897:             $compat = array($compat);
                   25898:         }
                   25899:         $required = array('name', 'channel', 'min', 'max', '*exclude');
                   25900:         foreach ($compat as $package) {
                   25901:             $type = '<compatible>';
                   25902:             if (is_array($package) && array_key_exists('name', $package)) {
                   25903:                 $type .= '<name>' . $package['name'] . '</name>';
                   25904:             }
                   25905:             $this->_stupidSchemaValidate($required, $package, $type);
                   25906:             if (is_array($package) && array_key_exists('min', $package)) {
                   25907:                 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25908:                       $package['min'])) {
                   25909:                     $this->_invalidVersion(substr($type, 1) . '<min', $package['min']);
                   25910:                 }
                   25911:             }
                   25912:             if (is_array($package) && array_key_exists('max', $package)) {
                   25913:                 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25914:                       $package['max'])) {
                   25915:                     $this->_invalidVersion(substr($type, 1) . '<max', $package['max']);
                   25916:                 }
                   25917:             }
                   25918:             if (is_array($package) && array_key_exists('exclude', $package)) {
                   25919:                 if (!is_array($package['exclude'])) {
                   25920:                     $package['exclude'] = array($package['exclude']);
                   25921:                 }
                   25922:                 foreach ($package['exclude'] as $exclude) {
                   25923:                     if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
                   25924:                           $exclude)) {
                   25925:                         $this->_invalidVersion(substr($type, 1) . '<exclude', $exclude);
                   25926:                     }
                   25927:                 }
                   25928:             }
                   25929:         }
                   25930:     }
                   25931: 
                   25932:     function _validateBundle($list)
                   25933:     {
                   25934:         if (!is_array($list) || !isset($list['bundledpackage'])) {
                   25935:             return $this->_NoBundledPackages();
                   25936:         }
                   25937:         if (!is_array($list['bundledpackage']) || !isset($list['bundledpackage'][0])) {
                   25938:             return $this->_AtLeast2BundledPackages();
                   25939:         }
                   25940:         foreach ($list['bundledpackage'] as $package) {
                   25941:             if (!is_string($package)) {
                   25942:                 $this->_bundledPackagesMustBeFilename();
                   25943:             }
                   25944:         }
                   25945:     }
                   25946: 
                   25947:     function _validateFilelist($list = false, $allowignore = false, $dirs = '')
                   25948:     {
                   25949:         $iscontents = false;
                   25950:         if (!$list) {
                   25951:             $iscontents = true;
                   25952:             $list = $this->_packageInfo['contents'];
                   25953:             if (isset($this->_packageInfo['bundle'])) {
                   25954:                 return $this->_validateBundle($list);
                   25955:             }
                   25956:         }
                   25957:         if ($allowignore) {
                   25958:             $struc = array(
                   25959:                 '*install->name->as',
                   25960:                 '*ignore->name'
                   25961:             );
                   25962:         } else {
                   25963:             $struc = array(
                   25964:                 '*dir->name->?baseinstalldir',
                   25965:                 '*file->name->role->?baseinstalldir->?md5sum'
                   25966:             );
                   25967:             if (isset($list['dir']) && isset($list['file'])) {
                   25968:                 // stave off validation errors without requiring a set order.
                   25969:                 $_old = $list;
                   25970:                 if (isset($list['attribs'])) {
                   25971:                     $list = array('attribs' => $_old['attribs']);
                   25972:                 }
                   25973:                 $list['dir'] = $_old['dir'];
                   25974:                 $list['file'] = $_old['file'];
                   25975:             }
                   25976:         }
                   25977:         if (!isset($list['attribs']) || !isset($list['attribs']['name'])) {
                   25978:             $unknown = $allowignore ? '<filelist>' : '<dir name="*unknown*">';
                   25979:             $dirname = $iscontents ? '<contents>' : $unknown;
                   25980:         } else {
                   25981:             $dirname = '<dir name="' . $list['attribs']['name'] . '">';
                   25982:             if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
                   25983:                           str_replace('\\', '/', $list['attribs']['name']))) {
                   25984:                 // file contains .. parent directory or . cur directory
                   25985:                 $this->_invalidDirName($list['attribs']['name']);
                   25986:             }
                   25987:         }
                   25988:         $res = $this->_stupidSchemaValidate($struc, $list, $dirname);
                   25989:         if ($allowignore && $res) {
                   25990:             $ignored_or_installed = array();
                   25991:             $this->_pf->getFilelist();
                   25992:             $fcontents = $this->_pf->getContents();
                   25993:             $filelist = array();
                   25994:             if (!isset($fcontents['dir']['file'][0])) {
                   25995:                 $fcontents['dir']['file'] = array($fcontents['dir']['file']);
                   25996:             }
                   25997:             foreach ($fcontents['dir']['file'] as $file) {
                   25998:                 $filelist[$file['attribs']['name']] = true;
                   25999:             }
                   26000:             if (isset($list['install'])) {
                   26001:                 if (!isset($list['install'][0])) {
                   26002:                     $list['install'] = array($list['install']);
                   26003:                 }
                   26004:                 foreach ($list['install'] as $file) {
                   26005:                     if (!isset($filelist[$file['attribs']['name']])) {
                   26006:                         $this->_notInContents($file['attribs']['name'], 'install');
                   26007:                         continue;
                   26008:                     }
                   26009:                     if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
                   26010:                         $this->_multipleInstallAs($file['attribs']['name']);
                   26011:                     }
                   26012:                     if (!isset($ignored_or_installed[$file['attribs']['name']])) {
                   26013:                         $ignored_or_installed[$file['attribs']['name']] = array();
                   26014:                     }
                   26015:                     $ignored_or_installed[$file['attribs']['name']][] = 1;
                   26016:                     if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
                   26017:                                   str_replace('\\', '/', $file['attribs']['as']))) {
                   26018:                         // file contains .. parent directory or . cur directory references
                   26019:                         $this->_invalidFileInstallAs($file['attribs']['name'],
                   26020:                             $file['attribs']['as']);
                   26021:                     }
                   26022:                 }
                   26023:             }
                   26024:             if (isset($list['ignore'])) {
                   26025:                 if (!isset($list['ignore'][0])) {
                   26026:                     $list['ignore'] = array($list['ignore']);
                   26027:                 }
                   26028:                 foreach ($list['ignore'] as $file) {
                   26029:                     if (!isset($filelist[$file['attribs']['name']])) {
                   26030:                         $this->_notInContents($file['attribs']['name'], 'ignore');
                   26031:                         continue;
                   26032:                     }
                   26033:                     if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
                   26034:                         $this->_ignoreAndInstallAs($file['attribs']['name']);
                   26035:                     }
                   26036:                 }
                   26037:             }
                   26038:         }
                   26039:         if (!$allowignore && isset($list['file'])) {
                   26040:             if (is_string($list['file'])) {
                   26041:                 $this->_oldStyleFileNotAllowed();
                   26042:                 return false;
                   26043:             }
                   26044:             if (!isset($list['file'][0])) {
                   26045:                 // single file
                   26046:                 $list['file'] = array($list['file']);
                   26047:             }
                   26048:             foreach ($list['file'] as $i => $file)
                   26049:             {
                   26050:                 if (isset($file['attribs']) && isset($file['attribs']['name'])) {
                   26051:                     if ($file['attribs']['name']{0} == '.' &&
                   26052:                           $file['attribs']['name']{1} == '/') {
                   26053:                         // name is something like "./doc/whatever.txt"
                   26054:                         $this->_invalidFileName($file['attribs']['name'], $dirname);
                   26055:                     }
                   26056:                     if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
                   26057:                                   str_replace('\\', '/', $file['attribs']['name']))) {
                   26058:                         // file contains .. parent directory or . cur directory
                   26059:                         $this->_invalidFileName($file['attribs']['name'], $dirname);
                   26060:                     }
                   26061:                 }
                   26062:                 if (isset($file['attribs']) && isset($file['attribs']['role'])) {
                   26063:                     if (!$this->_validateRole($file['attribs']['role'])) {
                   26064:                         if (isset($this->_packageInfo['usesrole'])) {
                   26065:                             $roles = $this->_packageInfo['usesrole'];
                   26066:                             if (!isset($roles[0])) {
                   26067:                                 $roles = array($roles);
                   26068:                             }
                   26069:                             foreach ($roles as $role) {
                   26070:                                 if ($role['role'] = $file['attribs']['role']) {
                   26071:                                     $msg = 'This package contains role "%role%" and requires ' .
                   26072:                                         'package "%package%" to be used';
                   26073:                                     if (isset($role['uri'])) {
                   26074:                                         $params = array('role' => $role['role'],
                   26075:                                             'package' => $role['uri']);
                   26076:                                     } else {
                   26077:                                         $params = array('role' => $role['role'],
                   26078:                                             'package' => $this->_pf->_registry->
                   26079:                                             parsedPackageNameToString(array('package' =>
                   26080:                                                 $role['package'], 'channel' => $role['channel']),
                   26081:                                                 true));
                   26082:                                     }
                   26083:                                     $this->_stack->push('_mustInstallRole', 'error', $params, $msg);
                   26084:                                 }
                   26085:                             }
                   26086:                         }
                   26087:                         $this->_invalidFileRole($file['attribs']['name'],
                   26088:                             $dirname, $file['attribs']['role']);
                   26089:                     }
                   26090:                 }
                   26091:                 if (!isset($file['attribs'])) {
                   26092:                     continue;
                   26093:                 }
                   26094:                 $save = $file['attribs'];
                   26095:                 if ($dirs) {
                   26096:                     $save['name'] = $dirs . '/' . $save['name'];
                   26097:                 }
                   26098:                 unset($file['attribs']);
                   26099:                 if (count($file) && $this->_curState != PEAR_VALIDATE_DOWNLOADING) { // has tasks
                   26100:                     foreach ($file as $task => $value) {
                   26101:                         if ($tagClass = $this->_pf->getTask($task)) {
                   26102:                             if (!is_array($value) || !isset($value[0])) {
                   26103:                                 $value = array($value);
                   26104:                             }
                   26105:                             foreach ($value as $v) {
                   26106:                                 $ret = call_user_func(array($tagClass, 'validateXml'),
                   26107:                                     $this->_pf, $v, $this->_pf->_config, $save);
                   26108:                                 if (is_array($ret)) {
                   26109:                                     $this->_invalidTask($task, $ret, isset($save['name']) ?
                   26110:                                         $save['name'] : '');
                   26111:                                 }
                   26112:                             }
                   26113:                         } else {
                   26114:                             if (isset($this->_packageInfo['usestask'])) {
                   26115:                                 $roles = $this->_packageInfo['usestask'];
                   26116:                                 if (!isset($roles[0])) {
                   26117:                                     $roles = array($roles);
                   26118:                                 }
                   26119:                                 foreach ($roles as $role) {
                   26120:                                     if ($role['task'] = $task) {
                   26121:                                         $msg = 'This package contains task "%task%" and requires ' .
                   26122:                                             'package "%package%" to be used';
                   26123:                                         if (isset($role['uri'])) {
                   26124:                                             $params = array('task' => $role['task'],
                   26125:                                                 'package' => $role['uri']);
                   26126:                                         } else {
                   26127:                                             $params = array('task' => $role['task'],
                   26128:                                                 'package' => $this->_pf->_registry->
                   26129:                                                 parsedPackageNameToString(array('package' =>
                   26130:                                                     $role['package'], 'channel' => $role['channel']),
                   26131:                                                     true));
                   26132:                                         }
                   26133:                                         $this->_stack->push('_mustInstallTask', 'error',
                   26134:                                             $params, $msg);
                   26135:                                     }
                   26136:                                 }
                   26137:                             }
                   26138:                             $this->_unknownTask($task, $save['name']);
                   26139:                         }
                   26140:                     }
                   26141:                 }
                   26142:             }
                   26143:         }
                   26144:         if (isset($list['ignore'])) {
                   26145:             if (!$allowignore) {
                   26146:                 $this->_ignoreNotAllowed('ignore');
                   26147:             }
                   26148:         }
                   26149:         if (isset($list['install'])) {
                   26150:             if (!$allowignore) {
                   26151:                 $this->_ignoreNotAllowed('install');
                   26152:             }
                   26153:         }
                   26154:         if (isset($list['file'])) {
                   26155:             if ($allowignore) {
                   26156:                 $this->_fileNotAllowed('file');
                   26157:             }
                   26158:         }
                   26159:         if (isset($list['dir'])) {
                   26160:             if ($allowignore) {
                   26161:                 $this->_fileNotAllowed('dir');
                   26162:             } else {
                   26163:                 if (!isset($list['dir'][0])) {
                   26164:                     $list['dir'] = array($list['dir']);
                   26165:                 }
                   26166:                 foreach ($list['dir'] as $dir) {
                   26167:                     if (isset($dir['attribs']) && isset($dir['attribs']['name'])) {
                   26168:                         if ($dir['attribs']['name'] == '/' ||
                   26169:                               !isset($this->_packageInfo['contents']['dir']['dir'])) {
                   26170:                             // always use nothing if the filelist has already been flattened
                   26171:                             $newdirs = '';
                   26172:                         } elseif ($dirs == '') {
                   26173:                             $newdirs = $dir['attribs']['name'];
                   26174:                         } else {
                   26175:                             $newdirs = $dirs . '/' . $dir['attribs']['name'];
                   26176:                         }
                   26177:                     } else {
                   26178:                         $newdirs = $dirs;
                   26179:                     }
                   26180:                     $this->_validateFilelist($dir, $allowignore, $newdirs);
                   26181:                 }
                   26182:             }
                   26183:         }
                   26184:     }
                   26185: 
                   26186:     function _validateRelease()
                   26187:     {
                   26188:         if (isset($this->_packageInfo['phprelease'])) {
                   26189:             $release = 'phprelease';
                   26190:             if (isset($this->_packageInfo['providesextension'])) {
                   26191:                 $this->_cannotProvideExtension($release);
                   26192:             }
                   26193:             if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
                   26194:                 $this->_cannotHaveSrcpackage($release);
                   26195:             }
                   26196:             $releases = $this->_packageInfo['phprelease'];
                   26197:             if (!is_array($releases)) {
                   26198:                 return true;
                   26199:             }
                   26200:             if (!isset($releases[0])) {
                   26201:                 $releases = array($releases);
                   26202:             }
                   26203:             foreach ($releases as $rel) {
                   26204:                 $this->_stupidSchemaValidate(array(
                   26205:                     '*installconditions',
                   26206:                     '*filelist',
                   26207:                 ), $rel, '<phprelease>');
                   26208:             }
                   26209:         }
                   26210:         foreach (array('', 'zend') as $prefix) {
                   26211:             $releasetype = $prefix . 'extsrcrelease';
                   26212:             if (isset($this->_packageInfo[$releasetype])) {
                   26213:                 $release = $releasetype;
                   26214:                 if (!isset($this->_packageInfo['providesextension'])) {
                   26215:                     $this->_mustProvideExtension($release);
                   26216:                 }
                   26217:                 if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
                   26218:                     $this->_cannotHaveSrcpackage($release);
                   26219:                 }
                   26220:                 $releases = $this->_packageInfo[$releasetype];
                   26221:                 if (!is_array($releases)) {
                   26222:                     return true;
                   26223:                 }
                   26224:                 if (!isset($releases[0])) {
                   26225:                     $releases = array($releases);
                   26226:                 }
                   26227:                 foreach ($releases as $rel) {
                   26228:                     $this->_stupidSchemaValidate(array(
                   26229:                         '*installconditions',
                   26230:                         '*configureoption->name->prompt->?default',
                   26231:                         '*binarypackage',
                   26232:                         '*filelist',
                   26233:                     ), $rel, '<' . $releasetype . '>');
                   26234:                     if (isset($rel['binarypackage'])) {
                   26235:                         if (!is_array($rel['binarypackage']) || !isset($rel['binarypackage'][0])) {
                   26236:                             $rel['binarypackage'] = array($rel['binarypackage']);
                   26237:                         }
                   26238:                         foreach ($rel['binarypackage'] as $bin) {
                   26239:                             if (!is_string($bin)) {
                   26240:                                 $this->_binaryPackageMustBePackagename();
                   26241:                             }
                   26242:                         }
                   26243:                     }
                   26244:                 }
                   26245:             }
                   26246:             $releasetype = 'extbinrelease';
                   26247:             if (isset($this->_packageInfo[$releasetype])) {
                   26248:                 $release = $releasetype;
                   26249:                 if (!isset($this->_packageInfo['providesextension'])) {
                   26250:                     $this->_mustProvideExtension($release);
                   26251:                 }
                   26252:                 if (isset($this->_packageInfo['channel']) &&
                   26253:                       !isset($this->_packageInfo['srcpackage'])) {
                   26254:                     $this->_mustSrcPackage($release);
                   26255:                 }
                   26256:                 if (isset($this->_packageInfo['uri']) && !isset($this->_packageInfo['srcuri'])) {
                   26257:                     $this->_mustSrcuri($release);
                   26258:                 }
                   26259:                 $releases = $this->_packageInfo[$releasetype];
                   26260:                 if (!is_array($releases)) {
                   26261:                     return true;
                   26262:                 }
                   26263:                 if (!isset($releases[0])) {
                   26264:                     $releases = array($releases);
                   26265:                 }
                   26266:                 foreach ($releases as $rel) {
                   26267:                     $this->_stupidSchemaValidate(array(
                   26268:                         '*installconditions',
                   26269:                         '*filelist',
                   26270:                     ), $rel, '<' . $releasetype . '>');
                   26271:                 }
                   26272:             }
                   26273:         }
                   26274:         if (isset($this->_packageInfo['bundle'])) {
                   26275:             $release = 'bundle';
                   26276:             if (isset($this->_packageInfo['providesextension'])) {
                   26277:                 $this->_cannotProvideExtension($release);
                   26278:             }
                   26279:             if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
                   26280:                 $this->_cannotHaveSrcpackage($release);
                   26281:             }
                   26282:             $releases = $this->_packageInfo['bundle'];
                   26283:             if (!is_array($releases) || !isset($releases[0])) {
                   26284:                 $releases = array($releases);
                   26285:             }
                   26286:             foreach ($releases as $rel) {
                   26287:                 $this->_stupidSchemaValidate(array(
                   26288:                     '*installconditions',
                   26289:                     '*filelist',
                   26290:                 ), $rel, '<bundle>');
                   26291:             }
                   26292:         }
                   26293:         foreach ($releases as $rel) {
                   26294:             if (is_array($rel) && array_key_exists('installconditions', $rel)) {
                   26295:                 $this->_validateInstallConditions($rel['installconditions'],
                   26296:                     "<$release><installconditions>");
                   26297:             }
                   26298:             if (is_array($rel) && array_key_exists('filelist', $rel)) {
                   26299:                 if ($rel['filelist']) {
                   26300: 
                   26301:                     $this->_validateFilelist($rel['filelist'], true);
                   26302:                 }
                   26303:             }
                   26304:         }
                   26305:     }
                   26306: 
                   26307:     /**
                   26308:      * This is here to allow role extension through plugins
                   26309:      * @param string
                   26310:      */
                   26311:     function _validateRole($role)
                   26312:     {
                   26313:         return in_array($role, PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType()));
                   26314:     }
                   26315: 
                   26316:     function _pearVersionTooLow($version)
                   26317:     {
                   26318:         $this->_stack->push(__FUNCTION__, 'error',
                   26319:             array('version' => $version),
                   26320:             'This package.xml requires PEAR version %version% to parse properly, we are ' .
                   26321:             'version 1.9.4');
                   26322:     }
                   26323: 
                   26324:     function _invalidTagOrder($oktags, $actual, $root)
                   26325:     {
                   26326:         $this->_stack->push(__FUNCTION__, 'error',
                   26327:             array('oktags' => $oktags, 'actual' => $actual, 'root' => $root),
                   26328:             'Invalid tag order in %root%, found <%actual%> expected one of "%oktags%"');
                   26329:     }
                   26330: 
                   26331:     function _ignoreNotAllowed($type)
                   26332:     {
                   26333:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
                   26334:             '<%type%> is not allowed inside global <contents>, only inside ' .
                   26335:             '<phprelease>/<extbinrelease>/<zendextbinrelease>, use <dir> and <file> only');
                   26336:     }
                   26337: 
                   26338:     function _fileNotAllowed($type)
                   26339:     {
                   26340:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
                   26341:             '<%type%> is not allowed inside release <filelist>, only inside ' .
                   26342:             '<contents>, use <ignore> and <install> only');
                   26343:     }
                   26344: 
                   26345:     function _oldStyleFileNotAllowed()
                   26346:     {
                   26347:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   26348:             'Old-style <file>name</file> is not allowed.  Use' .
                   26349:             '<file name="name" role="role"/>');
                   26350:     }
                   26351: 
                   26352:     function _tagMissingAttribute($tag, $attr, $context)
                   26353:     {
                   26354:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag,
                   26355:             'attribute' => $attr, 'context' => $context),
                   26356:             'tag <%tag%> in context "%context%" has no attribute "%attribute%"');
                   26357:     }
                   26358: 
                   26359:     function _tagHasNoAttribs($tag, $context)
                   26360:     {
                   26361:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag,
                   26362:             'context' => $context),
                   26363:             'tag <%tag%> has no attributes in context "%context%"');
                   26364:     }
                   26365: 
                   26366:     function _invalidInternalStructure()
                   26367:     {
                   26368:         $this->_stack->push(__FUNCTION__, 'exception', array(),
                   26369:             'internal array was not generated by compatible parser, or extreme parser error, cannot continue');
                   26370:     }
                   26371: 
                   26372:     function _invalidFileRole($file, $dir, $role)
                   26373:     {
                   26374:         $this->_stack->push(__FUNCTION__, 'error', array(
                   26375:             'file' => $file, 'dir' => $dir, 'role' => $role,
                   26376:             'roles' => PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType())),
                   26377:             'File "%file%" in directory "%dir%" has invalid role "%role%", should be one of %roles%');
                   26378:     }
                   26379: 
                   26380:     function _invalidFileName($file, $dir)
                   26381:     {
                   26382:         $this->_stack->push(__FUNCTION__, 'error', array(
                   26383:             'file' => $file),
                   26384:             'File "%file%" in directory "%dir%" cannot begin with "./" or contain ".."');
                   26385:     }
                   26386: 
                   26387:     function _invalidFileInstallAs($file, $as)
                   26388:     {
                   26389:         $this->_stack->push(__FUNCTION__, 'error', array(
                   26390:             'file' => $file, 'as' => $as),
                   26391:             'File "%file%" <install as="%as%"/> cannot contain "./" or contain ".."');
                   26392:     }
                   26393: 
                   26394:     function _invalidDirName($dir)
                   26395:     {
                   26396:         $this->_stack->push(__FUNCTION__, 'error', array(
                   26397:             'dir' => $file),
                   26398:             'Directory "%dir%" cannot begin with "./" or contain ".."');
                   26399:     }
                   26400: 
                   26401:     function _filelistCannotContainFile($filelist)
                   26402:     {
                   26403:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist),
                   26404:             '<%tag%> can only contain <dir>, contains <file>.  Use ' .
                   26405:             '<dir name="/"> as the first dir element');
                   26406:     }
                   26407: 
                   26408:     function _filelistMustContainDir($filelist)
                   26409:     {
                   26410:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist),
                   26411:             '<%tag%> must contain <dir>.  Use <dir name="/"> as the ' .
                   26412:             'first dir element');
                   26413:     }
                   26414: 
                   26415:     function _tagCannotBeEmpty($tag)
                   26416:     {
                   26417:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag),
                   26418:             '<%tag%> cannot be empty (<%tag%/>)');
                   26419:     }
                   26420: 
                   26421:     function _UrlOrChannel($type, $name)
                   26422:     {
                   26423:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
                   26424:             'name' => $name),
                   26425:             'Required dependency <%type%> "%name%" can have either url OR ' .
                   26426:             'channel attributes, and not both');
                   26427:     }
                   26428: 
                   26429:     function _NoChannel($type, $name)
                   26430:     {
                   26431:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
                   26432:             'name' => $name),
                   26433:             'Required dependency <%type%> "%name%" must have either url OR ' .
                   26434:             'channel attributes');
                   26435:     }
                   26436: 
                   26437:     function _UrlOrChannelGroup($type, $name, $group)
                   26438:     {
                   26439:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
                   26440:             'name' => $name, 'group' => $group),
                   26441:             'Group "%group%" dependency <%type%> "%name%" can have either url OR ' .
                   26442:             'channel attributes, and not both');
                   26443:     }
                   26444: 
                   26445:     function _NoChannelGroup($type, $name, $group)
                   26446:     {
                   26447:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
                   26448:             'name' => $name, 'group' => $group),
                   26449:             'Group "%group%" dependency <%type%> "%name%" must have either url OR ' .
                   26450:             'channel attributes');
                   26451:     }
                   26452: 
                   26453:     function _unknownChannel($channel)
                   26454:     {
                   26455:         $this->_stack->push(__FUNCTION__, 'error', array('channel' => $channel),
                   26456:             'Unknown channel "%channel%"');
                   26457:     }
                   26458: 
                   26459:     function _noPackageVersion()
                   26460:     {
                   26461:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   26462:             'package.xml <package> tag has no version attribute, or version is not 2.0');
                   26463:     }
                   26464: 
                   26465:     function _NoBundledPackages()
                   26466:     {
                   26467:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   26468:             'No <bundledpackage> tag was found in <contents>, required for bundle packages');
                   26469:     }
                   26470: 
                   26471:     function _AtLeast2BundledPackages()
                   26472:     {
                   26473:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   26474:             'At least 2 packages must be bundled in a bundle package');
                   26475:     }
                   26476: 
                   26477:     function _ChannelOrUri($name)
                   26478:     {
                   26479:         $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
                   26480:             'Bundled package "%name%" can have either a uri or a channel, not both');
                   26481:     }
                   26482: 
                   26483:     function _noChildTag($child, $tag)
                   26484:     {
                   26485:         $this->_stack->push(__FUNCTION__, 'error', array('child' => $child, 'tag' => $tag),
                   26486:             'Tag <%tag%> is missing child tag <%child%>');
                   26487:     }
                   26488: 
                   26489:     function _invalidVersion($type, $value)
                   26490:     {
                   26491:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value),
                   26492:             'Version type <%type%> is not a valid version (%value%)');
                   26493:     }
                   26494: 
                   26495:     function _invalidState($type, $value)
                   26496:     {
                   26497:         $states = array('stable', 'beta', 'alpha', 'devel');
                   26498:         if ($type != 'api') {
                   26499:             $states[] = 'snapshot';
                   26500:         }
                   26501:         if (strtolower($value) == 'rc') {
                   26502:             $this->_stack->push(__FUNCTION__, 'error',
                   26503:                 array('version' => $this->_packageInfo['version']['release']),
                   26504:                 'RC is not a state, it is a version postfix, try %version%RC1, stability beta');
                   26505:         }
                   26506:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value,
                   26507:             'types' => $states),
                   26508:             'Stability type <%type%> is not a valid stability (%value%), must be one of ' .
                   26509:             '%types%');
                   26510:     }
                   26511: 
                   26512:     function _invalidTask($task, $ret, $file)
                   26513:     {
                   26514:         switch ($ret[0]) {
                   26515:             case PEAR_TASK_ERROR_MISSING_ATTRIB :
                   26516:                 $info = array('attrib' => $ret[1], 'task' => $task, 'file' => $file);
                   26517:                 $msg = 'task <%task%> is missing attribute "%attrib%" in file %file%';
                   26518:             break;
                   26519:             case PEAR_TASK_ERROR_NOATTRIBS :
                   26520:                 $info = array('task' => $task, 'file' => $file);
                   26521:                 $msg = 'task <%task%> has no attributes in file %file%';
                   26522:             break;
                   26523:             case PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE :
                   26524:                 $info = array('attrib' => $ret[1], 'values' => $ret[3],
                   26525:                     'was' => $ret[2], 'task' => $task, 'file' => $file);
                   26526:                 $msg = 'task <%task%> attribute "%attrib%" has the wrong value "%was%" '.
                   26527:                     'in file %file%, expecting one of "%values%"';
                   26528:             break;
                   26529:             case PEAR_TASK_ERROR_INVALID :
                   26530:                 $info = array('reason' => $ret[1], 'task' => $task, 'file' => $file);
                   26531:                 $msg = 'task <%task%> in file %file% is invalid because of "%reason%"';
                   26532:             break;
                   26533:         }
                   26534:         $this->_stack->push(__FUNCTION__, 'error', $info, $msg);
                   26535:     }
                   26536: 
                   26537:     function _unknownTask($task, $file)
                   26538:     {
                   26539:         $this->_stack->push(__FUNCTION__, 'error', array('task' => $task, 'file' => $file),
                   26540:             'Unknown task "%task%" passed in file <file name="%file%">');
                   26541:     }
                   26542: 
                   26543:     function _subpackageCannotProvideExtension($name)
                   26544:     {
                   26545:         $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
                   26546:             'Subpackage dependency "%name%" cannot use <providesextension>, ' .
                   26547:             'only package dependencies can use this tag');
                   26548:     }
                   26549: 
                   26550:     function _subpackagesCannotConflict($name)
                   26551:     {
                   26552:         $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
                   26553:             'Subpackage dependency "%name%" cannot use <conflicts/>, ' .
                   26554:             'only package dependencies can use this tag');
                   26555:     }
                   26556: 
                   26557:     function _cannotProvideExtension($release)
                   26558:     {
                   26559:         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
                   26560:             '<%release%> packages cannot use <providesextension>, only extbinrelease, extsrcrelease, zendextsrcrelease, and zendextbinrelease can provide a PHP extension');
                   26561:     }
                   26562: 
                   26563:     function _mustProvideExtension($release)
                   26564:     {
                   26565:         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
                   26566:             '<%release%> packages must use <providesextension> to indicate which PHP extension is provided');
                   26567:     }
                   26568: 
                   26569:     function _cannotHaveSrcpackage($release)
                   26570:     {
                   26571:         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
                   26572:             '<%release%> packages cannot specify a source code package, only extension binaries may use the <srcpackage> tag');
                   26573:     }
                   26574: 
                   26575:     function _mustSrcPackage($release)
                   26576:     {
                   26577:         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
                   26578:             '<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcpackage>');
                   26579:     }
                   26580: 
                   26581:     function _mustSrcuri($release)
                   26582:     {
                   26583:         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
                   26584:             '<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcuri>');
                   26585:     }
                   26586: 
                   26587:     function _uriDepsCannotHaveVersioning($type)
                   26588:     {
                   26589:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
                   26590:             '%type%: dependencies with a <uri> tag cannot have any versioning information');
                   26591:     }
                   26592: 
                   26593:     function _conflictingDepsCannotHaveVersioning($type)
                   26594:     {
                   26595:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
                   26596:             '%type%: conflicting dependencies cannot have versioning info, use <exclude> to ' .
                   26597:             'exclude specific versions of a dependency');
                   26598:     }
                   26599: 
                   26600:     function _DepchannelCannotBeUri($type)
                   26601:     {
                   26602:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
                   26603:             '%type%: channel cannot be __uri, this is a pseudo-channel reserved for uri ' .
                   26604:             'dependencies only');
                   26605:     }
                   26606: 
                   26607:     function _bundledPackagesMustBeFilename()
                   26608:     {
                   26609:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   26610:             '<bundledpackage> tags must contain only the filename of a package release ' .
                   26611:             'in the bundle');
                   26612:     }
                   26613: 
                   26614:     function _binaryPackageMustBePackagename()
                   26615:     {
                   26616:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   26617:             '<binarypackage> tags must contain the name of a package that is ' .
                   26618:             'a compiled version of this extsrc/zendextsrc package');
                   26619:     }
                   26620: 
                   26621:     function _fileNotFound($file)
                   26622:     {
                   26623:         $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
                   26624:             'File "%file%" in package.xml does not exist');
                   26625:     }
                   26626: 
                   26627:     function _notInContents($file, $tag)
                   26628:     {
                   26629:         $this->_stack->push(__FUNCTION__, 'error', array('file' => $file, 'tag' => $tag),
                   26630:             '<%tag% name="%file%"> is invalid, file is not in <contents>');
                   26631:     }
                   26632: 
                   26633:     function _cannotValidateNoPathSet()
                   26634:     {
                   26635:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   26636:             'Cannot validate files, no path to package file is set (use setPackageFile())');
                   26637:     }
                   26638: 
                   26639:     function _usesroletaskMustHaveChannelOrUri($role, $tag)
                   26640:     {
                   26641:         $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
                   26642:             '<%tag%> for role "%role%" must contain either <uri>, or <channel> and <package>');
                   26643:     }
                   26644: 
                   26645:     function _usesroletaskMustHavePackage($role, $tag)
                   26646:     {
                   26647:         $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
                   26648:             '<%tag%> for role "%role%" must contain <package>');
                   26649:     }
                   26650: 
                   26651:     function _usesroletaskMustHaveRoleTask($tag, $type)
                   26652:     {
                   26653:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, 'type' => $type),
                   26654:             '<%tag%> must contain <%type%> defining the %type% to be used');
                   26655:     }
                   26656: 
                   26657:     function _cannotConflictWithAllOs($type)
                   26658:     {
                   26659:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag),
                   26660:             '%tag% cannot conflict with all OSes');
                   26661:     }
                   26662: 
                   26663:     function _invalidDepGroupName($name)
                   26664:     {
                   26665:         $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
                   26666:             'Invalid dependency group name "%name%"');
                   26667:     }
                   26668: 
                   26669:     function _multipleToplevelDirNotAllowed()
                   26670:     {
                   26671:         $this->_stack->push(__FUNCTION__, 'error', array(),
                   26672:             'Multiple top-level <dir> tags are not allowed.  Enclose them ' .
                   26673:                 'in a <dir name="/">');
                   26674:     }
                   26675: 
                   26676:     function _multipleInstallAs($file)
                   26677:     {
                   26678:         $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
                   26679:             'Only one <install> tag is allowed for file "%file%"');
                   26680:     }
                   26681: 
                   26682:     function _ignoreAndInstallAs($file)
                   26683:     {
                   26684:         $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
                   26685:             'Cannot have both <ignore> and <install> tags for file "%file%"');
                   26686:     }
                   26687: 
                   26688:     function _analyzeBundledPackages()
                   26689:     {
                   26690:         if (!$this->_isValid) {
                   26691:             return false;
                   26692:         }
                   26693:         if (!$this->_pf->getPackageType() == 'bundle') {
                   26694:             return false;
                   26695:         }
                   26696:         if (!isset($this->_pf->_packageFile)) {
                   26697:             return false;
                   26698:         }
                   26699:         $dir_prefix = dirname($this->_pf->_packageFile);
                   26700:         $common = new PEAR_Common;
                   26701:         $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
                   26702:             array($common, 'log');
                   26703:         $info = $this->_pf->getContents();
                   26704:         $info = $info['bundledpackage'];
                   26705:         if (!is_array($info)) {
                   26706:             $info = array($info);
                   26707:         }
                   26708:         $pkg = &new PEAR_PackageFile($this->_pf->_config);
                   26709:         foreach ($info as $package) {
                   26710:             if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $package)) {
                   26711:                 $this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $package);
                   26712:                 $this->_isValid = 0;
                   26713:                 continue;
                   26714:             }
                   26715:             call_user_func_array($log, array(1, "Analyzing bundled package $package"));
                   26716:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   26717:             $ret = $pkg->fromAnyFile($dir_prefix . DIRECTORY_SEPARATOR . $package,
                   26718:                 PEAR_VALIDATE_NORMAL);
                   26719:             PEAR::popErrorHandling();
                   26720:             if (PEAR::isError($ret)) {
                   26721:                 call_user_func_array($log, array(0, "ERROR: package $package is not a valid " .
                   26722:                     'package'));
                   26723:                 $inf = $ret->getUserInfo();
                   26724:                 if (is_array($inf)) {
                   26725:                     foreach ($inf as $err) {
                   26726:                         call_user_func_array($log, array(1, $err['message']));
                   26727:                     }
                   26728:                 }
                   26729:                 return false;
                   26730:             }
                   26731:         }
                   26732:         return true;
                   26733:     }
                   26734: 
                   26735:     function _analyzePhpFiles()
                   26736:     {
                   26737:         if (!$this->_isValid) {
                   26738:             return false;
                   26739:         }
                   26740:         if (!isset($this->_pf->_packageFile)) {
                   26741:             $this->_cannotValidateNoPathSet();
                   26742:             return false;
                   26743:         }
                   26744:         $dir_prefix = dirname($this->_pf->_packageFile);
                   26745:         $common = new PEAR_Common;
                   26746:         $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
                   26747:             array(&$common, 'log');
                   26748:         $info = $this->_pf->getContents();
                   26749:         if (!$info || !isset($info['dir']['file'])) {
                   26750:             $this->_tagCannotBeEmpty('contents><dir');
                   26751:             return false;
                   26752:         }
                   26753:         $info = $info['dir']['file'];
                   26754:         if (isset($info['attribs'])) {
                   26755:             $info = array($info);
                   26756:         }
                   26757:         $provides = array();
                   26758:         foreach ($info as $fa) {
                   26759:             $fa = $fa['attribs'];
                   26760:             $file = $fa['name'];
                   26761:             if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) {
                   26762:                 $this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $file);
                   26763:                 $this->_isValid = 0;
                   26764:                 continue;
                   26765:             }
                   26766:             if (in_array($fa['role'], PEAR_Installer_Role::getPhpRoles()) && $dir_prefix) {
                   26767:                 call_user_func_array($log, array(1, "Analyzing $file"));
                   26768:                 $srcinfo = $this->analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file);
                   26769:                 if ($srcinfo) {
                   26770:                     $provides = array_merge($provides, $this->_buildProvidesArray($srcinfo));
                   26771:                 }
                   26772:             }
                   26773:         }
                   26774:         $this->_packageName = $pn = $this->_pf->getPackage();
                   26775:         $pnl = strlen($pn);
                   26776:         foreach ($provides as $key => $what) {
                   26777:             if (isset($what['explicit']) || !$what) {
                   26778:                 // skip conformance checks if the provides entry is
                   26779:                 // specified in the package.xml file
                   26780:                 continue;
                   26781:             }
                   26782:             extract($what);
                   26783:             if ($type == 'class') {
                   26784:                 if (!strncasecmp($name, $pn, $pnl)) {
                   26785:                     continue;
                   26786:                 }
                   26787:                 $this->_stack->push(__FUNCTION__, 'warning',
                   26788:                     array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn),
                   26789:                     'in %file%: %type% "%name%" not prefixed with package name "%package%"');
                   26790:             } elseif ($type == 'function') {
                   26791:                 if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) {
                   26792:                     continue;
                   26793:                 }
                   26794:                 $this->_stack->push(__FUNCTION__, 'warning',
                   26795:                     array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn),
                   26796:                     'in %file%: %type% "%name%" not prefixed with package name "%package%"');
                   26797:             }
                   26798:         }
                   26799:         return $this->_isValid;
                   26800:     }
                   26801: 
                   26802:     /**
                   26803:      * Analyze the source code of the given PHP file
                   26804:      *
                   26805:      * @param  string Filename of the PHP file
                   26806:      * @param  boolean whether to analyze $file as the file contents
                   26807:      * @return mixed
                   26808:      */
                   26809:     function analyzeSourceCode($file, $string = false)
                   26810:     {
                   26811:         if (!function_exists("token_get_all")) {
                   26812:             $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
                   26813:                 'Parser error: token_get_all() function must exist to analyze source code, PHP may have been compiled with --disable-tokenizer');
                   26814:             return false;
                   26815:         }
                   26816: 
                   26817:         if (!defined('T_DOC_COMMENT')) {
                   26818:             define('T_DOC_COMMENT', T_COMMENT);
                   26819:         }
                   26820: 
                   26821:         if (!defined('T_INTERFACE')) {
                   26822:             define('T_INTERFACE', -1);
                   26823:         }
                   26824: 
                   26825:         if (!defined('T_IMPLEMENTS')) {
                   26826:             define('T_IMPLEMENTS', -1);
                   26827:         }
                   26828: 
                   26829:         if ($string) {
                   26830:             $contents = $file;
                   26831:         } else {
                   26832:             if (!$fp = @fopen($file, "r")) {
                   26833:                 return false;
                   26834:             }
                   26835:             fclose($fp);
                   26836:             $contents = file_get_contents($file);
                   26837:         }
                   26838: 
                   26839:         // Silence this function so we can catch PHP Warnings and show our own custom message
                   26840:         $tokens = @token_get_all($contents);
                   26841:         if (isset($php_errormsg)) {
                   26842:             if (isset($this->_stack)) {
                   26843:                 $pn = $this->_pf->getPackage();
                   26844:                 $this->_stack->push(__FUNCTION__, 'warning',
                   26845:                         array('file' => $file, 'package' => $pn),
                   26846:                         'in %file%: Could not process file for unkown reasons,' .
                   26847:                         ' possibly a PHP parse error in %file% from %package%');
                   26848:             }
                   26849:         }
                   26850: /*
                   26851:         for ($i = 0; $i < sizeof($tokens); $i++) {
                   26852:             @list($token, $data) = $tokens[$i];
                   26853:             if (is_string($token)) {
                   26854:                 var_dump($token);
                   26855:             } else {
                   26856:                 print token_name($token) . ' ';
                   26857:                 var_dump(rtrim($data));
                   26858:             }
                   26859:         }
                   26860: */
                   26861:         $look_for = 0;
                   26862:         $paren_level = 0;
                   26863:         $bracket_level = 0;
                   26864:         $brace_level = 0;
                   26865:         $lastphpdoc = '';
                   26866:         $current_class = '';
                   26867:         $current_interface = '';
                   26868:         $current_class_level = -1;
                   26869:         $current_function = '';
                   26870:         $current_function_level = -1;
                   26871:         $declared_classes = array();
                   26872:         $declared_interfaces = array();
                   26873:         $declared_functions = array();
                   26874:         $declared_methods = array();
                   26875:         $used_classes = array();
                   26876:         $used_functions = array();
                   26877:         $extends = array();
                   26878:         $implements = array();
                   26879:         $nodeps = array();
                   26880:         $inquote = false;
                   26881:         $interface = false;
                   26882:         for ($i = 0; $i < sizeof($tokens); $i++) {
                   26883:             if (is_array($tokens[$i])) {
                   26884:                 list($token, $data) = $tokens[$i];
                   26885:             } else {
                   26886:                 $token = $tokens[$i];
                   26887:                 $data = '';
                   26888:             }
                   26889: 
                   26890:             if ($inquote) {
                   26891:                 if ($token != '"' && $token != T_END_HEREDOC) {
                   26892:                     continue;
                   26893:                 } else {
                   26894:                     $inquote = false;
                   26895:                     continue;
                   26896:                 }
                   26897:             }
                   26898: 
                   26899:             switch ($token) {
                   26900:                 case T_WHITESPACE :
                   26901:                     continue;
                   26902:                 case ';':
                   26903:                     if ($interface) {
                   26904:                         $current_function = '';
                   26905:                         $current_function_level = -1;
                   26906:                     }
                   26907:                     break;
                   26908:                 case '"':
                   26909:                 case T_START_HEREDOC:
                   26910:                     $inquote = true;
                   26911:                     break;
                   26912:                 case T_CURLY_OPEN:
                   26913:                 case T_DOLLAR_OPEN_CURLY_BRACES:
                   26914:                 case '{': $brace_level++; continue 2;
                   26915:                 case '}':
                   26916:                     $brace_level--;
                   26917:                     if ($current_class_level == $brace_level) {
                   26918:                         $current_class = '';
                   26919:                         $current_class_level = -1;
                   26920:                     }
                   26921:                     if ($current_function_level == $brace_level) {
                   26922:                         $current_function = '';
                   26923:                         $current_function_level = -1;
                   26924:                     }
                   26925:                     continue 2;
                   26926:                 case '[': $bracket_level++; continue 2;
                   26927:                 case ']': $bracket_level--; continue 2;
                   26928:                 case '(': $paren_level++;   continue 2;
                   26929:                 case ')': $paren_level--;   continue 2;
                   26930:                 case T_INTERFACE:
                   26931:                     $interface = true;
                   26932:                 case T_CLASS:
                   26933:                     if (($current_class_level != -1) || ($current_function_level != -1)) {
                   26934:                         if (isset($this->_stack)) {
                   26935:                             $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
                   26936:                             'Parser error: invalid PHP found in file "%file%"');
                   26937:                         } else {
                   26938:                             PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"",
                   26939:                                 PEAR_COMMON_ERROR_INVALIDPHP);
                   26940:                         }
                   26941: 
                   26942:                         return false;
                   26943:                     }
                   26944:                 case T_FUNCTION:
                   26945:                 case T_NEW:
                   26946:                 case T_EXTENDS:
                   26947:                 case T_IMPLEMENTS:
                   26948:                     $look_for = $token;
                   26949:                     continue 2;
                   26950:                 case T_STRING:
                   26951:                     if (version_compare(zend_version(), '2.0', '<')) {
                   26952:                         if (in_array(strtolower($data),
                   26953:                             array('public', 'private', 'protected', 'abstract',
                   26954:                                   'interface', 'implements', 'throw')
                   26955:                                  )
                   26956:                         ) {
                   26957:                             if (isset($this->_stack)) {
                   26958:                                 $this->_stack->push(__FUNCTION__, 'warning', array(
                   26959:                                     'file' => $file),
                   26960:                                     'Error, PHP5 token encountered in %file%,' .
                   26961:                                     ' analysis should be in PHP5');
                   26962:                             } else {
                   26963:                                 PEAR::raiseError('Error: PHP5 token encountered in ' . $file .
                   26964:                                     'packaging should be done in PHP 5');
                   26965:                                 return false;
                   26966:                             }
                   26967:                         }
                   26968:                     }
                   26969: 
                   26970:                     if ($look_for == T_CLASS) {
                   26971:                         $current_class = $data;
                   26972:                         $current_class_level = $brace_level;
                   26973:                         $declared_classes[] = $current_class;
                   26974:                     } elseif ($look_for == T_INTERFACE) {
                   26975:                         $current_interface = $data;
                   26976:                         $current_class_level = $brace_level;
                   26977:                         $declared_interfaces[] = $current_interface;
                   26978:                     } elseif ($look_for == T_IMPLEMENTS) {
                   26979:                         $implements[$current_class] = $data;
                   26980:                     } elseif ($look_for == T_EXTENDS) {
                   26981:                         $extends[$current_class] = $data;
                   26982:                     } elseif ($look_for == T_FUNCTION) {
                   26983:                         if ($current_class) {
                   26984:                             $current_function = "$current_class::$data";
                   26985:                             $declared_methods[$current_class][] = $data;
                   26986:                         } elseif ($current_interface) {
                   26987:                             $current_function = "$current_interface::$data";
                   26988:                             $declared_methods[$current_interface][] = $data;
                   26989:                         } else {
                   26990:                             $current_function = $data;
                   26991:                             $declared_functions[] = $current_function;
                   26992:                         }
                   26993: 
                   26994:                         $current_function_level = $brace_level;
                   26995:                         $m = array();
                   26996:                     } elseif ($look_for == T_NEW) {
                   26997:                         $used_classes[$data] = true;
                   26998:                     }
                   26999: 
                   27000:                     $look_for = 0;
                   27001:                     continue 2;
                   27002:                 case T_VARIABLE:
                   27003:                     $look_for = 0;
                   27004:                     continue 2;
                   27005:                 case T_DOC_COMMENT:
                   27006:                 case T_COMMENT:
                   27007:                     if (preg_match('!^/\*\*\s!', $data)) {
                   27008:                         $lastphpdoc = $data;
                   27009:                         if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) {
                   27010:                             $nodeps = array_merge($nodeps, $m[1]);
                   27011:                         }
                   27012:                     }
                   27013:                     continue 2;
                   27014:                 case T_DOUBLE_COLON:
                   27015:                     $token = $tokens[$i - 1][0];
                   27016:                     if (!($token == T_WHITESPACE || $token == T_STRING || $token == T_STATIC)) {
                   27017:                         if (isset($this->_stack)) {
                   27018:                             $this->_stack->push(__FUNCTION__, 'warning', array('file' => $file),
                   27019:                                 'Parser error: invalid PHP found in file "%file%"');
                   27020:                         } else {
                   27021:                             PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"",
                   27022:                                 PEAR_COMMON_ERROR_INVALIDPHP);
                   27023:                         }
                   27024: 
                   27025:                         return false;
                   27026:                     }
                   27027: 
                   27028:                     $class = $tokens[$i - 1][1];
                   27029:                     if (strtolower($class) != 'parent') {
                   27030:                         $used_classes[$class] = true;
                   27031:                     }
                   27032: 
                   27033:                     continue 2;
                   27034:             }
                   27035:         }
                   27036: 
                   27037:         return array(
                   27038:             "source_file" => $file,
                   27039:             "declared_classes" => $declared_classes,
                   27040:             "declared_interfaces" => $declared_interfaces,
                   27041:             "declared_methods" => $declared_methods,
                   27042:             "declared_functions" => $declared_functions,
                   27043:             "used_classes" => array_diff(array_keys($used_classes), $nodeps),
                   27044:             "inheritance" => $extends,
                   27045:             "implements" => $implements,
                   27046:         );
                   27047:     }
                   27048: 
                   27049:     /**
                   27050:      * Build a "provides" array from data returned by
                   27051:      * analyzeSourceCode().  The format of the built array is like
                   27052:      * this:
                   27053:      *
                   27054:      *  array(
                   27055:      *    'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
                   27056:      *    ...
                   27057:      *  )
                   27058:      *
                   27059:      *
                   27060:      * @param array $srcinfo array with information about a source file
                   27061:      * as returned by the analyzeSourceCode() method.
                   27062:      *
                   27063:      * @return void
                   27064:      *
                   27065:      * @access private
                   27066:      *
                   27067:      */
                   27068:     function _buildProvidesArray($srcinfo)
                   27069:     {
                   27070:         if (!$this->_isValid) {
                   27071:             return array();
                   27072:         }
                   27073: 
                   27074:         $providesret = array();
                   27075:         $file        = basename($srcinfo['source_file']);
                   27076:         $pn          = isset($this->_pf) ? $this->_pf->getPackage() : '';
                   27077:         $pnl         = strlen($pn);
                   27078:         foreach ($srcinfo['declared_classes'] as $class) {
                   27079:             $key = "class;$class";
                   27080:             if (isset($providesret[$key])) {
                   27081:                 continue;
                   27082:             }
                   27083: 
                   27084:             $providesret[$key] =
                   27085:                 array('file'=> $file, 'type' => 'class', 'name' => $class);
                   27086:             if (isset($srcinfo['inheritance'][$class])) {
                   27087:                 $providesret[$key]['extends'] =
                   27088:                     $srcinfo['inheritance'][$class];
                   27089:             }
                   27090:         }
                   27091: 
                   27092:         foreach ($srcinfo['declared_methods'] as $class => $methods) {
                   27093:             foreach ($methods as $method) {
                   27094:                 $function = "$class::$method";
                   27095:                 $key = "function;$function";
                   27096:                 if ($method{0} == '_' || !strcasecmp($method, $class) ||
                   27097:                     isset($providesret[$key])) {
                   27098:                     continue;
                   27099:                 }
                   27100: 
                   27101:                 $providesret[$key] =
                   27102:                     array('file'=> $file, 'type' => 'function', 'name' => $function);
                   27103:             }
                   27104:         }
                   27105: 
                   27106:         foreach ($srcinfo['declared_functions'] as $function) {
                   27107:             $key = "function;$function";
                   27108:             if ($function{0} == '_' || isset($providesret[$key])) {
                   27109:                 continue;
                   27110:             }
                   27111: 
                   27112:             if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
                   27113:                 $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
                   27114:             }
                   27115: 
                   27116:             $providesret[$key] =
                   27117:                 array('file'=> $file, 'type' => 'function', 'name' => $function);
                   27118:         }
                   27119: 
                   27120:         return $providesret;
                   27121:     }
1.1.1.2 ! misho    27122: }PEAR-1.9.4/PEAR/PackageFile/v1.php0000644000076500000240000014376011605156614015170 0ustar  helgistaff<?php
1.1       misho    27123: /**
                   27124:  * PEAR_PackageFile_v1, package.xml version 1.0
                   27125:  *
                   27126:  * PHP versions 4 and 5
                   27127:  *
                   27128:  * @category   pear
                   27129:  * @package    PEAR
                   27130:  * @author     Greg Beaver <cellog@php.net>
                   27131:  * @copyright  1997-2009 The Authors
                   27132:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   27133:  * @version    CVS: $Id: v1.php 313023 2011-07-06 19:17:11Z dufuz $
                   27134:  * @link       http://pear.php.net/package/PEAR
                   27135:  * @since      File available since Release 1.4.0a1
                   27136:  */
                   27137: /**
                   27138:  * For error handling
                   27139:  */
                   27140: require_once 'PEAR/ErrorStack.php';
                   27141: 
                   27142: /**
                   27143:  * Error code if parsing is attempted with no xml extension
                   27144:  */
                   27145: define('PEAR_PACKAGEFILE_ERROR_NO_XML_EXT', 3);
                   27146: 
                   27147: /**
                   27148:  * Error code if creating the xml parser resource fails
                   27149:  */
                   27150: define('PEAR_PACKAGEFILE_ERROR_CANT_MAKE_PARSER', 4);
                   27151: 
                   27152: /**
                   27153:  * Error code used for all sax xml parsing errors
                   27154:  */
                   27155: define('PEAR_PACKAGEFILE_ERROR_PARSER_ERROR', 5);
                   27156: 
                   27157: /**
                   27158:  * Error code used when there is no name
                   27159:  */
                   27160: define('PEAR_PACKAGEFILE_ERROR_NO_NAME', 6);
                   27161: 
                   27162: /**
                   27163:  * Error code when a package name is not valid
                   27164:  */
                   27165: define('PEAR_PACKAGEFILE_ERROR_INVALID_NAME', 7);
                   27166: 
                   27167: /**
                   27168:  * Error code used when no summary is parsed
                   27169:  */
                   27170: define('PEAR_PACKAGEFILE_ERROR_NO_SUMMARY', 8);
                   27171: 
                   27172: /**
                   27173:  * Error code for summaries that are more than 1 line
                   27174:  */
                   27175: define('PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY', 9);
                   27176: 
                   27177: /**
                   27178:  * Error code used when no description is present
                   27179:  */
                   27180: define('PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION', 10);
                   27181: 
                   27182: /**
                   27183:  * Error code used when no license is present
                   27184:  */
                   27185: define('PEAR_PACKAGEFILE_ERROR_NO_LICENSE', 11);
                   27186: 
                   27187: /**
                   27188:  * Error code used when a <version> version number is not present
                   27189:  */
                   27190: define('PEAR_PACKAGEFILE_ERROR_NO_VERSION', 12);
                   27191: 
                   27192: /**
                   27193:  * Error code used when a <version> version number is invalid
                   27194:  */
                   27195: define('PEAR_PACKAGEFILE_ERROR_INVALID_VERSION', 13);
                   27196: 
                   27197: /**
                   27198:  * Error code when release state is missing
                   27199:  */
                   27200: define('PEAR_PACKAGEFILE_ERROR_NO_STATE', 14);
                   27201: 
                   27202: /**
                   27203:  * Error code when release state is invalid
                   27204:  */
                   27205: define('PEAR_PACKAGEFILE_ERROR_INVALID_STATE', 15);
                   27206: 
                   27207: /**
                   27208:  * Error code when release state is missing
                   27209:  */
                   27210: define('PEAR_PACKAGEFILE_ERROR_NO_DATE', 16);
                   27211: 
                   27212: /**
                   27213:  * Error code when release state is invalid
                   27214:  */
                   27215: define('PEAR_PACKAGEFILE_ERROR_INVALID_DATE', 17);
                   27216: 
                   27217: /**
                   27218:  * Error code when no release notes are found
                   27219:  */
                   27220: define('PEAR_PACKAGEFILE_ERROR_NO_NOTES', 18);
                   27221: 
                   27222: /**
                   27223:  * Error code when no maintainers are found
                   27224:  */
                   27225: define('PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS', 19);
                   27226: 
                   27227: /**
                   27228:  * Error code when a maintainer has no handle
                   27229:  */
                   27230: define('PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE', 20);
                   27231: 
                   27232: /**
                   27233:  * Error code when a maintainer has no handle
                   27234:  */
                   27235: define('PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE', 21);
                   27236: 
                   27237: /**
                   27238:  * Error code when a maintainer has no name
                   27239:  */
                   27240: define('PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME', 22);
                   27241: 
                   27242: /**
                   27243:  * Error code when a maintainer has no email
                   27244:  */
                   27245: define('PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL', 23);
                   27246: 
                   27247: /**
                   27248:  * Error code when a maintainer has no handle
                   27249:  */
                   27250: define('PEAR_PACKAGEFILE_ERROR_INVALID_MAINTROLE', 24);
                   27251: 
                   27252: /**
                   27253:  * Error code when a dependency is not a PHP dependency, but has no name
                   27254:  */
                   27255: define('PEAR_PACKAGEFILE_ERROR_NO_DEPNAME', 25);
                   27256: 
                   27257: /**
                   27258:  * Error code when a dependency has no type (pkg, php, etc.)
                   27259:  */
                   27260: define('PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE', 26);
                   27261: 
                   27262: /**
                   27263:  * Error code when a dependency has no relation (lt, ge, has, etc.)
                   27264:  */
                   27265: define('PEAR_PACKAGEFILE_ERROR_NO_DEPREL', 27);
                   27266: 
                   27267: /**
                   27268:  * Error code when a dependency is not a 'has' relation, but has no version
                   27269:  */
                   27270: define('PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION', 28);
                   27271: 
                   27272: /**
                   27273:  * Error code when a dependency has an invalid relation
                   27274:  */
                   27275: define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPREL', 29);
                   27276: 
                   27277: /**
                   27278:  * Error code when a dependency has an invalid type
                   27279:  */
                   27280: define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPTYPE', 30);
                   27281: 
                   27282: /**
                   27283:  * Error code when a dependency has an invalid optional option
                   27284:  */
                   27285: define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL', 31);
                   27286: 
                   27287: /**
                   27288:  * Error code when a dependency is a pkg dependency, and has an invalid package name
                   27289:  */
                   27290: define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPNAME', 32);
                   27291: 
                   27292: /**
                   27293:  * Error code when a dependency has a channel="foo" attribute, and foo is not a registered channel
                   27294:  */
                   27295: define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_DEPCHANNEL', 33);
                   27296: 
                   27297: /**
                   27298:  * Error code when rel="has" and version attribute is present.
                   27299:  */
                   27300: define('PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED', 34);
                   27301: 
                   27302: /**
                   27303:  * Error code when type="php" and dependency name is present
                   27304:  */
                   27305: define('PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED', 35);
                   27306: 
                   27307: /**
                   27308:  * Error code when a configure option has no name
                   27309:  */
                   27310: define('PEAR_PACKAGEFILE_ERROR_NO_CONFNAME', 36);
                   27311: 
                   27312: /**
                   27313:  * Error code when a configure option has no name
                   27314:  */
                   27315: define('PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT', 37);
                   27316: 
                   27317: /**
                   27318:  * Error code when a file in the filelist has an invalid role
                   27319:  */
                   27320: define('PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE', 38);
                   27321: 
                   27322: /**
                   27323:  * Error code when a file in the filelist has no role
                   27324:  */
                   27325: define('PEAR_PACKAGEFILE_ERROR_NO_FILEROLE', 39);
                   27326: 
                   27327: /**
                   27328:  * Error code when analyzing a php source file that has parse errors
                   27329:  */
                   27330: define('PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE', 40);
                   27331: 
                   27332: /**
                   27333:  * Error code when analyzing a php source file reveals a source element
                   27334:  * without a package name prefix
                   27335:  */
                   27336: define('PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX', 41);
                   27337: 
                   27338: /**
                   27339:  * Error code when an unknown channel is specified
                   27340:  */
                   27341: define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_CHANNEL', 42);
                   27342: 
                   27343: /**
                   27344:  * Error code when no files are found in the filelist
                   27345:  */
                   27346: define('PEAR_PACKAGEFILE_ERROR_NO_FILES', 43);
                   27347: 
                   27348: /**
                   27349:  * Error code when a file is not valid php according to _analyzeSourceCode()
                   27350:  */
                   27351: define('PEAR_PACKAGEFILE_ERROR_INVALID_FILE', 44);
                   27352: 
                   27353: /**
                   27354:  * Error code when the channel validator returns an error or warning
                   27355:  */
                   27356: define('PEAR_PACKAGEFILE_ERROR_CHANNELVAL', 45);
                   27357: 
                   27358: /**
                   27359:  * Error code when a php5 package is packaged in php4 (analysis doesn't work)
                   27360:  */
                   27361: define('PEAR_PACKAGEFILE_ERROR_PHP5', 46);
                   27362: 
                   27363: /**
                   27364:  * Error code when a file is listed in package.xml but does not exist
                   27365:  */
                   27366: define('PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND', 47);
                   27367: 
                   27368: /**
                   27369:  * Error code when a <dep type="php" rel="not"... is encountered (use rel="ne")
                   27370:  */
                   27371: define('PEAR_PACKAGEFILE_PHP_NO_NOT', 48);
                   27372: 
                   27373: /**
                   27374:  * Error code when a package.xml contains non-ISO-8859-1 characters
                   27375:  */
                   27376: define('PEAR_PACKAGEFILE_ERROR_NON_ISO_CHARS', 49);
                   27377: 
                   27378: /**
                   27379:  * Error code when a dependency is not a 'has' relation, but has no version
                   27380:  */
                   27381: define('PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION', 50);
                   27382: 
                   27383: /**
                   27384:  * Error code when a package has no lead developer
                   27385:  */
                   27386: define('PEAR_PACKAGEFILE_ERROR_NO_LEAD', 51);
                   27387: 
                   27388: /**
                   27389:  * Error code when a filename begins with "."
                   27390:  */
                   27391: define('PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME', 52);
                   27392: /**
                   27393:  * package.xml encapsulator
                   27394:  * @category   pear
                   27395:  * @package    PEAR
                   27396:  * @author     Greg Beaver <cellog@php.net>
                   27397:  * @copyright  1997-2009 The Authors
                   27398:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   27399:  * @version    Release: 1.9.4
                   27400:  * @link       http://pear.php.net/package/PEAR
                   27401:  * @since      Class available since Release 1.4.0a1
                   27402:  */
                   27403: class PEAR_PackageFile_v1
                   27404: {
                   27405:     /**
                   27406:      * @access private
                   27407:      * @var PEAR_ErrorStack
                   27408:      * @access private
                   27409:      */
                   27410:     var $_stack;
                   27411: 
                   27412:     /**
                   27413:      * A registry object, used to access the package name validation regex for non-standard channels
                   27414:      * @var PEAR_Registry
                   27415:      * @access private
                   27416:      */
                   27417:     var $_registry;
                   27418: 
                   27419:     /**
                   27420:      * An object that contains a log method that matches PEAR_Common::log's signature
                   27421:      * @var object
                   27422:      * @access private
                   27423:      */
                   27424:     var $_logger;
                   27425: 
                   27426:     /**
                   27427:      * Parsed package information
                   27428:      * @var array
                   27429:      * @access private
                   27430:      */
                   27431:     var $_packageInfo;
                   27432: 
                   27433:     /**
                   27434:      * path to package.xml
                   27435:      * @var string
                   27436:      * @access private
                   27437:      */
                   27438:     var $_packageFile;
                   27439: 
                   27440:     /**
                   27441:      * path to package .tgz or false if this is a local/extracted package.xml
                   27442:      * @var string
                   27443:      * @access private
                   27444:      */
                   27445:     var $_archiveFile;
                   27446: 
                   27447:     /**
                   27448:      * @var int
                   27449:      * @access private
                   27450:      */
                   27451:     var $_isValid = 0;
                   27452: 
                   27453:     /**
                   27454:      * Determines whether this packagefile was initialized only with partial package info
                   27455:      *
                   27456:      * If this package file was constructed via parsing REST, it will only contain
                   27457:      *
                   27458:      * - package name
                   27459:      * - channel name
                   27460:      * - dependencies 
                   27461:      * @var boolean
                   27462:      * @access private
                   27463:      */
                   27464:     var $_incomplete = true;
                   27465: 
                   27466:     /**
                   27467:      * @param bool determines whether to return a PEAR_Error object, or use the PEAR_ErrorStack
                   27468:      * @param string Name of Error Stack class to use.
                   27469:      */
                   27470:     function PEAR_PackageFile_v1()
                   27471:     {
                   27472:         $this->_stack = &new PEAR_ErrorStack('PEAR_PackageFile_v1');
                   27473:         $this->_stack->setErrorMessageTemplate($this->_getErrorMessage());
                   27474:         $this->_isValid = 0;
                   27475:     }
                   27476: 
                   27477:     function installBinary($installer)
                   27478:     {
                   27479:         return false;
                   27480:     }
                   27481: 
                   27482:     function isExtension($name)
                   27483:     {
                   27484:         return false;
                   27485:     }
                   27486: 
                   27487:     function setConfig(&$config)
                   27488:     {
                   27489:         $this->_config = &$config;
                   27490:         $this->_registry = &$config->getRegistry();
                   27491:     }
                   27492: 
                   27493:     function setRequestedGroup()
                   27494:     {
                   27495:         // placeholder
                   27496:     }
                   27497: 
                   27498:     /**
                   27499:      * For saving in the registry.
                   27500:      *
                   27501:      * Set the last version that was installed
                   27502:      * @param string
                   27503:      */
                   27504:     function setLastInstalledVersion($version)
                   27505:     {
                   27506:         $this->_packageInfo['_lastversion'] = $version;
                   27507:     }
                   27508: 
                   27509:     /**
                   27510:      * @return string|false
                   27511:      */
                   27512:     function getLastInstalledVersion()
                   27513:     {
                   27514:         if (isset($this->_packageInfo['_lastversion'])) {
                   27515:             return $this->_packageInfo['_lastversion'];
                   27516:         }
                   27517:         return false;
                   27518:     }
                   27519: 
                   27520:     function getInstalledBinary()
                   27521:     {
                   27522:         return false;
                   27523:     }
                   27524: 
                   27525:     function listPostinstallScripts()
                   27526:     {
                   27527:         return false;
                   27528:     }
                   27529: 
                   27530:     function initPostinstallScripts()
                   27531:     {
                   27532:         return false;
                   27533:     }
                   27534: 
                   27535:     function setLogger(&$logger)
                   27536:     {
                   27537:         if ($logger && (!is_object($logger) || !method_exists($logger, 'log'))) {
                   27538:             return PEAR::raiseError('Logger must be compatible with PEAR_Common::log');
                   27539:         }
                   27540:         $this->_logger = &$logger;
                   27541:     }
                   27542: 
                   27543:     function setPackagefile($file, $archive = false)
                   27544:     {
                   27545:         $this->_packageFile = $file;
                   27546:         $this->_archiveFile = $archive ? $archive : $file;
                   27547:     }
                   27548: 
                   27549:     function getPackageFile()
                   27550:     {
                   27551:         return isset($this->_packageFile) ? $this->_packageFile : false;
                   27552:     }
                   27553: 
                   27554:     function getPackageType()
                   27555:     {
                   27556:         return 'php';
                   27557:     }
                   27558: 
                   27559:     function getArchiveFile()
                   27560:     {
                   27561:         return $this->_archiveFile;
                   27562:     }
                   27563: 
                   27564:     function packageInfo($field)
                   27565:     {
                   27566:         if (!is_string($field) || empty($field) ||
                   27567:             !isset($this->_packageInfo[$field])) {
                   27568:             return false;
                   27569:         }
                   27570:         return $this->_packageInfo[$field];
                   27571:     }
                   27572: 
                   27573:     function setDirtree($path)
                   27574:     {
                   27575:         if (!isset($this->_packageInfo['dirtree'])) {
                   27576:             $this->_packageInfo['dirtree'] = array();
                   27577:         }
                   27578:         $this->_packageInfo['dirtree'][$path] = true;
                   27579:     }
                   27580: 
                   27581:     function getDirtree()
                   27582:     {
                   27583:         if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) {
                   27584:             return $this->_packageInfo['dirtree'];
                   27585:         }
                   27586:         return false;
                   27587:     }
                   27588: 
                   27589:     function resetDirtree()
                   27590:     {
                   27591:         unset($this->_packageInfo['dirtree']);
                   27592:     }
                   27593: 
                   27594:     function fromArray($pinfo)
                   27595:     {
                   27596:         $this->_incomplete = false;
                   27597:         $this->_packageInfo = $pinfo;
                   27598:     }
                   27599: 
                   27600:     function isIncomplete()
                   27601:     {
                   27602:         return $this->_incomplete;
                   27603:     }
                   27604: 
                   27605:     function getChannel()
                   27606:     {
                   27607:         return 'pear.php.net';
                   27608:     }
                   27609: 
                   27610:     function getUri()
                   27611:     {
                   27612:         return false;
                   27613:     }
                   27614: 
                   27615:     function getTime()
                   27616:     {
                   27617:         return false;
                   27618:     }
                   27619: 
                   27620:     function getExtends()
                   27621:     {
                   27622:         if (isset($this->_packageInfo['extends'])) {
                   27623:             return $this->_packageInfo['extends'];
                   27624:         }
                   27625:         return false;
                   27626:     }
                   27627: 
                   27628:     /**
                   27629:      * @return array
                   27630:      */
                   27631:     function toArray()
                   27632:     {
                   27633:         if (!$this->validate(PEAR_VALIDATE_NORMAL)) {
                   27634:             return false;
                   27635:         }
                   27636:         return $this->getArray();
                   27637:     }
                   27638: 
                   27639:     function getArray()
                   27640:     {
                   27641:         return $this->_packageInfo;
                   27642:     }
                   27643: 
                   27644:     function getName()
                   27645:     {
                   27646:         return $this->getPackage();
                   27647:     }
                   27648: 
                   27649:     function getPackage()
                   27650:     {
                   27651:         if (isset($this->_packageInfo['package'])) {
                   27652:             return $this->_packageInfo['package'];
                   27653:         }
                   27654:         return false;
                   27655:     }
                   27656: 
                   27657:     /**
                   27658:      * WARNING - don't use this unless you know what you are doing
                   27659:      */
                   27660:     function setRawPackage($package)
                   27661:     {
                   27662:         $this->_packageInfo['package'] = $package;
                   27663:     }
                   27664: 
                   27665:     function setPackage($package)
                   27666:     {
                   27667:         $this->_packageInfo['package'] = $package;
                   27668:         $this->_isValid = false;
                   27669:     }
                   27670: 
                   27671:     function getVersion()
                   27672:     {
                   27673:         if (isset($this->_packageInfo['version'])) {
                   27674:             return $this->_packageInfo['version'];
                   27675:         }
                   27676:         return false;
                   27677:     }
                   27678: 
                   27679:     function setVersion($version)
                   27680:     {
                   27681:         $this->_packageInfo['version'] = $version;
                   27682:         $this->_isValid = false;
                   27683:     }
                   27684: 
                   27685:     function clearMaintainers()
                   27686:     {
                   27687:         unset($this->_packageInfo['maintainers']);
                   27688:     }
                   27689: 
                   27690:     function getMaintainers()
                   27691:     {
                   27692:         if (isset($this->_packageInfo['maintainers'])) {
                   27693:             return $this->_packageInfo['maintainers'];
                   27694:         }
                   27695:         return false;
                   27696:     }
                   27697: 
                   27698:     /**
                   27699:      * Adds a new maintainer - no checking of duplicates is performed, use
                   27700:      * updatemaintainer for that purpose.
                   27701:      */
                   27702:     function addMaintainer($role, $handle, $name, $email)
                   27703:     {
                   27704:         $this->_packageInfo['maintainers'][] =
                   27705:             array('handle' => $handle, 'role' => $role, 'email' => $email, 'name' => $name);
                   27706:         $this->_isValid = false;
                   27707:     }
                   27708: 
                   27709:     function updateMaintainer($role, $handle, $name, $email)
                   27710:     {
                   27711:         $found = false;
                   27712:         if (!isset($this->_packageInfo['maintainers']) ||
                   27713:               !is_array($this->_packageInfo['maintainers'])) {
                   27714:             return $this->addMaintainer($role, $handle, $name, $email);
                   27715:         }
                   27716:         foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) {
                   27717:             if ($maintainer['handle'] == $handle) {
                   27718:                 $found = $i;
                   27719:                 break;
                   27720:             }
                   27721:         }
                   27722:         if ($found !== false) {
                   27723:             unset($this->_packageInfo['maintainers'][$found]);
                   27724:             $this->_packageInfo['maintainers'] =
                   27725:                 array_values($this->_packageInfo['maintainers']);
                   27726:         }
                   27727:         $this->addMaintainer($role, $handle, $name, $email);
                   27728:     }
                   27729: 
                   27730:     function deleteMaintainer($handle)
                   27731:     {
                   27732:         $found = false;
                   27733:         foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) {
                   27734:             if ($maintainer['handle'] == $handle) {
                   27735:                 $found = $i;
                   27736:                 break;
                   27737:             }
                   27738:         }
                   27739:         if ($found !== false) {
                   27740:             unset($this->_packageInfo['maintainers'][$found]);
                   27741:             $this->_packageInfo['maintainers'] =
                   27742:                 array_values($this->_packageInfo['maintainers']);
                   27743:             return true;
                   27744:         }
                   27745:         return false;
                   27746:     }
                   27747: 
                   27748:     function getState()
                   27749:     {
                   27750:         if (isset($this->_packageInfo['release_state'])) {
                   27751:             return $this->_packageInfo['release_state'];
                   27752:         }
                   27753:         return false;
                   27754:     }
                   27755: 
                   27756:     function setRawState($state)
                   27757:     {
                   27758:         $this->_packageInfo['release_state'] = $state;
                   27759:     }
                   27760: 
                   27761:     function setState($state)
                   27762:     {
                   27763:         $this->_packageInfo['release_state'] = $state;
                   27764:         $this->_isValid = false;
                   27765:     }
                   27766: 
                   27767:     function getDate()
                   27768:     {
                   27769:         if (isset($this->_packageInfo['release_date'])) {
                   27770:             return $this->_packageInfo['release_date'];
                   27771:         }
                   27772:         return false;
                   27773:     }
                   27774: 
                   27775:     function setDate($date)
                   27776:     {
                   27777:         $this->_packageInfo['release_date'] = $date;
                   27778:         $this->_isValid = false;
                   27779:     }
                   27780: 
                   27781:     function getLicense()
                   27782:     {
                   27783:         if (isset($this->_packageInfo['release_license'])) {
                   27784:             return $this->_packageInfo['release_license'];
                   27785:         }
                   27786:         return false;
                   27787:     }
                   27788: 
                   27789:     function setLicense($date)
                   27790:     {
                   27791:         $this->_packageInfo['release_license'] = $date;
                   27792:         $this->_isValid = false;
                   27793:     }
                   27794: 
                   27795:     function getSummary()
                   27796:     {
                   27797:         if (isset($this->_packageInfo['summary'])) {
                   27798:             return $this->_packageInfo['summary'];
                   27799:         }
                   27800:         return false;
                   27801:     }
                   27802: 
                   27803:     function setSummary($summary)
                   27804:     {
                   27805:         $this->_packageInfo['summary'] = $summary;
                   27806:         $this->_isValid = false;
                   27807:     }
                   27808: 
                   27809:     function getDescription()
                   27810:     {
                   27811:         if (isset($this->_packageInfo['description'])) {
                   27812:             return $this->_packageInfo['description'];
                   27813:         }
                   27814:         return false;
                   27815:     }
                   27816: 
                   27817:     function setDescription($desc)
                   27818:     {
                   27819:         $this->_packageInfo['description'] = $desc;
                   27820:         $this->_isValid = false;
                   27821:     }
                   27822: 
                   27823:     function getNotes()
                   27824:     {
                   27825:         if (isset($this->_packageInfo['release_notes'])) {
                   27826:             return $this->_packageInfo['release_notes'];
                   27827:         }
                   27828:         return false;
                   27829:     }
                   27830: 
                   27831:     function setNotes($notes)
                   27832:     {
                   27833:         $this->_packageInfo['release_notes'] = $notes;
                   27834:         $this->_isValid = false;
                   27835:     }
                   27836: 
                   27837:     function getDeps()
                   27838:     {
                   27839:         if (isset($this->_packageInfo['release_deps'])) {
                   27840:             return $this->_packageInfo['release_deps'];
                   27841:         }
                   27842:         return false;
                   27843:     }
                   27844: 
                   27845:     /**
                   27846:      * Reset dependencies prior to adding new ones
                   27847:      */
                   27848:     function clearDeps()
                   27849:     {
                   27850:         unset($this->_packageInfo['release_deps']);
                   27851:     }
                   27852: 
                   27853:     function addPhpDep($version, $rel)
                   27854:     {
                   27855:         $this->_isValid = false;
                   27856:         $this->_packageInfo['release_deps'][] =
                   27857:             array('type' => 'php',
                   27858:                   'rel' => $rel,
                   27859:                   'version' => $version);
                   27860:     }
                   27861: 
                   27862:     function addPackageDep($name, $version, $rel, $optional = 'no')
                   27863:     {
                   27864:         $this->_isValid = false;
                   27865:         $dep =
                   27866:             array('type' => 'pkg',
                   27867:                   'name' => $name,
                   27868:                   'rel' => $rel,
                   27869:                   'optional' => $optional);
                   27870:         if ($rel != 'has' && $rel != 'not') {
                   27871:             $dep['version'] = $version;
                   27872:         }
                   27873:         $this->_packageInfo['release_deps'][] = $dep;
                   27874:     }
                   27875: 
                   27876:     function addExtensionDep($name, $version, $rel, $optional = 'no')
                   27877:     {
                   27878:         $this->_isValid = false;
                   27879:         $this->_packageInfo['release_deps'][] =
                   27880:             array('type' => 'ext',
                   27881:                   'name' => $name,
                   27882:                   'rel' => $rel,
                   27883:                   'version' => $version,
                   27884:                   'optional' => $optional);
                   27885:     }
                   27886: 
                   27887:     /**
                   27888:      * WARNING - do not use this function directly unless you know what you're doing
                   27889:      */
                   27890:     function setDeps($deps)
                   27891:     {
                   27892:         $this->_packageInfo['release_deps'] = $deps;
                   27893:     }
                   27894: 
                   27895:     function hasDeps()
                   27896:     {
                   27897:         return isset($this->_packageInfo['release_deps']) &&
                   27898:             count($this->_packageInfo['release_deps']);
                   27899:     }
                   27900: 
                   27901:     function getDependencyGroup($group)
                   27902:     {
                   27903:         return false;
                   27904:     }
                   27905: 
                   27906:     function isCompatible($pf)
                   27907:     {
                   27908:         return false;
                   27909:     }
                   27910: 
                   27911:     function isSubpackageOf($p)
                   27912:     {
                   27913:         return $p->isSubpackage($this);
                   27914:     }
                   27915: 
                   27916:     function isSubpackage($p)
                   27917:     {
                   27918:         return false;
                   27919:     }
                   27920: 
                   27921:     function dependsOn($package, $channel)
                   27922:     {
                   27923:         if (strtolower($channel) != 'pear.php.net') {
                   27924:             return false;
                   27925:         }
                   27926:         if (!($deps = $this->getDeps())) {
                   27927:             return false;
                   27928:         }
                   27929:         foreach ($deps as $dep) {
                   27930:             if ($dep['type'] != 'pkg') {
                   27931:                 continue;
                   27932:             }
                   27933:             if (strtolower($dep['name']) == strtolower($package)) {
                   27934:                 return true;
                   27935:             }
                   27936:         }
                   27937:         return false;
                   27938:     }
                   27939: 
                   27940:     function getConfigureOptions()
                   27941:     {
                   27942:         if (isset($this->_packageInfo['configure_options'])) {
                   27943:             return $this->_packageInfo['configure_options'];
                   27944:         }
                   27945:         return false;
                   27946:     }
                   27947: 
                   27948:     function hasConfigureOptions()
                   27949:     {
                   27950:         return isset($this->_packageInfo['configure_options']) &&
                   27951:             count($this->_packageInfo['configure_options']);
                   27952:     }
                   27953: 
                   27954:     function addConfigureOption($name, $prompt, $default = false)
                   27955:     {
                   27956:         $o = array('name' => $name, 'prompt' => $prompt);
                   27957:         if ($default !== false) {
                   27958:             $o['default'] = $default;
                   27959:         }
                   27960:         if (!isset($this->_packageInfo['configure_options'])) {
                   27961:             $this->_packageInfo['configure_options'] = array();
                   27962:         }
                   27963:         $this->_packageInfo['configure_options'][] = $o;
                   27964:     }
                   27965: 
                   27966:     function clearConfigureOptions()
                   27967:     {
                   27968:         unset($this->_packageInfo['configure_options']);
                   27969:     }
                   27970: 
                   27971:     function getProvides()
                   27972:     {
                   27973:         if (isset($this->_packageInfo['provides'])) {
                   27974:             return $this->_packageInfo['provides'];
                   27975:         }
                   27976:         return false;
                   27977:     }
                   27978: 
                   27979:     function getProvidesExtension()
                   27980:     {
                   27981:         return false;
                   27982:     }
                   27983: 
                   27984:     function addFile($dir, $file, $attrs)
                   27985:     {
                   27986:         $dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir);
                   27987:         if ($dir == '/' || $dir == '') {
                   27988:             $dir = '';
                   27989:         } else {
                   27990:             $dir .= '/';
                   27991:         }
                   27992:         $file = $dir . $file;
                   27993:         $file = preg_replace('![\\/]+!', '/', $file);
                   27994:         $this->_packageInfo['filelist'][$file] = $attrs;
                   27995:     }
                   27996: 
                   27997:     function getInstallationFilelist()
                   27998:     {
                   27999:         return $this->getFilelist();
                   28000:     }
                   28001: 
                   28002:     function getFilelist()
                   28003:     {
                   28004:         if (isset($this->_packageInfo['filelist'])) {
                   28005:             return $this->_packageInfo['filelist'];
                   28006:         }
                   28007:         return false;
                   28008:     }
                   28009: 
                   28010:     function setFileAttribute($file, $attr, $value)
                   28011:     {
                   28012:         $this->_packageInfo['filelist'][$file][$attr] = $value;
                   28013:     }
                   28014: 
                   28015:     function resetFilelist()
                   28016:     {
                   28017:         $this->_packageInfo['filelist'] = array();
                   28018:     }
                   28019: 
                   28020:     function setInstalledAs($file, $path)
                   28021:     {
                   28022:         if ($path) {
                   28023:             return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
                   28024:         }
                   28025:         unset($this->_packageInfo['filelist'][$file]['installed_as']);
                   28026:     }
                   28027: 
                   28028:     function installedFile($file, $atts)
                   28029:     {
                   28030:         if (isset($this->_packageInfo['filelist'][$file])) {
                   28031:             $this->_packageInfo['filelist'][$file] =
                   28032:                 array_merge($this->_packageInfo['filelist'][$file], $atts);
                   28033:         } else {
                   28034:             $this->_packageInfo['filelist'][$file] = $atts;
                   28035:         }
                   28036:     }
                   28037: 
                   28038:     function getChangelog()
                   28039:     {
                   28040:         if (isset($this->_packageInfo['changelog'])) {
                   28041:             return $this->_packageInfo['changelog'];
                   28042:         }
                   28043:         return false;
                   28044:     }
                   28045: 
                   28046:     function getPackagexmlVersion()
                   28047:     {
                   28048:         return '1.0';
                   28049:     }
                   28050: 
                   28051:     /**
                   28052:      * Wrapper to {@link PEAR_ErrorStack::getErrors()}
                   28053:      * @param boolean determines whether to purge the error stack after retrieving
                   28054:      * @return array
                   28055:      */
                   28056:     function getValidationWarnings($purge = true)
                   28057:     {
                   28058:         return $this->_stack->getErrors($purge);
                   28059:     }
                   28060: 
                   28061:     // }}}
                   28062:     /**
                   28063:      * Validation error.  Also marks the object contents as invalid
                   28064:      * @param error code
                   28065:      * @param array error information
                   28066:      * @access private
                   28067:      */
                   28068:     function _validateError($code, $params = array())
                   28069:     {
                   28070:         $this->_stack->push($code, 'error', $params, false, false, debug_backtrace());
                   28071:         $this->_isValid = false;
                   28072:     }
                   28073: 
                   28074:     /**
                   28075:      * Validation warning.  Does not mark the object contents invalid.
                   28076:      * @param error code
                   28077:      * @param array error information
                   28078:      * @access private
                   28079:      */
                   28080:     function _validateWarning($code, $params = array())
                   28081:     {
                   28082:         $this->_stack->push($code, 'warning', $params, false, false, debug_backtrace());
                   28083:     }
                   28084: 
                   28085:     /**
                   28086:      * @param integer error code
                   28087:      * @access protected
                   28088:      */
                   28089:     function _getErrorMessage()
                   28090:     {
                   28091:         return array(
                   28092:                 PEAR_PACKAGEFILE_ERROR_NO_NAME =>
                   28093:                     'Missing Package Name',
                   28094:                 PEAR_PACKAGEFILE_ERROR_NO_SUMMARY =>
                   28095:                     'No summary found',
                   28096:                 PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY =>
                   28097:                     'Summary should be on one line',
                   28098:                 PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION =>
                   28099:                     'Missing description',
                   28100:                 PEAR_PACKAGEFILE_ERROR_NO_LICENSE =>
                   28101:                     'Missing license',
                   28102:                 PEAR_PACKAGEFILE_ERROR_NO_VERSION =>
                   28103:                     'No release version found',
                   28104:                 PEAR_PACKAGEFILE_ERROR_NO_STATE =>
                   28105:                     'No release state found',
                   28106:                 PEAR_PACKAGEFILE_ERROR_NO_DATE =>
                   28107:                     'No release date found',
                   28108:                 PEAR_PACKAGEFILE_ERROR_NO_NOTES =>
                   28109:                     'No release notes found',
                   28110:                 PEAR_PACKAGEFILE_ERROR_NO_LEAD =>
                   28111:                     'Package must have at least one lead maintainer',
                   28112:                 PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS =>
                   28113:                     'No maintainers found, at least one must be defined',
                   28114:                 PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE =>
                   28115:                     'Maintainer %index% has no handle (user ID at channel server)',
                   28116:                 PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE =>
                   28117:                     'Maintainer %index% has no role',
                   28118:                 PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME =>
                   28119:                     'Maintainer %index% has no name',
                   28120:                 PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL =>
                   28121:                     'Maintainer %index% has no email',
                   28122:                 PEAR_PACKAGEFILE_ERROR_NO_DEPNAME =>
                   28123:                     'Dependency %index% is not a php dependency, and has no name',
                   28124:                 PEAR_PACKAGEFILE_ERROR_NO_DEPREL =>
                   28125:                     'Dependency %index% has no relation (rel)',
                   28126:                 PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE =>
                   28127:                     'Dependency %index% has no type',
                   28128:                 PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED =>
                   28129:                     'PHP Dependency %index% has a name attribute of "%name%" which will be' .
                   28130:                         ' ignored!',
                   28131:                 PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION =>
                   28132:                     'Dependency %index% is not a rel="has" or rel="not" dependency, ' .
                   28133:                         'and has no version',
                   28134:                 PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION =>
                   28135:                     'Dependency %index% is a type="php" dependency, ' .
                   28136:                         'and has no version',
                   28137:                 PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED =>
                   28138:                     'Dependency %index% is a rel="%rel%" dependency, versioning is ignored',
                   28139:                 PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL =>
                   28140:                     'Dependency %index% has invalid optional value "%opt%", should be yes or no',
                   28141:                 PEAR_PACKAGEFILE_PHP_NO_NOT =>
                   28142:                     'Dependency %index%: php dependencies cannot use "not" rel, use "ne"' .
                   28143:                         ' to exclude specific versions',
                   28144:                 PEAR_PACKAGEFILE_ERROR_NO_CONFNAME =>
                   28145:                     'Configure Option %index% has no name',
                   28146:                 PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT =>
                   28147:                     'Configure Option %index% has no prompt',
                   28148:                 PEAR_PACKAGEFILE_ERROR_NO_FILES =>
                   28149:                     'No files in <filelist> section of package.xml',
                   28150:                 PEAR_PACKAGEFILE_ERROR_NO_FILEROLE =>
                   28151:                     'File "%file%" has no role, expecting one of "%roles%"',
                   28152:                 PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE =>
                   28153:                     'File "%file%" has invalid role "%role%", expecting one of "%roles%"',
                   28154:                 PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME =>
                   28155:                     'File "%file%" cannot start with ".", cannot package or install',
                   28156:                 PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE =>
                   28157:                     'Parser error: invalid PHP found in file "%file%"',
                   28158:                 PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX =>
                   28159:                     'in %file%: %type% "%name%" not prefixed with package name "%package%"',
                   28160:                 PEAR_PACKAGEFILE_ERROR_INVALID_FILE =>
                   28161:                     'Parser error: invalid PHP file "%file%"',
                   28162:                 PEAR_PACKAGEFILE_ERROR_CHANNELVAL =>
                   28163:                     'Channel validator error: field "%field%" - %reason%',
                   28164:                 PEAR_PACKAGEFILE_ERROR_PHP5 =>
                   28165:                     'Error, PHP5 token encountered in %file%, analysis should be in PHP5',
                   28166:                 PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND =>
                   28167:                     'File "%file%" in package.xml does not exist',
                   28168:                 PEAR_PACKAGEFILE_ERROR_NON_ISO_CHARS =>
                   28169:                     'Package.xml contains non-ISO-8859-1 characters, and may not validate',
                   28170:             );
                   28171:     }
                   28172: 
                   28173:     /**
                   28174:      * Validate XML package definition file.
                   28175:      *
                   28176:      * @access public
                   28177:      * @return boolean
                   28178:      */
                   28179:     function validate($state = PEAR_VALIDATE_NORMAL, $nofilechecking = false)
                   28180:     {
                   28181:         if (($this->_isValid & $state) == $state) {
                   28182:             return true;
                   28183:         }
                   28184:         $this->_isValid = true;
                   28185:         $info = $this->_packageInfo;
                   28186:         if (empty($info['package'])) {
                   28187:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NAME);
                   28188:             $this->_packageName = $pn = 'unknown';
                   28189:         } else {
                   28190:             $this->_packageName = $pn = $info['package'];
                   28191:         }
                   28192: 
                   28193:         if (empty($info['summary'])) {
                   28194:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_SUMMARY);
                   28195:         } elseif (strpos(trim($info['summary']), "\n") !== false) {
                   28196:             $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY,
                   28197:                 array('summary' => $info['summary']));
                   28198:         }
                   28199:         if (empty($info['description'])) {
                   28200:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION);
                   28201:         }
                   28202:         if (empty($info['release_license'])) {
                   28203:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LICENSE);
                   28204:         }
                   28205:         if (empty($info['version'])) {
                   28206:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_VERSION);
                   28207:         }
                   28208:         if (empty($info['release_state'])) {
                   28209:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_STATE);
                   28210:         }
                   28211:         if (empty($info['release_date'])) {
                   28212:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DATE);
                   28213:         }
                   28214:         if (empty($info['release_notes'])) {
                   28215:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NOTES);
                   28216:         }
                   28217:         if (empty($info['maintainers'])) {
                   28218:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS);
                   28219:         } else {
                   28220:             $haslead = false;
                   28221:             $i = 1;
                   28222:             foreach ($info['maintainers'] as $m) {
                   28223:                 if (empty($m['handle'])) {
                   28224:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE,
                   28225:                         array('index' => $i));
                   28226:                 }
                   28227:                 if (empty($m['role'])) {
                   28228:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE,
                   28229:                         array('index' => $i, 'roles' => PEAR_Common::getUserRoles()));
                   28230:                 } elseif ($m['role'] == 'lead') {
                   28231:                     $haslead = true;
                   28232:                 }
                   28233:                 if (empty($m['name'])) {
                   28234:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME,
                   28235:                         array('index' => $i));
                   28236:                 }
                   28237:                 if (empty($m['email'])) {
                   28238:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL,
                   28239:                         array('index' => $i));
                   28240:                 }
                   28241:                 $i++;
                   28242:             }
                   28243:             if (!$haslead) {
                   28244:                 $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LEAD);
                   28245:             }
                   28246:         }
                   28247:         if (!empty($info['release_deps'])) {
                   28248:             $i = 1;
                   28249:             foreach ($info['release_deps'] as $d) {
                   28250:                 if (!isset($d['type']) || empty($d['type'])) {
                   28251:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE,
                   28252:                         array('index' => $i, 'types' => PEAR_Common::getDependencyTypes()));
                   28253:                     continue;
                   28254:                 }
                   28255:                 if (!isset($d['rel']) || empty($d['rel'])) {
                   28256:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPREL,
                   28257:                         array('index' => $i, 'rels' => PEAR_Common::getDependencyRelations()));
                   28258:                     continue;
                   28259:                 }
                   28260:                 if (!empty($d['optional'])) {
                   28261:                     if (!in_array($d['optional'], array('yes', 'no'))) {
                   28262:                         $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL,
                   28263:                             array('index' => $i, 'opt' => $d['optional']));
                   28264:                     }
                   28265:                 }
                   28266:                 if ($d['rel'] != 'has' && $d['rel'] != 'not' && empty($d['version'])) {
                   28267:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION,
                   28268:                         array('index' => $i));
                   28269:                 } elseif (($d['rel'] == 'has' || $d['rel'] == 'not') && !empty($d['version'])) {
                   28270:                     $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED,
                   28271:                         array('index' => $i, 'rel' => $d['rel']));
                   28272:                 }
                   28273:                 if ($d['type'] == 'php' && !empty($d['name'])) {
                   28274:                     $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED,
                   28275:                         array('index' => $i, 'name' => $d['name']));
                   28276:                 } elseif ($d['type'] != 'php' && empty($d['name'])) {
                   28277:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPNAME,
                   28278:                         array('index' => $i));
                   28279:                 }
                   28280:                 if ($d['type'] == 'php' && empty($d['version'])) {
                   28281:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION,
                   28282:                         array('index' => $i));
                   28283:                 }
                   28284:                 if (($d['rel'] == 'not') && ($d['type'] == 'php')) {
                   28285:                     $this->_validateError(PEAR_PACKAGEFILE_PHP_NO_NOT,
                   28286:                         array('index' => $i));
                   28287:                 }
                   28288:                 $i++;
                   28289:             }
                   28290:         }
                   28291:         if (!empty($info['configure_options'])) {
                   28292:             $i = 1;
                   28293:             foreach ($info['configure_options'] as $c) {
                   28294:                 if (empty($c['name'])) {
                   28295:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFNAME,
                   28296:                         array('index' => $i));
                   28297:                 }
                   28298:                 if (empty($c['prompt'])) {
                   28299:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT,
                   28300:                         array('index' => $i));
                   28301:                 }
                   28302:                 $i++;
                   28303:             }
                   28304:         }
                   28305:         if (empty($info['filelist'])) {
                   28306:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILES);
                   28307:             $errors[] = 'no files';
                   28308:         } else {
                   28309:             foreach ($info['filelist'] as $file => $fa) {
                   28310:                 if (empty($fa['role'])) {
                   28311:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILEROLE,
                   28312:                         array('file' => $file, 'roles' => PEAR_Common::getFileRoles()));
                   28313:                     continue;
                   28314:                 } elseif (!in_array($fa['role'], PEAR_Common::getFileRoles())) {
                   28315:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE,
                   28316:                         array('file' => $file, 'role' => $fa['role'], 'roles' => PEAR_Common::getFileRoles()));
                   28317:                 }
                   28318:                 if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', str_replace('\\', '/', $file))) {
                   28319:                     // file contains .. parent directory or . cur directory references
                   28320:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
                   28321:                         array('file' => $file));
                   28322:                 }
                   28323:                 if (isset($fa['install-as']) &&
                   28324:                       preg_match('~/\.\.?(/|\\z)|^\.\.?/~', 
                   28325:                                  str_replace('\\', '/', $fa['install-as']))) {
                   28326:                     // install-as contains .. parent directory or . cur directory references
                   28327:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
                   28328:                         array('file' => $file . ' [installed as ' . $fa['install-as'] . ']'));
                   28329:                 }
                   28330:                 if (isset($fa['baseinstalldir']) &&
                   28331:                       preg_match('~/\.\.?(/|\\z)|^\.\.?/~', 
                   28332:                                  str_replace('\\', '/', $fa['baseinstalldir']))) {
                   28333:                     // install-as contains .. parent directory or . cur directory references
                   28334:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
                   28335:                         array('file' => $file . ' [baseinstalldir ' . $fa['baseinstalldir'] . ']'));
                   28336:                 }
                   28337:             }
                   28338:         }
                   28339:         if (isset($this->_registry) && $this->_isValid) {
                   28340:             $chan = $this->_registry->getChannel('pear.php.net');
                   28341:             if (PEAR::isError($chan)) {
                   28342:                 $this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $chan->getMessage());
                   28343:                 return $this->_isValid = 0;
                   28344:             }
                   28345:             $validator = $chan->getValidationObject();
                   28346:             $validator->setPackageFile($this);
                   28347:             $validator->validate($state);
                   28348:             $failures = $validator->getFailures();
                   28349:             foreach ($failures['errors'] as $error) {
                   28350:                 $this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $error);
                   28351:             }
                   28352:             foreach ($failures['warnings'] as $warning) {
                   28353:                 $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $warning);
                   28354:             }
                   28355:         }
                   28356:         if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$nofilechecking) {
                   28357:             if ($this->_analyzePhpFiles()) {
                   28358:                 $this->_isValid = true;
                   28359:             }
                   28360:         }
                   28361:         if ($this->_isValid) {
                   28362:             return $this->_isValid = $state;
                   28363:         }
                   28364:         return $this->_isValid = 0;
                   28365:     }
                   28366: 
                   28367:     function _analyzePhpFiles()
                   28368:     {
                   28369:         if (!$this->_isValid) {
                   28370:             return false;
                   28371:         }
                   28372:         if (!isset($this->_packageFile)) {
                   28373:             return false;
                   28374:         }
                   28375:         $dir_prefix = dirname($this->_packageFile);
                   28376:         $common = new PEAR_Common;
                   28377:         $log = isset($this->_logger) ? array(&$this->_logger, 'log') :
                   28378:             array($common, 'log');
                   28379:         $info = $this->getFilelist();
                   28380:         foreach ($info as $file => $fa) {
                   28381:             if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) {
                   28382:                 $this->_validateError(PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND,
                   28383:                     array('file' => realpath($dir_prefix) . DIRECTORY_SEPARATOR . $file));
                   28384:                 continue;
                   28385:             }
                   28386:             if ($fa['role'] == 'php' && $dir_prefix) {
                   28387:                 call_user_func_array($log, array(1, "Analyzing $file"));
                   28388:                 $srcinfo = $this->_analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file);
                   28389:                 if ($srcinfo) {
                   28390:                     $this->_buildProvidesArray($srcinfo);
                   28391:                 }
                   28392:             }
                   28393:         }
                   28394:         $this->_packageName = $pn = $this->getPackage();
                   28395:         $pnl = strlen($pn);
                   28396:         if (isset($this->_packageInfo['provides'])) {
                   28397:             foreach ((array) $this->_packageInfo['provides'] as $key => $what) {
                   28398:                 if (isset($what['explicit'])) {
                   28399:                     // skip conformance checks if the provides entry is
                   28400:                     // specified in the package.xml file
                   28401:                     continue;
                   28402:                 }
                   28403:                 extract($what);
                   28404:                 if ($type == 'class') {
                   28405:                     if (!strncasecmp($name, $pn, $pnl)) {
                   28406:                         continue;
                   28407:                     }
                   28408:                     $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX,
                   28409:                         array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn));
                   28410:                 } elseif ($type == 'function') {
                   28411:                     if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) {
                   28412:                         continue;
                   28413:                     }
                   28414:                     $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX,
                   28415:                         array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn));
                   28416:                 }
                   28417:             }
                   28418:         }
                   28419:         return $this->_isValid;
                   28420:     }
                   28421: 
                   28422:     /**
                   28423:      * Get the default xml generator object
                   28424:      *
                   28425:      * @return PEAR_PackageFile_Generator_v1
                   28426:      */
                   28427:     function &getDefaultGenerator()
                   28428:     {
                   28429:         if (!class_exists('PEAR_PackageFile_Generator_v1')) {
                   28430:             require_once 'PEAR/PackageFile/Generator/v1.php';
                   28431:         }
                   28432:         $a = &new PEAR_PackageFile_Generator_v1($this);
                   28433:         return $a;
                   28434:     }
                   28435: 
                   28436:     /**
                   28437:      * Get the contents of a file listed within the package.xml
                   28438:      * @param string
                   28439:      * @return string
                   28440:      */
                   28441:     function getFileContents($file)
                   28442:     {
                   28443:         if ($this->_archiveFile == $this->_packageFile) { // unpacked
                   28444:             $dir = dirname($this->_packageFile);
                   28445:             $file = $dir . DIRECTORY_SEPARATOR . $file;
                   28446:             $file = str_replace(array('/', '\\'),
                   28447:                 array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file);
                   28448:             if (file_exists($file) && is_readable($file)) {
                   28449:                 return implode('', file($file));
                   28450:             }
                   28451:         } else { // tgz
                   28452:             if (!class_exists('Archive_Tar')) {
                   28453:                 require_once 'Archive/Tar.php';
                   28454:             }
                   28455:             $tar = &new Archive_Tar($this->_archiveFile);
                   28456:             $tar->pushErrorHandling(PEAR_ERROR_RETURN);
                   28457:             if ($file != 'package.xml' && $file != 'package2.xml') {
                   28458:                 $file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file;
                   28459:             }
                   28460:             $file = $tar->extractInString($file);
                   28461:             $tar->popErrorHandling();
                   28462:             if (PEAR::isError($file)) {
                   28463:                 return PEAR::raiseError("Cannot locate file '$file' in archive");
                   28464:             }
                   28465:             return $file;
                   28466:         }
                   28467:     }
                   28468: 
                   28469:     // {{{ analyzeSourceCode()
                   28470:     /**
                   28471:      * Analyze the source code of the given PHP file
                   28472:      *
                   28473:      * @param  string Filename of the PHP file
                   28474:      * @return mixed
                   28475:      * @access private
                   28476:      */
                   28477:     function _analyzeSourceCode($file)
                   28478:     {
                   28479:         if (!function_exists("token_get_all")) {
                   28480:             return false;
                   28481:         }
                   28482:         if (!defined('T_DOC_COMMENT')) {
                   28483:             define('T_DOC_COMMENT', T_COMMENT);
                   28484:         }
                   28485:         if (!defined('T_INTERFACE')) {
                   28486:             define('T_INTERFACE', -1);
                   28487:         }
                   28488:         if (!defined('T_IMPLEMENTS')) {
                   28489:             define('T_IMPLEMENTS', -1);
                   28490:         }
                   28491:         if (!$fp = @fopen($file, "r")) {
                   28492:             return false;
                   28493:         }
                   28494:         fclose($fp);
                   28495:         $contents = file_get_contents($file);
                   28496:         $tokens = token_get_all($contents);
                   28497: /*
                   28498:         for ($i = 0; $i < sizeof($tokens); $i++) {
                   28499:             @list($token, $data) = $tokens[$i];
                   28500:             if (is_string($token)) {
                   28501:                 var_dump($token);
                   28502:             } else {
                   28503:                 print token_name($token) . ' ';
                   28504:                 var_dump(rtrim($data));
                   28505:             }
                   28506:         }
                   28507: */
                   28508:         $look_for = 0;
                   28509:         $paren_level = 0;
                   28510:         $bracket_level = 0;
                   28511:         $brace_level = 0;
                   28512:         $lastphpdoc = '';
                   28513:         $current_class = '';
                   28514:         $current_interface = '';
                   28515:         $current_class_level = -1;
                   28516:         $current_function = '';
                   28517:         $current_function_level = -1;
                   28518:         $declared_classes = array();
                   28519:         $declared_interfaces = array();
                   28520:         $declared_functions = array();
                   28521:         $declared_methods = array();
                   28522:         $used_classes = array();
                   28523:         $used_functions = array();
                   28524:         $extends = array();
                   28525:         $implements = array();
                   28526:         $nodeps = array();
                   28527:         $inquote = false;
                   28528:         $interface = false;
                   28529:         for ($i = 0; $i < sizeof($tokens); $i++) {
                   28530:             if (is_array($tokens[$i])) {
                   28531:                 list($token, $data) = $tokens[$i];
                   28532:             } else {
                   28533:                 $token = $tokens[$i];
                   28534:                 $data = '';
                   28535:             }
                   28536:             if ($inquote) {
                   28537:                 if ($token != '"' && $token != T_END_HEREDOC) {
                   28538:                     continue;
                   28539:                 } else {
                   28540:                     $inquote = false;
                   28541:                     continue;
                   28542:                 }
                   28543:             }
                   28544:             switch ($token) {
                   28545:                 case T_WHITESPACE :
                   28546:                     continue;
                   28547:                 case ';':
                   28548:                     if ($interface) {
                   28549:                         $current_function = '';
                   28550:                         $current_function_level = -1;
                   28551:                     }
                   28552:                     break;
                   28553:                 case '"':
                   28554:                 case T_START_HEREDOC:
                   28555:                     $inquote = true;
                   28556:                     break;
                   28557:                 case T_CURLY_OPEN:
                   28558:                 case T_DOLLAR_OPEN_CURLY_BRACES:
                   28559:                 case '{': $brace_level++; continue 2;
                   28560:                 case '}':
                   28561:                     $brace_level--;
                   28562:                     if ($current_class_level == $brace_level) {
                   28563:                         $current_class = '';
                   28564:                         $current_class_level = -1;
                   28565:                     }
                   28566:                     if ($current_function_level == $brace_level) {
                   28567:                         $current_function = '';
                   28568:                         $current_function_level = -1;
                   28569:                     }
                   28570:                     continue 2;
                   28571:                 case '[': $bracket_level++; continue 2;
                   28572:                 case ']': $bracket_level--; continue 2;
                   28573:                 case '(': $paren_level++;   continue 2;
                   28574:                 case ')': $paren_level--;   continue 2;
                   28575:                 case T_INTERFACE:
                   28576:                     $interface = true;
                   28577:                 case T_CLASS:
                   28578:                     if (($current_class_level != -1) || ($current_function_level != -1)) {
                   28579:                         $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE,
                   28580:                             array('file' => $file));
                   28581:                         return false;
                   28582:                     }
                   28583:                 case T_FUNCTION:
                   28584:                 case T_NEW:
                   28585:                 case T_EXTENDS:
                   28586:                 case T_IMPLEMENTS:
                   28587:                     $look_for = $token;
                   28588:                     continue 2;
                   28589:                 case T_STRING:
                   28590:                     if (version_compare(zend_version(), '2.0', '<')) {
                   28591:                         if (in_array(strtolower($data),
                   28592:                             array('public', 'private', 'protected', 'abstract',
                   28593:                                   'interface', 'implements', 'throw') 
                   28594:                                  )) {
                   28595:                             $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_PHP5,
                   28596:                                 array($file));
                   28597:                         }
                   28598:                     }
                   28599:                     if ($look_for == T_CLASS) {
                   28600:                         $current_class = $data;
                   28601:                         $current_class_level = $brace_level;
                   28602:                         $declared_classes[] = $current_class;
                   28603:                     } elseif ($look_for == T_INTERFACE) {
                   28604:                         $current_interface = $data;
                   28605:                         $current_class_level = $brace_level;
                   28606:                         $declared_interfaces[] = $current_interface;
                   28607:                     } elseif ($look_for == T_IMPLEMENTS) {
                   28608:                         $implements[$current_class] = $data;
                   28609:                     } elseif ($look_for == T_EXTENDS) {
                   28610:                         $extends[$current_class] = $data;
                   28611:                     } elseif ($look_for == T_FUNCTION) {
                   28612:                         if ($current_class) {
                   28613:                             $current_function = "$current_class::$data";
                   28614:                             $declared_methods[$current_class][] = $data;
                   28615:                         } elseif ($current_interface) {
                   28616:                             $current_function = "$current_interface::$data";
                   28617:                             $declared_methods[$current_interface][] = $data;
                   28618:                         } else {
                   28619:                             $current_function = $data;
                   28620:                             $declared_functions[] = $current_function;
                   28621:                         }
                   28622:                         $current_function_level = $brace_level;
                   28623:                         $m = array();
                   28624:                     } elseif ($look_for == T_NEW) {
                   28625:                         $used_classes[$data] = true;
                   28626:                     }
                   28627:                     $look_for = 0;
                   28628:                     continue 2;
                   28629:                 case T_VARIABLE:
                   28630:                     $look_for = 0;
                   28631:                     continue 2;
                   28632:                 case T_DOC_COMMENT:
                   28633:                 case T_COMMENT:
                   28634:                     if (preg_match('!^/\*\*\s!', $data)) {
                   28635:                         $lastphpdoc = $data;
                   28636:                         if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) {
                   28637:                             $nodeps = array_merge($nodeps, $m[1]);
                   28638:                         }
                   28639:                     }
                   28640:                     continue 2;
                   28641:                 case T_DOUBLE_COLON:
                   28642:                     if (!($tokens[$i - 1][0] == T_WHITESPACE || $tokens[$i - 1][0] == T_STRING)) {
                   28643:                         $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE,
                   28644:                             array('file' => $file));
                   28645:                         return false;
                   28646:                     }
                   28647:                     $class = $tokens[$i - 1][1];
                   28648:                     if (strtolower($class) != 'parent') {
                   28649:                         $used_classes[$class] = true;
                   28650:                     }
                   28651:                     continue 2;
                   28652:             }
                   28653:         }
                   28654:         return array(
                   28655:             "source_file" => $file,
                   28656:             "declared_classes" => $declared_classes,
                   28657:             "declared_interfaces" => $declared_interfaces,
                   28658:             "declared_methods" => $declared_methods,
                   28659:             "declared_functions" => $declared_functions,
                   28660:             "used_classes" => array_diff(array_keys($used_classes), $nodeps),
                   28661:             "inheritance" => $extends,
                   28662:             "implements" => $implements,
                   28663:             );
                   28664:     }
                   28665: 
                   28666:     /**
                   28667:      * Build a "provides" array from data returned by
                   28668:      * analyzeSourceCode().  The format of the built array is like
                   28669:      * this:
                   28670:      *
                   28671:      *  array(
                   28672:      *    'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
                   28673:      *    ...
                   28674:      *  )
                   28675:      *
                   28676:      *
                   28677:      * @param array $srcinfo array with information about a source file
                   28678:      * as returned by the analyzeSourceCode() method.
                   28679:      *
                   28680:      * @return void
                   28681:      *
                   28682:      * @access private
                   28683:      *
                   28684:      */
                   28685:     function _buildProvidesArray($srcinfo)
                   28686:     {
                   28687:         if (!$this->_isValid) {
                   28688:             return false;
                   28689:         }
                   28690:         $file = basename($srcinfo['source_file']);
                   28691:         $pn = $this->getPackage();
                   28692:         $pnl = strlen($pn);
                   28693:         foreach ($srcinfo['declared_classes'] as $class) {
                   28694:             $key = "class;$class";
                   28695:             if (isset($this->_packageInfo['provides'][$key])) {
                   28696:                 continue;
                   28697:             }
                   28698:             $this->_packageInfo['provides'][$key] =
                   28699:                 array('file'=> $file, 'type' => 'class', 'name' => $class);
                   28700:             if (isset($srcinfo['inheritance'][$class])) {
                   28701:                 $this->_packageInfo['provides'][$key]['extends'] =
                   28702:                     $srcinfo['inheritance'][$class];
                   28703:             }
                   28704:         }
                   28705:         foreach ($srcinfo['declared_methods'] as $class => $methods) {
                   28706:             foreach ($methods as $method) {
                   28707:                 $function = "$class::$method";
                   28708:                 $key = "function;$function";
                   28709:                 if ($method{0} == '_' || !strcasecmp($method, $class) ||
                   28710:                     isset($this->_packageInfo['provides'][$key])) {
                   28711:                     continue;
                   28712:                 }
                   28713:                 $this->_packageInfo['provides'][$key] =
                   28714:                     array('file'=> $file, 'type' => 'function', 'name' => $function);
                   28715:             }
                   28716:         }
                   28717: 
                   28718:         foreach ($srcinfo['declared_functions'] as $function) {
                   28719:             $key = "function;$function";
                   28720:             if ($function{0} == '_' || isset($this->_packageInfo['provides'][$key])) {
                   28721:                 continue;
                   28722:             }
                   28723:             if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
                   28724:                 $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
                   28725:             }
                   28726:             $this->_packageInfo['provides'][$key] =
                   28727:                 array('file'=> $file, 'type' => 'function', 'name' => $function);
                   28728:         }
                   28729:     }
                   28730: 
                   28731:     // }}}
                   28732: }
                   28733: ?>
1.1.1.2 ! misho    28734: PEAR-1.9.4/PEAR/PackageFile/v2.php0000644000076500000240000021011311605156614015154 0ustar  helgistaff<?php
1.1       misho    28735: /**
                   28736:  * PEAR_PackageFile_v2, package.xml version 2.0
                   28737:  *
                   28738:  * PHP versions 4 and 5
                   28739:  *
                   28740:  * @category   pear
                   28741:  * @package    PEAR
                   28742:  * @author     Greg Beaver <cellog@php.net>
                   28743:  * @copyright  1997-2009 The Authors
                   28744:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   28745:  * @version    CVS: $Id: v2.php 313023 2011-07-06 19:17:11Z dufuz $
                   28746:  * @link       http://pear.php.net/package/PEAR
                   28747:  * @since      File available since Release 1.4.0a1
                   28748:  */
                   28749: /**
                   28750:  * For error handling
                   28751:  */
                   28752: require_once 'PEAR/ErrorStack.php';
                   28753: /**
                   28754:  * @category   pear
                   28755:  * @package    PEAR
                   28756:  * @author     Greg Beaver <cellog@php.net>
                   28757:  * @copyright  1997-2009 The Authors
                   28758:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   28759:  * @version    Release: 1.9.4
                   28760:  * @link       http://pear.php.net/package/PEAR
                   28761:  * @since      Class available since Release 1.4.0a1
                   28762:  */
                   28763: class PEAR_PackageFile_v2
                   28764: {
                   28765: 
                   28766:     /**
                   28767:      * Parsed package information
                   28768:      * @var array
                   28769:      * @access private
                   28770:      */
                   28771:     var $_packageInfo = array();
                   28772: 
                   28773:     /**
                   28774:      * path to package .tgz or false if this is a local/extracted package.xml
                   28775:      * @var string|false
                   28776:      * @access private
                   28777:      */
                   28778:     var $_archiveFile;
                   28779: 
                   28780:     /**
                   28781:      * path to package .xml or false if this is an abstract parsed-from-string xml
                   28782:      * @var string|false
                   28783:      * @access private
                   28784:      */
                   28785:     var $_packageFile;
                   28786: 
                   28787:     /**
                   28788:      * This is used by file analysis routines to log progress information
                   28789:      * @var PEAR_Common
                   28790:      * @access protected
                   28791:      */
                   28792:     var $_logger;
                   28793: 
                   28794:     /**
                   28795:      * This is set to the highest validation level that has been validated
                   28796:      *
                   28797:      * If the package.xml is invalid or unknown, this is set to 0.  If
                   28798:      * normal validation has occurred, this is set to PEAR_VALIDATE_NORMAL.  If
                   28799:      * downloading/installation validation has occurred it is set to PEAR_VALIDATE_DOWNLOADING
                   28800:      * or INSTALLING, and so on up to PEAR_VALIDATE_PACKAGING.  This allows validation
                   28801:      * "caching" to occur, which is particularly important for package validation, so
                   28802:      * that PHP files are not validated twice
                   28803:      * @var int
                   28804:      * @access private
                   28805:      */
                   28806:     var $_isValid = 0;
                   28807: 
                   28808:     /**
                   28809:      * True if the filelist has been validated
                   28810:      * @param bool
                   28811:      */
                   28812:     var $_filesValid = false;
                   28813: 
                   28814:     /**
                   28815:      * @var PEAR_Registry
                   28816:      * @access protected
                   28817:      */
                   28818:     var $_registry;
                   28819: 
                   28820:     /**
                   28821:      * @var PEAR_Config
                   28822:      * @access protected
                   28823:      */
                   28824:     var $_config;
                   28825: 
                   28826:     /**
                   28827:      * Optional Dependency group requested for installation
                   28828:      * @var string
                   28829:      * @access private
                   28830:      */
                   28831:     var $_requestedGroup = false;
                   28832: 
                   28833:     /**
                   28834:      * @var PEAR_ErrorStack
                   28835:      * @access protected
                   28836:      */
                   28837:     var $_stack;
                   28838: 
                   28839:     /**
                   28840:      * Namespace prefix used for tasks in this package.xml - use tasks: whenever possible
                   28841:      */
                   28842:     var $_tasksNs;
                   28843: 
                   28844:     /**
                   28845:      * Determines whether this packagefile was initialized only with partial package info
                   28846:      *
                   28847:      * If this package file was constructed via parsing REST, it will only contain
                   28848:      *
                   28849:      * - package name
                   28850:      * - channel name
                   28851:      * - dependencies
                   28852:      * @var boolean
                   28853:      * @access private
                   28854:      */
                   28855:     var $_incomplete = true;
                   28856: 
                   28857:     /**
                   28858:      * @var PEAR_PackageFile_v2_Validator
                   28859:      */
                   28860:     var $_v2Validator;
                   28861: 
                   28862:     /**
                   28863:      * The constructor merely sets up the private error stack
                   28864:      */
                   28865:     function PEAR_PackageFile_v2()
                   28866:     {
                   28867:         $this->_stack = new PEAR_ErrorStack('PEAR_PackageFile_v2', false, null);
                   28868:         $this->_isValid = false;
                   28869:     }
                   28870: 
                   28871:     /**
                   28872:      * To make unit-testing easier
                   28873:      * @param PEAR_Frontend_*
                   28874:      * @param array options
                   28875:      * @param PEAR_Config
                   28876:      * @return PEAR_Downloader
                   28877:      * @access protected
                   28878:      */
                   28879:     function &getPEARDownloader(&$i, $o, &$c)
                   28880:     {
                   28881:         $z = &new PEAR_Downloader($i, $o, $c);
                   28882:         return $z;
                   28883:     }
                   28884: 
                   28885:     /**
                   28886:      * To make unit-testing easier
                   28887:      * @param PEAR_Config
                   28888:      * @param array options
                   28889:      * @param array package name as returned from {@link PEAR_Registry::parsePackageName()}
                   28890:      * @param int PEAR_VALIDATE_* constant
                   28891:      * @return PEAR_Dependency2
                   28892:      * @access protected
                   28893:      */
                   28894:     function &getPEARDependency2(&$c, $o, $p, $s = PEAR_VALIDATE_INSTALLING)
                   28895:     {
                   28896:         if (!class_exists('PEAR_Dependency2')) {
                   28897:             require_once 'PEAR/Dependency2.php';
                   28898:         }
                   28899:         $z = &new PEAR_Dependency2($c, $o, $p, $s);
                   28900:         return $z;
                   28901:     }
                   28902: 
                   28903:     function getInstalledBinary()
                   28904:     {
                   28905:         return isset($this->_packageInfo['#binarypackage']) ? $this->_packageInfo['#binarypackage'] :
                   28906:             false;
                   28907:     }
                   28908: 
                   28909:     /**
                   28910:      * Installation of source package has failed, attempt to download and install the
                   28911:      * binary version of this package.
                   28912:      * @param PEAR_Installer
                   28913:      * @return array|false
                   28914:      */
                   28915:     function installBinary(&$installer)
                   28916:     {
                   28917:         if (!OS_WINDOWS) {
                   28918:             $a = false;
                   28919:             return $a;
                   28920:         }
                   28921:         if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
                   28922:             $releasetype = $this->getPackageType() . 'release';
                   28923:             if (!is_array($installer->getInstallPackages())) {
                   28924:                 $a = false;
                   28925:                 return $a;
                   28926:             }
                   28927:             foreach ($installer->getInstallPackages() as $p) {
                   28928:                 if ($p->isExtension($this->_packageInfo['providesextension'])) {
                   28929:                     if ($p->getPackageType() != 'extsrc' && $p->getPackageType() != 'zendextsrc') {
                   28930:                         $a = false;
                   28931:                         return $a; // the user probably downloaded it separately
                   28932:                     }
                   28933:                 }
                   28934:             }
                   28935:             if (isset($this->_packageInfo[$releasetype]['binarypackage'])) {
                   28936:                 $installer->log(0, 'Attempting to download binary version of extension "' .
                   28937:                     $this->_packageInfo['providesextension'] . '"');
                   28938:                 $params = $this->_packageInfo[$releasetype]['binarypackage'];
                   28939:                 if (!is_array($params) || !isset($params[0])) {
                   28940:                     $params = array($params);
                   28941:                 }
                   28942:                 if (isset($this->_packageInfo['channel'])) {
                   28943:                     foreach ($params as $i => $param) {
                   28944:                         $params[$i] = array('channel' => $this->_packageInfo['channel'],
                   28945:                             'package' => $param, 'version' => $this->getVersion());
                   28946:                     }
                   28947:                 }
                   28948:                 $dl = &$this->getPEARDownloader($installer->ui, $installer->getOptions(),
                   28949:                     $installer->config);
                   28950:                 $verbose = $dl->config->get('verbose');
                   28951:                 $dl->config->set('verbose', -1);
                   28952:                 foreach ($params as $param) {
                   28953:                     PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   28954:                     $ret = $dl->download(array($param));
                   28955:                     PEAR::popErrorHandling();
                   28956:                     if (is_array($ret) && count($ret)) {
                   28957:                         break;
                   28958:                     }
                   28959:                 }
                   28960:                 $dl->config->set('verbose', $verbose);
                   28961:                 if (is_array($ret)) {
                   28962:                     if (count($ret) == 1) {
                   28963:                         $pf = $ret[0]->getPackageFile();
                   28964:                         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   28965:                         $err = $installer->install($ret[0]);
                   28966:                         PEAR::popErrorHandling();
                   28967:                         if (is_array($err)) {
                   28968:                             $this->_packageInfo['#binarypackage'] = $ret[0]->getPackage();
                   28969:                             // "install" self, so all dependencies will work transparently
                   28970:                             $this->_registry->addPackage2($this);
                   28971:                             $installer->log(0, 'Download and install of binary extension "' .
                   28972:                                 $this->_registry->parsedPackageNameToString(
                   28973:                                     array('channel' => $pf->getChannel(),
                   28974:                                           'package' => $pf->getPackage()), true) . '" successful');
                   28975:                             $a = array($ret[0], $err);
                   28976:                             return $a;
                   28977:                         }
                   28978:                         $installer->log(0, 'Download and install of binary extension "' .
                   28979:                             $this->_registry->parsedPackageNameToString(
                   28980:                                     array('channel' => $pf->getChannel(),
                   28981:                                           'package' => $pf->getPackage()), true) . '" failed');
                   28982:                     }
                   28983:                 }
                   28984:             }
                   28985:         }
                   28986:         $a = false;
                   28987:         return $a;
                   28988:     }
                   28989: 
                   28990:     /**
                   28991:      * @return string|false Extension name
                   28992:      */
                   28993:     function getProvidesExtension()
                   28994:     {
                   28995:         if (in_array($this->getPackageType(),
                   28996:               array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
                   28997:             if (isset($this->_packageInfo['providesextension'])) {
                   28998:                 return $this->_packageInfo['providesextension'];
                   28999:             }
                   29000:         }
                   29001:         return false;
                   29002:     }
                   29003: 
                   29004:     /**
                   29005:      * @param string Extension name
                   29006:      * @return bool
                   29007:      */
                   29008:     function isExtension($extension)
                   29009:     {
                   29010:         if (in_array($this->getPackageType(),
                   29011:               array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
                   29012:             return $this->_packageInfo['providesextension'] == $extension;
                   29013:         }
                   29014:         return false;
                   29015:     }
                   29016: 
                   29017:     /**
                   29018:      * Tests whether every part of the package.xml 1.0 is represented in
                   29019:      * this package.xml 2.0
                   29020:      * @param PEAR_PackageFile_v1
                   29021:      * @return bool
                   29022:      */
                   29023:     function isEquivalent($pf1)
                   29024:     {
                   29025:         if (!$pf1) {
                   29026:             return true;
                   29027:         }
                   29028:         if ($this->getPackageType() == 'bundle') {
                   29029:             return false;
                   29030:         }
                   29031:         $this->_stack->getErrors(true);
                   29032:         if (!$pf1->validate(PEAR_VALIDATE_NORMAL)) {
                   29033:             return false;
                   29034:         }
                   29035:         $pass = true;
                   29036:         if ($pf1->getPackage() != $this->getPackage()) {
                   29037:             $this->_differentPackage($pf1->getPackage());
                   29038:             $pass = false;
                   29039:         }
                   29040:         if ($pf1->getVersion() != $this->getVersion()) {
                   29041:             $this->_differentVersion($pf1->getVersion());
                   29042:             $pass = false;
                   29043:         }
                   29044:         if (trim($pf1->getSummary()) != $this->getSummary()) {
                   29045:             $this->_differentSummary($pf1->getSummary());
                   29046:             $pass = false;
                   29047:         }
                   29048:         if (preg_replace('/\s+/', '', $pf1->getDescription()) !=
                   29049:               preg_replace('/\s+/', '', $this->getDescription())) {
                   29050:             $this->_differentDescription($pf1->getDescription());
                   29051:             $pass = false;
                   29052:         }
                   29053:         if ($pf1->getState() != $this->getState()) {
                   29054:             $this->_differentState($pf1->getState());
                   29055:             $pass = false;
                   29056:         }
                   29057:         if (!strstr(preg_replace('/\s+/', '', $this->getNotes()),
                   29058:               preg_replace('/\s+/', '', $pf1->getNotes()))) {
                   29059:             $this->_differentNotes($pf1->getNotes());
                   29060:             $pass = false;
                   29061:         }
                   29062:         $mymaintainers = $this->getMaintainers();
                   29063:         $yourmaintainers = $pf1->getMaintainers();
                   29064:         for ($i1 = 0; $i1 < count($yourmaintainers); $i1++) {
                   29065:             $reset = false;
                   29066:             for ($i2 = 0; $i2 < count($mymaintainers); $i2++) {
                   29067:                 if ($mymaintainers[$i2]['handle'] == $yourmaintainers[$i1]['handle']) {
                   29068:                     if ($mymaintainers[$i2]['role'] != $yourmaintainers[$i1]['role']) {
                   29069:                         $this->_differentRole($mymaintainers[$i2]['handle'],
                   29070:                             $yourmaintainers[$i1]['role'], $mymaintainers[$i2]['role']);
                   29071:                         $pass = false;
                   29072:                     }
                   29073:                     if ($mymaintainers[$i2]['email'] != $yourmaintainers[$i1]['email']) {
                   29074:                         $this->_differentEmail($mymaintainers[$i2]['handle'],
                   29075:                             $yourmaintainers[$i1]['email'], $mymaintainers[$i2]['email']);
                   29076:                         $pass = false;
                   29077:                     }
                   29078:                     if ($mymaintainers[$i2]['name'] != $yourmaintainers[$i1]['name']) {
                   29079:                         $this->_differentName($mymaintainers[$i2]['handle'],
                   29080:                             $yourmaintainers[$i1]['name'], $mymaintainers[$i2]['name']);
                   29081:                         $pass = false;
                   29082:                     }
                   29083:                     unset($mymaintainers[$i2]);
                   29084:                     $mymaintainers = array_values($mymaintainers);
                   29085:                     unset($yourmaintainers[$i1]);
                   29086:                     $yourmaintainers = array_values($yourmaintainers);
                   29087:                     $reset = true;
                   29088:                     break;
                   29089:                 }
                   29090:             }
                   29091:             if ($reset) {
                   29092:                 $i1 = -1;
                   29093:             }
                   29094:         }
                   29095:         $this->_unmatchedMaintainers($mymaintainers, $yourmaintainers);
                   29096:         $filelist = $this->getFilelist();
                   29097:         foreach ($pf1->getFilelist() as $file => $atts) {
                   29098:             if (!isset($filelist[$file])) {
                   29099:                 $this->_missingFile($file);
                   29100:                 $pass = false;
                   29101:             }
                   29102:         }
                   29103:         return $pass;
                   29104:     }
                   29105: 
                   29106:     function _differentPackage($package)
                   29107:     {
                   29108:         $this->_stack->push(__FUNCTION__, 'error', array('package' => $package,
                   29109:             'self' => $this->getPackage()),
                   29110:             'package.xml 1.0 package "%package%" does not match "%self%"');
                   29111:     }
                   29112: 
                   29113:     function _differentVersion($version)
                   29114:     {
                   29115:         $this->_stack->push(__FUNCTION__, 'error', array('version' => $version,
                   29116:             'self' => $this->getVersion()),
                   29117:             'package.xml 1.0 version "%version%" does not match "%self%"');
                   29118:     }
                   29119: 
                   29120:     function _differentState($state)
                   29121:     {
                   29122:         $this->_stack->push(__FUNCTION__, 'error', array('state' => $state,
                   29123:             'self' => $this->getState()),
                   29124:             'package.xml 1.0 state "%state%" does not match "%self%"');
                   29125:     }
                   29126: 
                   29127:     function _differentRole($handle, $role, $selfrole)
                   29128:     {
                   29129:         $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
                   29130:             'role' => $role, 'self' => $selfrole),
                   29131:             'package.xml 1.0 maintainer "%handle%" role "%role%" does not match "%self%"');
                   29132:     }
                   29133: 
                   29134:     function _differentEmail($handle, $email, $selfemail)
                   29135:     {
                   29136:         $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
                   29137:             'email' => $email, 'self' => $selfemail),
                   29138:             'package.xml 1.0 maintainer "%handle%" email "%email%" does not match "%self%"');
                   29139:     }
                   29140: 
                   29141:     function _differentName($handle, $name, $selfname)
                   29142:     {
                   29143:         $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
                   29144:             'name' => $name, 'self' => $selfname),
                   29145:             'package.xml 1.0 maintainer "%handle%" name "%name%" does not match "%self%"');
                   29146:     }
                   29147: 
                   29148:     function _unmatchedMaintainers($my, $yours)
                   29149:     {
                   29150:         if ($my) {
                   29151:             array_walk($my, create_function('&$i, $k', '$i = $i["handle"];'));
                   29152:             $this->_stack->push(__FUNCTION__, 'error', array('handles' => $my),
                   29153:                 'package.xml 2.0 has unmatched extra maintainers "%handles%"');
                   29154:         }
                   29155:         if ($yours) {
                   29156:             array_walk($yours, create_function('&$i, $k', '$i = $i["handle"];'));
                   29157:             $this->_stack->push(__FUNCTION__, 'error', array('handles' => $yours),
                   29158:                 'package.xml 1.0 has unmatched extra maintainers "%handles%"');
                   29159:         }
                   29160:     }
                   29161: 
                   29162:     function _differentNotes($notes)
                   29163:     {
                   29164:         $truncnotes = strlen($notes) < 25 ? $notes : substr($notes, 0, 24) . '...';
                   29165:         $truncmynotes = strlen($this->getNotes()) < 25 ? $this->getNotes() :
                   29166:             substr($this->getNotes(), 0, 24) . '...';
                   29167:         $this->_stack->push(__FUNCTION__, 'error', array('notes' => $truncnotes,
                   29168:             'self' => $truncmynotes),
                   29169:             'package.xml 1.0 release notes "%notes%" do not match "%self%"');
                   29170:     }
                   29171: 
                   29172:     function _differentSummary($summary)
                   29173:     {
                   29174:         $truncsummary = strlen($summary) < 25 ? $summary : substr($summary, 0, 24) . '...';
                   29175:         $truncmysummary = strlen($this->getsummary()) < 25 ? $this->getSummary() :
                   29176:             substr($this->getsummary(), 0, 24) . '...';
                   29177:         $this->_stack->push(__FUNCTION__, 'error', array('summary' => $truncsummary,
                   29178:             'self' => $truncmysummary),
                   29179:             'package.xml 1.0 summary "%summary%" does not match "%self%"');
                   29180:     }
                   29181: 
                   29182:     function _differentDescription($description)
                   29183:     {
                   29184:         $truncdescription = trim(strlen($description) < 25 ? $description : substr($description, 0, 24) . '...');
                   29185:         $truncmydescription = trim(strlen($this->getDescription()) < 25 ? $this->getDescription() :
                   29186:             substr($this->getdescription(), 0, 24) . '...');
                   29187:         $this->_stack->push(__FUNCTION__, 'error', array('description' => $truncdescription,
                   29188:             'self' => $truncmydescription),
                   29189:             'package.xml 1.0 description "%description%" does not match "%self%"');
                   29190:     }
                   29191: 
                   29192:     function _missingFile($file)
                   29193:     {
                   29194:         $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
                   29195:             'package.xml 1.0 file "%file%" is not present in <contents>');
                   29196:     }
                   29197: 
                   29198:     /**
                   29199:      * WARNING - do not use this function unless you know what you're doing
                   29200:      */
                   29201:     function setRawState($state)
                   29202:     {
                   29203:         if (!isset($this->_packageInfo['stability'])) {
                   29204:             $this->_packageInfo['stability'] = array();
                   29205:         }
                   29206:         $this->_packageInfo['stability']['release'] = $state;
                   29207:     }
                   29208: 
                   29209:     /**
                   29210:      * WARNING - do not use this function unless you know what you're doing
                   29211:      */
                   29212:     function setRawCompatible($compatible)
                   29213:     {
                   29214:         $this->_packageInfo['compatible'] = $compatible;
                   29215:     }
                   29216: 
                   29217:     /**
                   29218:      * WARNING - do not use this function unless you know what you're doing
                   29219:      */
                   29220:     function setRawPackage($package)
                   29221:     {
                   29222:         $this->_packageInfo['name'] = $package;
                   29223:     }
                   29224: 
                   29225:     /**
                   29226:      * WARNING - do not use this function unless you know what you're doing
                   29227:      */
                   29228:     function setRawChannel($channel)
                   29229:     {
                   29230:         $this->_packageInfo['channel'] = $channel;
                   29231:     }
                   29232: 
                   29233:     function setRequestedGroup($group)
                   29234:     {
                   29235:         $this->_requestedGroup = $group;
                   29236:     }
                   29237: 
                   29238:     function getRequestedGroup()
                   29239:     {
                   29240:         if (isset($this->_requestedGroup)) {
                   29241:             return $this->_requestedGroup;
                   29242:         }
                   29243:         return false;
                   29244:     }
                   29245: 
                   29246:     /**
                   29247:      * For saving in the registry.
                   29248:      *
                   29249:      * Set the last version that was installed
                   29250:      * @param string
                   29251:      */
                   29252:     function setLastInstalledVersion($version)
                   29253:     {
                   29254:         $this->_packageInfo['_lastversion'] = $version;
                   29255:     }
                   29256: 
                   29257:     /**
                   29258:      * @return string|false
                   29259:      */
                   29260:     function getLastInstalledVersion()
                   29261:     {
                   29262:         if (isset($this->_packageInfo['_lastversion'])) {
                   29263:             return $this->_packageInfo['_lastversion'];
                   29264:         }
                   29265:         return false;
                   29266:     }
                   29267: 
                   29268:     /**
                   29269:      * Determines whether this package.xml has post-install scripts or not
                   29270:      * @return array|false
                   29271:      */
                   29272:     function listPostinstallScripts()
                   29273:     {
                   29274:         $filelist = $this->getFilelist();
                   29275:         $contents = $this->getContents();
                   29276:         $contents = $contents['dir']['file'];
                   29277:         if (!is_array($contents) || !isset($contents[0])) {
                   29278:             $contents = array($contents);
                   29279:         }
                   29280:         $taskfiles = array();
                   29281:         foreach ($contents as $file) {
                   29282:             $atts = $file['attribs'];
                   29283:             unset($file['attribs']);
                   29284:             if (count($file)) {
                   29285:                 $taskfiles[$atts['name']] = $file;
                   29286:             }
                   29287:         }
                   29288:         $common = new PEAR_Common;
                   29289:         $common->debug = $this->_config->get('verbose');
                   29290:         $this->_scripts = array();
                   29291:         $ret = array();
                   29292:         foreach ($taskfiles as $name => $tasks) {
                   29293:             if (!isset($filelist[$name])) {
                   29294:                 // ignored files will not be in the filelist
                   29295:                 continue;
                   29296:             }
                   29297:             $atts = $filelist[$name];
                   29298:             foreach ($tasks as $tag => $raw) {
                   29299:                 $task = $this->getTask($tag);
                   29300:                 $task = &new $task($this->_config, $common, PEAR_TASK_INSTALL);
                   29301:                 if ($task->isScript()) {
                   29302:                     $ret[] = $filelist[$name]['installed_as'];
                   29303:                 }
                   29304:             }
                   29305:         }
                   29306:         if (count($ret)) {
                   29307:             return $ret;
                   29308:         }
                   29309:         return false;
                   29310:     }
                   29311: 
                   29312:     /**
                   29313:      * Initialize post-install scripts for running
                   29314:      *
                   29315:      * This method can be used to detect post-install scripts, as the return value
                   29316:      * indicates whether any exist
                   29317:      * @return bool
                   29318:      */
                   29319:     function initPostinstallScripts()
                   29320:     {
                   29321:         $filelist = $this->getFilelist();
                   29322:         $contents = $this->getContents();
                   29323:         $contents = $contents['dir']['file'];
                   29324:         if (!is_array($contents) || !isset($contents[0])) {
                   29325:             $contents = array($contents);
                   29326:         }
                   29327:         $taskfiles = array();
                   29328:         foreach ($contents as $file) {
                   29329:             $atts = $file['attribs'];
                   29330:             unset($file['attribs']);
                   29331:             if (count($file)) {
                   29332:                 $taskfiles[$atts['name']] = $file;
                   29333:             }
                   29334:         }
                   29335:         $common = new PEAR_Common;
                   29336:         $common->debug = $this->_config->get('verbose');
                   29337:         $this->_scripts = array();
                   29338:         foreach ($taskfiles as $name => $tasks) {
                   29339:             if (!isset($filelist[$name])) {
                   29340:                 // file was not installed due to installconditions
                   29341:                 continue;
                   29342:             }
                   29343:             $atts = $filelist[$name];
                   29344:             foreach ($tasks as $tag => $raw) {
                   29345:                 $taskname = $this->getTask($tag);
                   29346:                 $task = &new $taskname($this->_config, $common, PEAR_TASK_INSTALL);
                   29347:                 if (!$task->isScript()) {
                   29348:                     continue; // scripts are only handled after installation
                   29349:                 }
                   29350:                 $lastversion = isset($this->_packageInfo['_lastversion']) ?
                   29351:                     $this->_packageInfo['_lastversion'] : null;
                   29352:                 $task->init($raw, $atts, $lastversion);
                   29353:                 $res = $task->startSession($this, $atts['installed_as']);
                   29354:                 if (!$res) {
                   29355:                     continue; // skip this file
                   29356:                 }
                   29357:                 if (PEAR::isError($res)) {
                   29358:                     return $res;
                   29359:                 }
                   29360:                 $assign = &$task;
                   29361:                 $this->_scripts[] = &$assign;
                   29362:             }
                   29363:         }
                   29364:         if (count($this->_scripts)) {
                   29365:             return true;
                   29366:         }
                   29367:         return false;
                   29368:     }
                   29369: 
                   29370:     function runPostinstallScripts()
                   29371:     {
                   29372:         if ($this->initPostinstallScripts()) {
                   29373:             $ui = &PEAR_Frontend::singleton();
                   29374:             if ($ui) {
                   29375:                 $ui->runPostinstallScripts($this->_scripts, $this);
                   29376:             }
                   29377:         }
                   29378:     }
                   29379: 
                   29380: 
                   29381:     /**
                   29382:      * Convert a recursive set of <dir> and <file> tags into a single <dir> tag with
                   29383:      * <file> tags.
                   29384:      */
                   29385:     function flattenFilelist()
                   29386:     {
                   29387:         if (isset($this->_packageInfo['bundle'])) {
                   29388:             return;
                   29389:         }
                   29390:         $filelist = array();
                   29391:         if (isset($this->_packageInfo['contents']['dir']['dir'])) {
                   29392:             $this->_getFlattenedFilelist($filelist, $this->_packageInfo['contents']['dir']);
                   29393:             if (!isset($filelist[1])) {
                   29394:                 $filelist = $filelist[0];
                   29395:             }
                   29396:             $this->_packageInfo['contents']['dir']['file'] = $filelist;
                   29397:             unset($this->_packageInfo['contents']['dir']['dir']);
                   29398:         } else {
                   29399:             // else already flattened but check for baseinstalldir propagation
                   29400:             if (isset($this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'])) {
                   29401:                 if (isset($this->_packageInfo['contents']['dir']['file'][0])) {
                   29402:                     foreach ($this->_packageInfo['contents']['dir']['file'] as $i => $file) {
                   29403:                         if (isset($file['attribs']['baseinstalldir'])) {
                   29404:                             continue;
                   29405:                         }
                   29406:                         $this->_packageInfo['contents']['dir']['file'][$i]['attribs']['baseinstalldir']
                   29407:                             = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'];
                   29408:                     }
                   29409:                 } else {
                   29410:                     if (!isset($this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir'])) {
                   29411:                        $this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir']
                   29412:                             = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'];
                   29413:                     }
                   29414:                 }
                   29415:             }
                   29416:         }
                   29417:     }
                   29418: 
                   29419:     /**
                   29420:      * @param array the final flattened file list
                   29421:      * @param array the current directory being processed
                   29422:      * @param string|false any recursively inherited baeinstalldir attribute
                   29423:      * @param string private recursion variable
                   29424:      * @return array
                   29425:      * @access protected
                   29426:      */
                   29427:     function _getFlattenedFilelist(&$files, $dir, $baseinstall = false, $path = '')
                   29428:     {
                   29429:         if (isset($dir['attribs']) && isset($dir['attribs']['baseinstalldir'])) {
                   29430:             $baseinstall = $dir['attribs']['baseinstalldir'];
                   29431:         }
                   29432:         if (isset($dir['dir'])) {
                   29433:             if (!isset($dir['dir'][0])) {
                   29434:                 $dir['dir'] = array($dir['dir']);
                   29435:             }
                   29436:             foreach ($dir['dir'] as $subdir) {
                   29437:                 if (!isset($subdir['attribs']) || !isset($subdir['attribs']['name'])) {
                   29438:                     $name = '*unknown*';
                   29439:                 } else {
                   29440:                     $name = $subdir['attribs']['name'];
                   29441:                 }
                   29442:                 $newpath = empty($path) ? $name :
                   29443:                     $path . '/' . $name;
                   29444:                 $this->_getFlattenedFilelist($files, $subdir,
                   29445:                     $baseinstall, $newpath);
                   29446:             }
                   29447:         }
                   29448:         if (isset($dir['file'])) {
                   29449:             if (!isset($dir['file'][0])) {
                   29450:                 $dir['file'] = array($dir['file']);
                   29451:             }
                   29452:             foreach ($dir['file'] as $file) {
                   29453:                 $attrs = $file['attribs'];
                   29454:                 $name = $attrs['name'];
                   29455:                 if ($baseinstall && !isset($attrs['baseinstalldir'])) {
                   29456:                     $attrs['baseinstalldir'] = $baseinstall;
                   29457:                 }
                   29458:                 $attrs['name'] = empty($path) ? $name : $path . '/' . $name;
                   29459:                 $attrs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
                   29460:                     $attrs['name']);
                   29461:                 $file['attribs'] = $attrs;
                   29462:                 $files[] = $file;
                   29463:             }
                   29464:         }
                   29465:     }
                   29466: 
                   29467:     function setConfig(&$config)
                   29468:     {
                   29469:         $this->_config = &$config;
                   29470:         $this->_registry = &$config->getRegistry();
                   29471:     }
                   29472: 
                   29473:     function setLogger(&$logger)
                   29474:     {
                   29475:         if (!is_object($logger) || !method_exists($logger, 'log')) {
                   29476:             return PEAR::raiseError('Logger must be compatible with PEAR_Common::log');
                   29477:         }
                   29478:         $this->_logger = &$logger;
                   29479:     }
                   29480: 
                   29481:     /**
                   29482:      * WARNING - do not use this function directly unless you know what you're doing
                   29483:      */
                   29484:     function setDeps($deps)
                   29485:     {
                   29486:         $this->_packageInfo['dependencies'] = $deps;
                   29487:     }
                   29488: 
                   29489:     /**
                   29490:      * WARNING - do not use this function directly unless you know what you're doing
                   29491:      */
                   29492:     function setCompatible($compat)
                   29493:     {
                   29494:         $this->_packageInfo['compatible'] = $compat;
                   29495:     }
                   29496: 
                   29497:     function setPackagefile($file, $archive = false)
                   29498:     {
                   29499:         $this->_packageFile = $file;
                   29500:         $this->_archiveFile = $archive ? $archive : $file;
                   29501:     }
                   29502: 
                   29503:     /**
                   29504:      * Wrapper to {@link PEAR_ErrorStack::getErrors()}
                   29505:      * @param boolean determines whether to purge the error stack after retrieving
                   29506:      * @return array
                   29507:      */
                   29508:     function getValidationWarnings($purge = true)
                   29509:     {
                   29510:         return $this->_stack->getErrors($purge);
                   29511:     }
                   29512: 
                   29513:     function getPackageFile()
                   29514:     {
                   29515:         return $this->_packageFile;
                   29516:     }
                   29517: 
                   29518:     function getArchiveFile()
                   29519:     {
                   29520:         return $this->_archiveFile;
                   29521:     }
                   29522: 
                   29523: 
                   29524:     /**
                   29525:      * Directly set the array that defines this packagefile
                   29526:      *
                   29527:      * WARNING: no validation.  This should only be performed by internal methods
                   29528:      * inside PEAR or by inputting an array saved from an existing PEAR_PackageFile_v2
                   29529:      * @param array
                   29530:      */
                   29531:     function fromArray($pinfo)
                   29532:     {
                   29533:         unset($pinfo['old']);
                   29534:         unset($pinfo['xsdversion']);
                   29535:         // If the changelog isn't an array then it was passed in as an empty tag
                   29536:         if (isset($pinfo['changelog']) && !is_array($pinfo['changelog'])) {
                   29537:           unset($pinfo['changelog']);
                   29538:         }
                   29539:         $this->_incomplete = false;
                   29540:         $this->_packageInfo = $pinfo;
                   29541:     }
                   29542: 
                   29543:     function isIncomplete()
                   29544:     {
                   29545:         return $this->_incomplete;
                   29546:     }
                   29547: 
                   29548:     /**
                   29549:      * @return array
                   29550:      */
                   29551:     function toArray($forreg = false)
                   29552:     {
                   29553:         if (!$this->validate(PEAR_VALIDATE_NORMAL)) {
                   29554:             return false;
                   29555:         }
                   29556:         return $this->getArray($forreg);
                   29557:     }
                   29558: 
                   29559:     function getArray($forReg = false)
                   29560:     {
                   29561:         if ($forReg) {
                   29562:             $arr = $this->_packageInfo;
                   29563:             $arr['old'] = array();
                   29564:             $arr['old']['version'] = $this->getVersion();
                   29565:             $arr['old']['release_date'] = $this->getDate();
                   29566:             $arr['old']['release_state'] = $this->getState();
                   29567:             $arr['old']['release_license'] = $this->getLicense();
                   29568:             $arr['old']['release_notes'] = $this->getNotes();
                   29569:             $arr['old']['release_deps'] = $this->getDeps();
                   29570:             $arr['old']['maintainers'] = $this->getMaintainers();
                   29571:             $arr['xsdversion'] = '2.0';
                   29572:             return $arr;
                   29573:         } else {
                   29574:             $info = $this->_packageInfo;
                   29575:             unset($info['dirtree']);
                   29576:             if (isset($info['_lastversion'])) {
                   29577:                 unset($info['_lastversion']);
                   29578:             }
                   29579:             if (isset($info['#binarypackage'])) {
                   29580:                 unset($info['#binarypackage']);
                   29581:             }
                   29582:             return $info;
                   29583:         }
                   29584:     }
                   29585: 
                   29586:     function packageInfo($field)
                   29587:     {
                   29588:         $arr = $this->getArray(true);
                   29589:         if ($field == 'state') {
                   29590:             return $arr['stability']['release'];
                   29591:         }
                   29592:         if ($field == 'api-version') {
                   29593:             return $arr['version']['api'];
                   29594:         }
                   29595:         if ($field == 'api-state') {
                   29596:             return $arr['stability']['api'];
                   29597:         }
                   29598:         if (isset($arr['old'][$field])) {
                   29599:             if (!is_string($arr['old'][$field])) {
                   29600:                 return null;
                   29601:             }
                   29602:             return $arr['old'][$field];
                   29603:         }
                   29604:         if (isset($arr[$field])) {
                   29605:             if (!is_string($arr[$field])) {
                   29606:                 return null;
                   29607:             }
                   29608:             return $arr[$field];
                   29609:         }
                   29610:         return null;
                   29611:     }
                   29612: 
                   29613:     function getName()
                   29614:     {
                   29615:         return $this->getPackage();
                   29616:     }
                   29617: 
                   29618:     function getPackage()
                   29619:     {
                   29620:         if (isset($this->_packageInfo['name'])) {
                   29621:             return $this->_packageInfo['name'];
                   29622:         }
                   29623:         return false;
                   29624:     }
                   29625: 
                   29626:     function getChannel()
                   29627:     {
                   29628:         if (isset($this->_packageInfo['uri'])) {
                   29629:             return '__uri';
                   29630:         }
                   29631:         if (isset($this->_packageInfo['channel'])) {
                   29632:             return strtolower($this->_packageInfo['channel']);
                   29633:         }
                   29634:         return false;
                   29635:     }
                   29636: 
                   29637:     function getUri()
                   29638:     {
                   29639:         if (isset($this->_packageInfo['uri'])) {
                   29640:             return $this->_packageInfo['uri'];
                   29641:         }
                   29642:         return false;
                   29643:     }
                   29644: 
                   29645:     function getExtends()
                   29646:     {
                   29647:         if (isset($this->_packageInfo['extends'])) {
                   29648:             return $this->_packageInfo['extends'];
                   29649:         }
                   29650:         return false;
                   29651:     }
                   29652: 
                   29653:     function getSummary()
                   29654:     {
                   29655:         if (isset($this->_packageInfo['summary'])) {
                   29656:             return $this->_packageInfo['summary'];
                   29657:         }
                   29658:         return false;
                   29659:     }
                   29660: 
                   29661:     function getDescription()
                   29662:     {
                   29663:         if (isset($this->_packageInfo['description'])) {
                   29664:             return $this->_packageInfo['description'];
                   29665:         }
                   29666:         return false;
                   29667:     }
                   29668: 
                   29669:     function getMaintainers($raw = false)
                   29670:     {
                   29671:         if (!isset($this->_packageInfo['lead'])) {
                   29672:             return false;
                   29673:         }
                   29674:         if ($raw) {
                   29675:             $ret = array('lead' => $this->_packageInfo['lead']);
                   29676:             (isset($this->_packageInfo['developer'])) ?
                   29677:                 $ret['developer'] = $this->_packageInfo['developer'] :null;
                   29678:             (isset($this->_packageInfo['contributor'])) ?
                   29679:                 $ret['contributor'] = $this->_packageInfo['contributor'] :null;
                   29680:             (isset($this->_packageInfo['helper'])) ?
                   29681:                 $ret['helper'] = $this->_packageInfo['helper'] :null;
                   29682:             return $ret;
                   29683:         } else {
                   29684:             $ret = array();
                   29685:             $leads = isset($this->_packageInfo['lead'][0]) ? $this->_packageInfo['lead'] :
                   29686:                 array($this->_packageInfo['lead']);
                   29687:             foreach ($leads as $lead) {
                   29688:                 $s = $lead;
                   29689:                 $s['handle'] = $s['user'];
                   29690:                 unset($s['user']);
                   29691:                 $s['role'] = 'lead';
                   29692:                 $ret[] = $s;
                   29693:             }
                   29694:             if (isset($this->_packageInfo['developer'])) {
                   29695:                 $leads = isset($this->_packageInfo['developer'][0]) ?
                   29696:                     $this->_packageInfo['developer'] :
                   29697:                     array($this->_packageInfo['developer']);
                   29698:                 foreach ($leads as $maintainer) {
                   29699:                     $s = $maintainer;
                   29700:                     $s['handle'] = $s['user'];
                   29701:                     unset($s['user']);
                   29702:                     $s['role'] = 'developer';
                   29703:                     $ret[] = $s;
                   29704:                 }
                   29705:             }
                   29706:             if (isset($this->_packageInfo['contributor'])) {
                   29707:                 $leads = isset($this->_packageInfo['contributor'][0]) ?
                   29708:                     $this->_packageInfo['contributor'] :
                   29709:                     array($this->_packageInfo['contributor']);
                   29710:                 foreach ($leads as $maintainer) {
                   29711:                     $s = $maintainer;
                   29712:                     $s['handle'] = $s['user'];
                   29713:                     unset($s['user']);
                   29714:                     $s['role'] = 'contributor';
                   29715:                     $ret[] = $s;
                   29716:                 }
                   29717:             }
                   29718:             if (isset($this->_packageInfo['helper'])) {
                   29719:                 $leads = isset($this->_packageInfo['helper'][0]) ?
                   29720:                     $this->_packageInfo['helper'] :
                   29721:                     array($this->_packageInfo['helper']);
                   29722:                 foreach ($leads as $maintainer) {
                   29723:                     $s = $maintainer;
                   29724:                     $s['handle'] = $s['user'];
                   29725:                     unset($s['user']);
                   29726:                     $s['role'] = 'helper';
                   29727:                     $ret[] = $s;
                   29728:                 }
                   29729:             }
                   29730:             return $ret;
                   29731:         }
                   29732:         return false;
                   29733:     }
                   29734: 
                   29735:     function getLeads()
                   29736:     {
                   29737:         if (isset($this->_packageInfo['lead'])) {
                   29738:             return $this->_packageInfo['lead'];
                   29739:         }
                   29740:         return false;
                   29741:     }
                   29742: 
                   29743:     function getDevelopers()
                   29744:     {
                   29745:         if (isset($this->_packageInfo['developer'])) {
                   29746:             return $this->_packageInfo['developer'];
                   29747:         }
                   29748:         return false;
                   29749:     }
                   29750: 
                   29751:     function getContributors()
                   29752:     {
                   29753:         if (isset($this->_packageInfo['contributor'])) {
                   29754:             return $this->_packageInfo['contributor'];
                   29755:         }
                   29756:         return false;
                   29757:     }
                   29758: 
                   29759:     function getHelpers()
                   29760:     {
                   29761:         if (isset($this->_packageInfo['helper'])) {
                   29762:             return $this->_packageInfo['helper'];
                   29763:         }
                   29764:         return false;
                   29765:     }
                   29766: 
                   29767:     function setDate($date)
                   29768:     {
                   29769:         if (!isset($this->_packageInfo['date'])) {
                   29770:             // ensure that the extends tag is set up in the right location
                   29771:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   29772:                 array('time', 'version',
                   29773:                     'stability', 'license', 'notes', 'contents', 'compatible',
                   29774:                     'dependencies', 'providesextension', 'srcpackage', 'srcuri',
                   29775:                     'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease',
                   29776:                     'zendextbinrelease', 'bundle', 'changelog'), array(), 'date');
                   29777:         }
                   29778:         $this->_packageInfo['date'] = $date;
                   29779:         $this->_isValid = 0;
                   29780:     }
                   29781: 
                   29782:     function setTime($time)
                   29783:     {
                   29784:         $this->_isValid = 0;
                   29785:         if (!isset($this->_packageInfo['time'])) {
                   29786:             // ensure that the time tag is set up in the right location
                   29787:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
                   29788:                     array('version',
                   29789:                     'stability', 'license', 'notes', 'contents', 'compatible',
                   29790:                     'dependencies', 'providesextension', 'srcpackage', 'srcuri',
                   29791:                     'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease',
                   29792:                     'zendextbinrelease', 'bundle', 'changelog'), $time, 'time');
                   29793:         }
                   29794:         $this->_packageInfo['time'] = $time;
                   29795:     }
                   29796: 
                   29797:     function getDate()
                   29798:     {
                   29799:         if (isset($this->_packageInfo['date'])) {
                   29800:             return $this->_packageInfo['date'];
                   29801:         }
                   29802:         return false;
                   29803:     }
                   29804: 
                   29805:     function getTime()
                   29806:     {
                   29807:         if (isset($this->_packageInfo['time'])) {
                   29808:             return $this->_packageInfo['time'];
                   29809:         }
                   29810:         return false;
                   29811:     }
                   29812: 
                   29813:     /**
                   29814:      * @param package|api version category to return
                   29815:      */
                   29816:     function getVersion($key = 'release')
                   29817:     {
                   29818:         if (isset($this->_packageInfo['version'][$key])) {
                   29819:             return $this->_packageInfo['version'][$key];
                   29820:         }
                   29821:         return false;
                   29822:     }
                   29823: 
                   29824:     function getStability()
                   29825:     {
                   29826:         if (isset($this->_packageInfo['stability'])) {
                   29827:             return $this->_packageInfo['stability'];
                   29828:         }
                   29829:         return false;
                   29830:     }
                   29831: 
                   29832:     function getState($key = 'release')
                   29833:     {
                   29834:         if (isset($this->_packageInfo['stability'][$key])) {
                   29835:             return $this->_packageInfo['stability'][$key];
                   29836:         }
                   29837:         return false;
                   29838:     }
                   29839: 
                   29840:     function getLicense($raw = false)
                   29841:     {
                   29842:         if (isset($this->_packageInfo['license'])) {
                   29843:             if ($raw) {
                   29844:                 return $this->_packageInfo['license'];
                   29845:             }
                   29846:             if (is_array($this->_packageInfo['license'])) {
                   29847:                 return $this->_packageInfo['license']['_content'];
                   29848:             } else {
                   29849:                 return $this->_packageInfo['license'];
                   29850:             }
                   29851:         }
                   29852:         return false;
                   29853:     }
                   29854: 
                   29855:     function getLicenseLocation()
                   29856:     {
                   29857:         if (!isset($this->_packageInfo['license']) || !is_array($this->_packageInfo['license'])) {
                   29858:             return false;
                   29859:         }
                   29860:         return $this->_packageInfo['license']['attribs'];
                   29861:     }
                   29862: 
                   29863:     function getNotes()
                   29864:     {
                   29865:         if (isset($this->_packageInfo['notes'])) {
                   29866:             return $this->_packageInfo['notes'];
                   29867:         }
                   29868:         return false;
                   29869:     }
                   29870: 
                   29871:     /**
                   29872:      * Return the <usesrole> tag contents, if any
                   29873:      * @return array|false
                   29874:      */
                   29875:     function getUsesrole()
                   29876:     {
                   29877:         if (isset($this->_packageInfo['usesrole'])) {
                   29878:             return $this->_packageInfo['usesrole'];
                   29879:         }
                   29880:         return false;
                   29881:     }
                   29882: 
                   29883:     /**
                   29884:      * Return the <usestask> tag contents, if any
                   29885:      * @return array|false
                   29886:      */
                   29887:     function getUsestask()
                   29888:     {
                   29889:         if (isset($this->_packageInfo['usestask'])) {
                   29890:             return $this->_packageInfo['usestask'];
                   29891:         }
                   29892:         return false;
                   29893:     }
                   29894: 
                   29895:     /**
                   29896:      * This should only be used to retrieve filenames and install attributes
                   29897:      */
                   29898:     function getFilelist($preserve = false)
                   29899:     {
                   29900:         if (isset($this->_packageInfo['filelist']) && !$preserve) {
                   29901:             return $this->_packageInfo['filelist'];
                   29902:         }
                   29903:         $this->flattenFilelist();
                   29904:         if ($contents = $this->getContents()) {
                   29905:             $ret = array();
                   29906:             if (!isset($contents['dir'])) {
                   29907:                 return false;
                   29908:             }
                   29909:             if (!isset($contents['dir']['file'][0])) {
                   29910:                 $contents['dir']['file'] = array($contents['dir']['file']);
                   29911:             }
                   29912:             foreach ($contents['dir']['file'] as $file) {
                   29913:                 $name = $file['attribs']['name'];
                   29914:                 if (!$preserve) {
                   29915:                     $file = $file['attribs'];
                   29916:                 }
                   29917:                 $ret[$name] = $file;
                   29918:             }
                   29919:             if (!$preserve) {
                   29920:                 $this->_packageInfo['filelist'] = $ret;
                   29921:             }
                   29922:             return $ret;
                   29923:         }
                   29924:         return false;
                   29925:     }
                   29926: 
                   29927:     /**
                   29928:      * Return configure options array, if any
                   29929:      *
                   29930:      * @return array|false
                   29931:      */
                   29932:     function getConfigureOptions()
                   29933:     {
                   29934:         if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
                   29935:             return false;
                   29936:         }
                   29937: 
                   29938:         $releases = $this->getReleases();
                   29939:         if (isset($releases[0])) {
                   29940:             $releases = $releases[0];
                   29941:         }
                   29942: 
                   29943:         if (isset($releases['configureoption'])) {
                   29944:             if (!isset($releases['configureoption'][0])) {
                   29945:                 $releases['configureoption'] = array($releases['configureoption']);
                   29946:             }
                   29947: 
                   29948:             for ($i = 0; $i < count($releases['configureoption']); $i++) {
                   29949:                 $releases['configureoption'][$i] = $releases['configureoption'][$i]['attribs'];
                   29950:             }
                   29951: 
                   29952:             return $releases['configureoption'];
                   29953:         }
                   29954: 
                   29955:         return false;
                   29956:     }
                   29957: 
                   29958:     /**
                   29959:      * This is only used at install-time, after all serialization
                   29960:      * is over.
                   29961:      */
                   29962:     function resetFilelist()
                   29963:     {
                   29964:         $this->_packageInfo['filelist'] = array();
                   29965:     }
                   29966: 
                   29967:     /**
                   29968:      * Retrieve a list of files that should be installed on this computer
                   29969:      * @return array
                   29970:      */
                   29971:     function getInstallationFilelist($forfilecheck = false)
                   29972:     {
                   29973:         $contents = $this->getFilelist(true);
                   29974:         if (isset($contents['dir']['attribs']['baseinstalldir'])) {
                   29975:             $base = $contents['dir']['attribs']['baseinstalldir'];
                   29976:         }
                   29977:         if (isset($this->_packageInfo['bundle'])) {
                   29978:             return PEAR::raiseError(
                   29979:                 'Exception: bundles should be handled in download code only');
                   29980:         }
                   29981:         $release = $this->getReleases();
                   29982:         if ($release) {
                   29983:             if (!isset($release[0])) {
                   29984:                 if (!isset($release['installconditions']) && !isset($release['filelist'])) {
                   29985:                     if ($forfilecheck) {
                   29986:                         return $this->getFilelist();
                   29987:                     }
                   29988:                     return $contents;
                   29989:                 }
                   29990:                 $release = array($release);
                   29991:             }
                   29992:             $depchecker = &$this->getPEARDependency2($this->_config, array(),
                   29993:                 array('channel' => $this->getChannel(), 'package' => $this->getPackage()),
                   29994:                 PEAR_VALIDATE_INSTALLING);
                   29995:             foreach ($release as $instance) {
                   29996:                 if (isset($instance['installconditions'])) {
                   29997:                     $installconditions = $instance['installconditions'];
                   29998:                     if (is_array($installconditions)) {
                   29999:                         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   30000:                         foreach ($installconditions as $type => $conditions) {
                   30001:                             if (!isset($conditions[0])) {
                   30002:                                 $conditions = array($conditions);
                   30003:                             }
                   30004:                             foreach ($conditions as $condition) {
                   30005:                                 $ret = $depchecker->{"validate{$type}Dependency"}($condition);
                   30006:                                 if (PEAR::isError($ret)) {
                   30007:                                     PEAR::popErrorHandling();
                   30008:                                     continue 3; // skip this release
                   30009:                                 }
                   30010:                             }
                   30011:                         }
                   30012:                         PEAR::popErrorHandling();
                   30013:                     }
                   30014:                 }
                   30015:                 // this is the release to use
                   30016:                 if (isset($instance['filelist'])) {
                   30017:                     // ignore files
                   30018:                     if (isset($instance['filelist']['ignore'])) {
                   30019:                         $ignore = isset($instance['filelist']['ignore'][0]) ?
                   30020:                             $instance['filelist']['ignore'] :
                   30021:                             array($instance['filelist']['ignore']);
                   30022:                         foreach ($ignore as $ig) {
                   30023:                             unset ($contents[$ig['attribs']['name']]);
                   30024:                         }
                   30025:                     }
                   30026:                     // install files as this name
                   30027:                     if (isset($instance['filelist']['install'])) {
                   30028:                         $installas = isset($instance['filelist']['install'][0]) ?
                   30029:                             $instance['filelist']['install'] :
                   30030:                             array($instance['filelist']['install']);
                   30031:                         foreach ($installas as $as) {
                   30032:                             $contents[$as['attribs']['name']]['attribs']['install-as'] =
                   30033:                                 $as['attribs']['as'];
                   30034:                         }
                   30035:                     }
                   30036:                 }
                   30037:                 if ($forfilecheck) {
                   30038:                     foreach ($contents as $file => $attrs) {
                   30039:                         $contents[$file] = $attrs['attribs'];
                   30040:                     }
                   30041:                 }
                   30042:                 return $contents;
                   30043:             }
                   30044:         } else { // simple release - no installconditions or install-as
                   30045:             if ($forfilecheck) {
                   30046:                 return $this->getFilelist();
                   30047:             }
                   30048:             return $contents;
                   30049:         }
                   30050:         // no releases matched
                   30051:         return PEAR::raiseError('No releases in package.xml matched the existing operating ' .
                   30052:             'system, extensions installed, or architecture, cannot install');
                   30053:     }
                   30054: 
                   30055:     /**
                   30056:      * This is only used at install-time, after all serialization
                   30057:      * is over.
                   30058:      * @param string file name
                   30059:      * @param string installed path
                   30060:      */
                   30061:     function setInstalledAs($file, $path)
                   30062:     {
                   30063:         if ($path) {
                   30064:             return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
                   30065:         }
                   30066:         unset($this->_packageInfo['filelist'][$file]['installed_as']);
                   30067:     }
                   30068: 
                   30069:     function getInstalledLocation($file)
                   30070:     {
                   30071:         if (isset($this->_packageInfo['filelist'][$file]['installed_as'])) {
                   30072:             return $this->_packageInfo['filelist'][$file]['installed_as'];
                   30073:         }
                   30074:         return false;
                   30075:     }
                   30076: 
                   30077:     /**
                   30078:      * This is only used at install-time, after all serialization
                   30079:      * is over.
                   30080:      */
                   30081:     function installedFile($file, $atts)
                   30082:     {
                   30083:         if (isset($this->_packageInfo['filelist'][$file])) {
                   30084:             $this->_packageInfo['filelist'][$file] =
                   30085:                 array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']);
                   30086:         } else {
                   30087:             $this->_packageInfo['filelist'][$file] = $atts['attribs'];
                   30088:         }
                   30089:     }
                   30090: 
                   30091:     /**
                   30092:      * Retrieve the contents tag
                   30093:      */
                   30094:     function getContents()
                   30095:     {
                   30096:         if (isset($this->_packageInfo['contents'])) {
                   30097:             return $this->_packageInfo['contents'];
                   30098:         }
                   30099:         return false;
                   30100:     }
                   30101: 
                   30102:     /**
                   30103:      * @param string full path to file
                   30104:      * @param string attribute name
                   30105:      * @param string attribute value
                   30106:      * @param int risky but fast - use this to choose a file based on its position in the list
                   30107:      *            of files.  Index is zero-based like PHP arrays.
                   30108:      * @return bool success of operation
                   30109:      */
                   30110:     function setFileAttribute($filename, $attr, $value, $index = false)
                   30111:     {
                   30112:         $this->_isValid = 0;
                   30113:         if (in_array($attr, array('role', 'name', 'baseinstalldir'))) {
                   30114:             $this->_filesValid = false;
                   30115:         }
                   30116:         if ($index !== false &&
                   30117:               isset($this->_packageInfo['contents']['dir']['file'][$index]['attribs'])) {
                   30118:             $this->_packageInfo['contents']['dir']['file'][$index]['attribs'][$attr] = $value;
                   30119:             return true;
                   30120:         }
                   30121:         if (!isset($this->_packageInfo['contents']['dir']['file'])) {
                   30122:             return false;
                   30123:         }
                   30124:         $files = $this->_packageInfo['contents']['dir']['file'];
                   30125:         if (!isset($files[0])) {
                   30126:             $files = array($files);
                   30127:             $ind = false;
                   30128:         } else {
                   30129:             $ind = true;
                   30130:         }
                   30131:         foreach ($files as $i => $file) {
                   30132:             if (isset($file['attribs'])) {
                   30133:                 if ($file['attribs']['name'] == $filename) {
                   30134:                     if ($ind) {
                   30135:                         $this->_packageInfo['contents']['dir']['file'][$i]['attribs'][$attr] = $value;
                   30136:                     } else {
                   30137:                         $this->_packageInfo['contents']['dir']['file']['attribs'][$attr] = $value;
                   30138:                     }
                   30139:                     return true;
                   30140:                 }
                   30141:             }
                   30142:         }
                   30143:         return false;
                   30144:     }
                   30145: 
                   30146:     function setDirtree($path)
                   30147:     {
                   30148:         if (!isset($this->_packageInfo['dirtree'])) {
                   30149:             $this->_packageInfo['dirtree'] = array();
                   30150:         }
                   30151:         $this->_packageInfo['dirtree'][$path] = true;
                   30152:     }
                   30153: 
                   30154:     function getDirtree()
                   30155:     {
                   30156:         if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) {
                   30157:             return $this->_packageInfo['dirtree'];
                   30158:         }
                   30159:         return false;
                   30160:     }
                   30161: 
                   30162:     function resetDirtree()
                   30163:     {
                   30164:         unset($this->_packageInfo['dirtree']);
                   30165:     }
                   30166: 
                   30167:     /**
                   30168:      * Determines whether this package claims it is compatible with the version of
                   30169:      * the package that has a recommended version dependency
                   30170:      * @param PEAR_PackageFile_v2|PEAR_PackageFile_v1|PEAR_Downloader_Package
                   30171:      * @return boolean
                   30172:      */
                   30173:     function isCompatible($pf)
                   30174:     {
                   30175:         if (!isset($this->_packageInfo['compatible'])) {
                   30176:             return false;
                   30177:         }
                   30178:         if (!isset($this->_packageInfo['channel'])) {
                   30179:             return false;
                   30180:         }
                   30181:         $me = $pf->getVersion();
                   30182:         $compatible = $this->_packageInfo['compatible'];
                   30183:         if (!isset($compatible[0])) {
                   30184:             $compatible = array($compatible);
                   30185:         }
                   30186:         $found = false;
                   30187:         foreach ($compatible as $info) {
                   30188:             if (strtolower($info['name']) == strtolower($pf->getPackage())) {
                   30189:                 if (strtolower($info['channel']) == strtolower($pf->getChannel())) {
                   30190:                     $found = true;
                   30191:                     break;
                   30192:                 }
                   30193:             }
                   30194:         }
                   30195:         if (!$found) {
                   30196:             return false;
                   30197:         }
                   30198:         if (isset($info['exclude'])) {
                   30199:             if (!isset($info['exclude'][0])) {
                   30200:                 $info['exclude'] = array($info['exclude']);
                   30201:             }
                   30202:             foreach ($info['exclude'] as $exclude) {
                   30203:                 if (version_compare($me, $exclude, '==')) {
                   30204:                     return false;
                   30205:                 }
                   30206:             }
                   30207:         }
                   30208:         if (version_compare($me, $info['min'], '>=') && version_compare($me, $info['max'], '<=')) {
                   30209:             return true;
                   30210:         }
                   30211:         return false;
                   30212:     }
                   30213: 
                   30214:     /**
                   30215:      * @return array|false
                   30216:      */
                   30217:     function getCompatible()
                   30218:     {
                   30219:         if (isset($this->_packageInfo['compatible'])) {
                   30220:             return $this->_packageInfo['compatible'];
                   30221:         }
                   30222:         return false;
                   30223:     }
                   30224: 
                   30225:     function getDependencies()
                   30226:     {
                   30227:         if (isset($this->_packageInfo['dependencies'])) {
                   30228:             return $this->_packageInfo['dependencies'];
                   30229:         }
                   30230:         return false;
                   30231:     }
                   30232: 
                   30233:     function isSubpackageOf($p)
                   30234:     {
                   30235:         return $p->isSubpackage($this);
                   30236:     }
                   30237: 
                   30238:     /**
                   30239:      * Determines whether the passed in package is a subpackage of this package.
                   30240:      *
                   30241:      * No version checking is done, only name verification.
                   30242:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   30243:      * @return bool
                   30244:      */
                   30245:     function isSubpackage($p)
                   30246:     {
                   30247:         $sub = array();
                   30248:         if (isset($this->_packageInfo['dependencies']['required']['subpackage'])) {
                   30249:             $sub = $this->_packageInfo['dependencies']['required']['subpackage'];
                   30250:             if (!isset($sub[0])) {
                   30251:                 $sub = array($sub);
                   30252:             }
                   30253:         }
                   30254:         if (isset($this->_packageInfo['dependencies']['optional']['subpackage'])) {
                   30255:             $sub1 = $this->_packageInfo['dependencies']['optional']['subpackage'];
                   30256:             if (!isset($sub1[0])) {
                   30257:                 $sub1 = array($sub1);
                   30258:             }
                   30259:             $sub = array_merge($sub, $sub1);
                   30260:         }
                   30261:         if (isset($this->_packageInfo['dependencies']['group'])) {
                   30262:             $group = $this->_packageInfo['dependencies']['group'];
                   30263:             if (!isset($group[0])) {
                   30264:                 $group = array($group);
                   30265:             }
                   30266:             foreach ($group as $deps) {
                   30267:                 if (isset($deps['subpackage'])) {
                   30268:                     $sub2 = $deps['subpackage'];
                   30269:                     if (!isset($sub2[0])) {
                   30270:                         $sub2 = array($sub2);
                   30271:                     }
                   30272:                     $sub = array_merge($sub, $sub2);
                   30273:                 }
                   30274:             }
                   30275:         }
                   30276:         foreach ($sub as $dep) {
                   30277:             if (strtolower($dep['name']) == strtolower($p->getPackage())) {
                   30278:                 if (isset($dep['channel'])) {
                   30279:                     if (strtolower($dep['channel']) == strtolower($p->getChannel())) {
                   30280:                         return true;
                   30281:                     }
                   30282:                 } else {
                   30283:                     if ($dep['uri'] == $p->getURI()) {
                   30284:                         return true;
                   30285:                     }
                   30286:                 }
                   30287:             }
                   30288:         }
                   30289:         return false;
                   30290:     }
                   30291: 
                   30292:     function dependsOn($package, $channel)
                   30293:     {
                   30294:         if (!($deps = $this->getDependencies())) {
                   30295:             return false;
                   30296:         }
                   30297:         foreach (array('package', 'subpackage') as $type) {
                   30298:             foreach (array('required', 'optional') as $needed) {
                   30299:                 if (isset($deps[$needed][$type])) {
                   30300:                     if (!isset($deps[$needed][$type][0])) {
                   30301:                         $deps[$needed][$type] = array($deps[$needed][$type]);
                   30302:                     }
                   30303:                     foreach ($deps[$needed][$type] as $dep) {
                   30304:                         $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
                   30305:                         if (strtolower($dep['name']) == strtolower($package) &&
                   30306:                               $depchannel == $channel) {
                   30307:                             return true;
                   30308:                         }
                   30309:                     }
                   30310:                 }
                   30311:             }
                   30312:             if (isset($deps['group'])) {
                   30313:                 if (!isset($deps['group'][0])) {
                   30314:                     $dep['group'] = array($deps['group']);
                   30315:                 }
                   30316:                 foreach ($deps['group'] as $group) {
                   30317:                     if (isset($group[$type])) {
                   30318:                         if (!is_array($group[$type])) {
                   30319:                             $group[$type] = array($group[$type]);
                   30320:                         }
                   30321:                         foreach ($group[$type] as $dep) {
                   30322:                             $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
                   30323:                             if (strtolower($dep['name']) == strtolower($package) &&
                   30324:                                   $depchannel == $channel) {
                   30325:                                 return true;
                   30326:                             }
                   30327:                         }
                   30328:                     }
                   30329:                 }
                   30330:             }
                   30331:         }
                   30332:         return false;
                   30333:     }
                   30334: 
                   30335:     /**
                   30336:      * Get the contents of a dependency group
                   30337:      * @param string
                   30338:      * @return array|false
                   30339:      */
                   30340:     function getDependencyGroup($name)
                   30341:     {
                   30342:         $name = strtolower($name);
                   30343:         if (!isset($this->_packageInfo['dependencies']['group'])) {
                   30344:             return false;
                   30345:         }
                   30346:         $groups = $this->_packageInfo['dependencies']['group'];
                   30347:         if (!isset($groups[0])) {
                   30348:             $groups = array($groups);
                   30349:         }
                   30350:         foreach ($groups as $group) {
                   30351:             if (strtolower($group['attribs']['name']) == $name) {
                   30352:                 return $group;
                   30353:             }
                   30354:         }
                   30355:         return false;
                   30356:     }
                   30357: 
                   30358:     /**
                   30359:      * Retrieve a partial package.xml 1.0 representation of dependencies
                   30360:      *
                   30361:      * a very limited representation of dependencies is returned by this method.
                   30362:      * The <exclude> tag for excluding certain versions of a dependency is
                   30363:      * completely ignored.  In addition, dependency groups are ignored, with the
                   30364:      * assumption that all dependencies in dependency groups are also listed in
                   30365:      * the optional group that work with all dependency groups
                   30366:      * @param boolean return package.xml 2.0 <dependencies> tag
                   30367:      * @return array|false
                   30368:      */
                   30369:     function getDeps($raw = false, $nopearinstaller = false)
                   30370:     {
                   30371:         if (isset($this->_packageInfo['dependencies'])) {
                   30372:             if ($raw) {
                   30373:                 return $this->_packageInfo['dependencies'];
                   30374:             }
                   30375:             $ret = array();
                   30376:             $map = array(
                   30377:                 'php' => 'php',
                   30378:                 'package' => 'pkg',
                   30379:                 'subpackage' => 'pkg',
                   30380:                 'extension' => 'ext',
                   30381:                 'os' => 'os',
                   30382:                 'pearinstaller' => 'pkg',
                   30383:                 );
                   30384:             foreach (array('required', 'optional') as $type) {
                   30385:                 $optional = ($type == 'optional') ? 'yes' : 'no';
                   30386:                 if (!isset($this->_packageInfo['dependencies'][$type])
                   30387:                     || empty($this->_packageInfo['dependencies'][$type])) {
                   30388:                     continue;
                   30389:                 }
                   30390:                 foreach ($this->_packageInfo['dependencies'][$type] as $dtype => $deps) {
                   30391:                     if ($dtype == 'pearinstaller' && $nopearinstaller) {
                   30392:                         continue;
                   30393:                     }
                   30394:                     if (!isset($deps[0])) {
                   30395:                         $deps = array($deps);
                   30396:                     }
                   30397:                     foreach ($deps as $dep) {
                   30398:                         if (!isset($map[$dtype])) {
                   30399:                             // no support for arch type
                   30400:                             continue;
                   30401:                         }
                   30402:                         if ($dtype == 'pearinstaller') {
                   30403:                             $dep['name'] = 'PEAR';
                   30404:                             $dep['channel'] = 'pear.php.net';
                   30405:                         }
                   30406:                         $s = array('type' => $map[$dtype]);
                   30407:                         if (isset($dep['channel'])) {
                   30408:                             $s['channel'] = $dep['channel'];
                   30409:                         }
                   30410:                         if (isset($dep['uri'])) {
                   30411:                             $s['uri'] = $dep['uri'];
                   30412:                         }
                   30413:                         if (isset($dep['name'])) {
                   30414:                             $s['name'] = $dep['name'];
                   30415:                         }
                   30416:                         if (isset($dep['conflicts'])) {
                   30417:                             $s['rel'] = 'not';
                   30418:                         } else {
                   30419:                             if (!isset($dep['min']) &&
                   30420:                                   !isset($dep['max'])) {
                   30421:                                 $s['rel'] = 'has';
                   30422:                                 $s['optional'] = $optional;
                   30423:                             } elseif (isset($dep['min']) &&
                   30424:                                   isset($dep['max'])) {
                   30425:                                 $s['rel'] = 'ge';
                   30426:                                 $s1 = $s;
                   30427:                                 $s1['rel'] = 'le';
                   30428:                                 $s['version'] = $dep['min'];
                   30429:                                 $s1['version'] = $dep['max'];
                   30430:                                 if (isset($dep['channel'])) {
                   30431:                                     $s1['channel'] = $dep['channel'];
                   30432:                                 }
                   30433:                                 if ($dtype != 'php') {
                   30434:                                     $s['name'] = $dep['name'];
                   30435:                                     $s1['name'] = $dep['name'];
                   30436:                                 }
                   30437:                                 $s['optional'] = $optional;
                   30438:                                 $s1['optional'] = $optional;
                   30439:                                 $ret[] = $s1;
                   30440:                             } elseif (isset($dep['min'])) {
                   30441:                                 if (isset($dep['exclude']) &&
                   30442:                                       $dep['exclude'] == $dep['min']) {
                   30443:                                     $s['rel'] = 'gt';
                   30444:                                 } else {
                   30445:                                     $s['rel'] = 'ge';
                   30446:                                 }
                   30447:                                 $s['version'] = $dep['min'];
                   30448:                                 $s['optional'] = $optional;
                   30449:                                 if ($dtype != 'php') {
                   30450:                                     $s['name'] = $dep['name'];
                   30451:                                 }
                   30452:                             } elseif (isset($dep['max'])) {
                   30453:                                 if (isset($dep['exclude']) &&
                   30454:                                       $dep['exclude'] == $dep['max']) {
                   30455:                                     $s['rel'] = 'lt';
                   30456:                                 } else {
                   30457:                                     $s['rel'] = 'le';
                   30458:                                 }
                   30459:                                 $s['version'] = $dep['max'];
                   30460:                                 $s['optional'] = $optional;
                   30461:                                 if ($dtype != 'php') {
                   30462:                                     $s['name'] = $dep['name'];
                   30463:                                 }
                   30464:                             }
                   30465:                         }
                   30466:                         $ret[] = $s;
                   30467:                     }
                   30468:                 }
                   30469:             }
                   30470:             if (count($ret)) {
                   30471:                 return $ret;
                   30472:             }
                   30473:         }
                   30474:         return false;
                   30475:     }
                   30476: 
                   30477:     /**
                   30478:      * @return php|extsrc|extbin|zendextsrc|zendextbin|bundle|false
                   30479:      */
                   30480:     function getPackageType()
                   30481:     {
                   30482:         if (isset($this->_packageInfo['phprelease'])) {
                   30483:             return 'php';
                   30484:         }
                   30485:         if (isset($this->_packageInfo['extsrcrelease'])) {
                   30486:             return 'extsrc';
                   30487:         }
                   30488:         if (isset($this->_packageInfo['extbinrelease'])) {
                   30489:             return 'extbin';
                   30490:         }
                   30491:         if (isset($this->_packageInfo['zendextsrcrelease'])) {
                   30492:             return 'zendextsrc';
                   30493:         }
                   30494:         if (isset($this->_packageInfo['zendextbinrelease'])) {
                   30495:             return 'zendextbin';
                   30496:         }
                   30497:         if (isset($this->_packageInfo['bundle'])) {
                   30498:             return 'bundle';
                   30499:         }
                   30500:         return false;
                   30501:     }
                   30502: 
                   30503:     /**
                   30504:      * @return array|false
                   30505:      */
                   30506:     function getReleases()
                   30507:     {
                   30508:         $type = $this->getPackageType();
                   30509:         if ($type != 'bundle') {
                   30510:             $type .= 'release';
                   30511:         }
                   30512:         if ($this->getPackageType() && isset($this->_packageInfo[$type])) {
                   30513:             return $this->_packageInfo[$type];
                   30514:         }
                   30515:         return false;
                   30516:     }
                   30517: 
                   30518:     /**
                   30519:      * @return array
                   30520:      */
                   30521:     function getChangelog()
                   30522:     {
                   30523:         if (isset($this->_packageInfo['changelog'])) {
                   30524:             return $this->_packageInfo['changelog'];
                   30525:         }
                   30526:         return false;
                   30527:     }
                   30528: 
                   30529:     function hasDeps()
                   30530:     {
                   30531:         return isset($this->_packageInfo['dependencies']);
                   30532:     }
                   30533: 
                   30534:     function getPackagexmlVersion()
                   30535:     {
                   30536:         if (isset($this->_packageInfo['zendextsrcrelease'])) {
                   30537:             return '2.1';
                   30538:         }
                   30539:         if (isset($this->_packageInfo['zendextbinrelease'])) {
                   30540:             return '2.1';
                   30541:         }
                   30542:         return '2.0';
                   30543:     }
                   30544: 
                   30545:     /**
                   30546:      * @return array|false
                   30547:      */
                   30548:     function getSourcePackage()
                   30549:     {
                   30550:         if (isset($this->_packageInfo['extbinrelease']) ||
                   30551:               isset($this->_packageInfo['zendextbinrelease'])) {
                   30552:             return array('channel' => $this->_packageInfo['srcchannel'],
                   30553:                          'package' => $this->_packageInfo['srcpackage']);
                   30554:         }
                   30555:         return false;
                   30556:     }
                   30557: 
                   30558:     function getBundledPackages()
                   30559:     {
                   30560:         if (isset($this->_packageInfo['bundle'])) {
                   30561:             return $this->_packageInfo['contents']['bundledpackage'];
                   30562:         }
                   30563:         return false;
                   30564:     }
                   30565: 
                   30566:     function getLastModified()
                   30567:     {
                   30568:         if (isset($this->_packageInfo['_lastmodified'])) {
                   30569:             return $this->_packageInfo['_lastmodified'];
                   30570:         }
                   30571:         return false;
                   30572:     }
                   30573: 
                   30574:     /**
                   30575:      * Get the contents of a file listed within the package.xml
                   30576:      * @param string
                   30577:      * @return string
                   30578:      */
                   30579:     function getFileContents($file)
                   30580:     {
                   30581:         if ($this->_archiveFile == $this->_packageFile) { // unpacked
                   30582:             $dir = dirname($this->_packageFile);
                   30583:             $file = $dir . DIRECTORY_SEPARATOR . $file;
                   30584:             $file = str_replace(array('/', '\\'),
                   30585:                 array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file);
                   30586:             if (file_exists($file) && is_readable($file)) {
                   30587:                 return implode('', file($file));
                   30588:             }
                   30589:         } else { // tgz
                   30590:             $tar = &new Archive_Tar($this->_archiveFile);
                   30591:             $tar->pushErrorHandling(PEAR_ERROR_RETURN);
                   30592:             if ($file != 'package.xml' && $file != 'package2.xml') {
                   30593:                 $file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file;
                   30594:             }
                   30595:             $file = $tar->extractInString($file);
                   30596:             $tar->popErrorHandling();
                   30597:             if (PEAR::isError($file)) {
                   30598:                 return PEAR::raiseError("Cannot locate file '$file' in archive");
                   30599:             }
                   30600:             return $file;
                   30601:         }
                   30602:     }
                   30603: 
                   30604:     function &getRW()
                   30605:     {
                   30606:         if (!class_exists('PEAR_PackageFile_v2_rw')) {
                   30607:             require_once 'PEAR/PackageFile/v2/rw.php';
                   30608:         }
                   30609:         $a = new PEAR_PackageFile_v2_rw;
                   30610:         foreach (get_object_vars($this) as $name => $unused) {
                   30611:             if (!isset($this->$name)) {
                   30612:                 continue;
                   30613:             }
                   30614:             if ($name == '_config' || $name == '_logger'|| $name == '_registry' ||
                   30615:                   $name == '_stack') {
                   30616:                 $a->$name = &$this->$name;
                   30617:             } else {
                   30618:                 $a->$name = $this->$name;
                   30619:             }
                   30620:         }
                   30621:         return $a;
                   30622:     }
                   30623: 
                   30624:     function &getDefaultGenerator()
                   30625:     {
                   30626:         if (!class_exists('PEAR_PackageFile_Generator_v2')) {
                   30627:             require_once 'PEAR/PackageFile/Generator/v2.php';
                   30628:         }
                   30629:         $a = &new PEAR_PackageFile_Generator_v2($this);
                   30630:         return $a;
                   30631:     }
                   30632: 
                   30633:     function analyzeSourceCode($file, $string = false)
                   30634:     {
                   30635:         if (!isset($this->_v2Validator) ||
                   30636:               !is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) {
                   30637:             if (!class_exists('PEAR_PackageFile_v2_Validator')) {
                   30638:                 require_once 'PEAR/PackageFile/v2/Validator.php';
                   30639:             }
                   30640:             $this->_v2Validator = new PEAR_PackageFile_v2_Validator;
                   30641:         }
                   30642:         return $this->_v2Validator->analyzeSourceCode($file, $string);
                   30643:     }
                   30644: 
                   30645:     function validate($state = PEAR_VALIDATE_NORMAL)
                   30646:     {
                   30647:         if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) {
                   30648:             return false;
                   30649:         }
                   30650:         if (!isset($this->_v2Validator) ||
                   30651:               !is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) {
                   30652:             if (!class_exists('PEAR_PackageFile_v2_Validator')) {
                   30653:                 require_once 'PEAR/PackageFile/v2/Validator.php';
                   30654:             }
                   30655:             $this->_v2Validator = new PEAR_PackageFile_v2_Validator;
                   30656:         }
                   30657:         if (isset($this->_packageInfo['xsdversion'])) {
                   30658:             unset($this->_packageInfo['xsdversion']);
                   30659:         }
                   30660:         return $this->_v2Validator->validate($this, $state);
                   30661:     }
                   30662: 
                   30663:     function getTasksNs()
                   30664:     {
                   30665:         if (!isset($this->_tasksNs)) {
                   30666:             if (isset($this->_packageInfo['attribs'])) {
                   30667:                 foreach ($this->_packageInfo['attribs'] as $name => $value) {
                   30668:                     if ($value == 'http://pear.php.net/dtd/tasks-1.0') {
                   30669:                         $this->_tasksNs = str_replace('xmlns:', '', $name);
                   30670:                         break;
                   30671:                     }
                   30672:                 }
                   30673:             }
                   30674:         }
                   30675:         return $this->_tasksNs;
                   30676:     }
                   30677: 
                   30678:     /**
                   30679:      * Determine whether a task name is a valid task.  Custom tasks may be defined
                   30680:      * using subdirectories by putting a "-" in the name, as in <tasks:mycustom-task>
                   30681:      *
                   30682:      * Note that this method will auto-load the task class file and test for the existence
                   30683:      * of the name with "-" replaced by "_" as in PEAR/Task/mycustom/task.php makes class
                   30684:      * PEAR_Task_mycustom_task
                   30685:      * @param string
                   30686:      * @return boolean
                   30687:      */
                   30688:     function getTask($task)
                   30689:     {
                   30690:         $this->getTasksNs();
                   30691:         // transform all '-' to '/' and 'tasks:' to '' so tasks:replace becomes replace
                   30692:         $task = str_replace(array($this->_tasksNs . ':', '-'), array('', ' '), $task);
                   30693:         $taskfile = str_replace(' ', '/', ucwords($task));
                   30694:         $task = str_replace(array(' ', '/'), '_', ucwords($task));
                   30695:         if (class_exists("PEAR_Task_$task")) {
                   30696:             return "PEAR_Task_$task";
                   30697:         }
                   30698:         $fp = @fopen("PEAR/Task/$taskfile.php", 'r', true);
                   30699:         if ($fp) {
                   30700:             fclose($fp);
                   30701:             require_once "PEAR/Task/$taskfile.php";
                   30702:             return "PEAR_Task_$task";
                   30703:         }
                   30704:         return false;
                   30705:     }
                   30706: 
                   30707:     /**
                   30708:      * Key-friendly array_splice
                   30709:      * @param tagname to splice a value in before
                   30710:      * @param mixed the value to splice in
                   30711:      * @param string the new tag name
                   30712:      */
                   30713:     function _ksplice($array, $key, $value, $newkey)
                   30714:     {
                   30715:         $offset = array_search($key, array_keys($array));
                   30716:         $after = array_slice($array, $offset);
                   30717:         $before = array_slice($array, 0, $offset);
                   30718:         $before[$newkey] = $value;
                   30719:         return array_merge($before, $after);
                   30720:     }
                   30721: 
                   30722:     /**
                   30723:      * @param array a list of possible keys, in the order they may occur
                   30724:      * @param mixed contents of the new package.xml tag
                   30725:      * @param string tag name
                   30726:      * @access private
                   30727:      */
                   30728:     function _insertBefore($array, $keys, $contents, $newkey)
                   30729:     {
                   30730:         foreach ($keys as $key) {
                   30731:             if (isset($array[$key])) {
                   30732:                 return $array = $this->_ksplice($array, $key, $contents, $newkey);
                   30733:             }
                   30734:         }
                   30735:         $array[$newkey] = $contents;
                   30736:         return $array;
                   30737:     }
                   30738: 
                   30739:     /**
                   30740:      * @param subsection of {@link $_packageInfo}
                   30741:      * @param array|string tag contents
                   30742:      * @param array format:
                   30743:      * <pre>
                   30744:      * array(
                   30745:      *   tagname => array(list of tag names that follow this one),
                   30746:      *   childtagname => array(list of child tag names that follow this one),
                   30747:      * )
                   30748:      * </pre>
                   30749:      *
                   30750:      * This allows construction of nested tags
                   30751:      * @access private
                   30752:      */
                   30753:     function _mergeTag($manip, $contents, $order)
                   30754:     {
                   30755:         if (count($order)) {
                   30756:             foreach ($order as $tag => $curorder) {
                   30757:                 if (!isset($manip[$tag])) {
                   30758:                     // ensure that the tag is set up
                   30759:                     $manip = $this->_insertBefore($manip, $curorder, array(), $tag);
                   30760:                 }
                   30761:                 if (count($order) > 1) {
                   30762:                     $manip[$tag] = $this->_mergeTag($manip[$tag], $contents, array_slice($order, 1));
                   30763:                     return $manip;
                   30764:                 }
                   30765:             }
                   30766:         } else {
                   30767:             return $manip;
                   30768:         }
                   30769:         if (is_array($manip[$tag]) && !empty($manip[$tag]) && isset($manip[$tag][0])) {
                   30770:             $manip[$tag][] = $contents;
                   30771:         } else {
                   30772:             if (!count($manip[$tag])) {
                   30773:                 $manip[$tag] = $contents;
                   30774:             } else {
                   30775:                 $manip[$tag] = array($manip[$tag]);
                   30776:                 $manip[$tag][] = $contents;
                   30777:             }
                   30778:         }
                   30779:         return $manip;
                   30780:     }
                   30781: }
                   30782: ?>
1.1.1.2 ! misho    30783: PEAR-1.9.4/PEAR/REST/10.php0000644000076500000240000007772411605156614013512 0ustar  helgistaff<?php
1.1       misho    30784: /**
                   30785:  * PEAR_REST_10
                   30786:  *
                   30787:  * PHP versions 4 and 5
                   30788:  *
                   30789:  * @category   pear
                   30790:  * @package    PEAR
                   30791:  * @author     Greg Beaver <cellog@php.net>
                   30792:  * @copyright  1997-2009 The Authors
                   30793:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   30794:  * @version    CVS: $Id: 10.php 313023 2011-07-06 19:17:11Z dufuz $
                   30795:  * @link       http://pear.php.net/package/PEAR
                   30796:  * @since      File available since Release 1.4.0a12
                   30797:  */
                   30798: 
                   30799: /**
                   30800:  * For downloading REST xml/txt files
                   30801:  */
                   30802: require_once 'PEAR/REST.php';
                   30803: 
                   30804: /**
                   30805:  * Implement REST 1.0
                   30806:  *
                   30807:  * @category   pear
                   30808:  * @package    PEAR
                   30809:  * @author     Greg Beaver <cellog@php.net>
                   30810:  * @copyright  1997-2009 The Authors
                   30811:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   30812:  * @version    Release: 1.9.4
                   30813:  * @link       http://pear.php.net/package/PEAR
                   30814:  * @since      Class available since Release 1.4.0a12
                   30815:  */
                   30816: class PEAR_REST_10
                   30817: {
                   30818:     /**
                   30819:      * @var PEAR_REST
                   30820:      */
                   30821:     var $_rest;
                   30822:     function PEAR_REST_10($config, $options = array())
                   30823:     {
                   30824:         $this->_rest = &new PEAR_REST($config, $options);
                   30825:     }
                   30826: 
                   30827:     /**
                   30828:      * Retrieve information about a remote package to be downloaded from a REST server
                   30829:      *
                   30830:      * @param string $base The uri to prepend to all REST calls
                   30831:      * @param array $packageinfo an array of format:
                   30832:      * <pre>
                   30833:      *  array(
                   30834:      *   'package' => 'packagename',
                   30835:      *   'channel' => 'channelname',
                   30836:      *  ['state' => 'alpha' (or valid state),]
                   30837:      *  -or-
                   30838:      *  ['version' => '1.whatever']
                   30839:      * </pre>
                   30840:      * @param string $prefstate Current preferred_state config variable value
                   30841:      * @param bool $installed the installed version of this package to compare against
                   30842:      * @return array|false|PEAR_Error see {@link _returnDownloadURL()}
                   30843:      */
                   30844:     function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false)
                   30845:     {
                   30846:         $states = $this->betterStates($prefstate, true);
                   30847:         if (!$states) {
                   30848:             return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
                   30849:         }
                   30850: 
                   30851:         $channel  = $packageinfo['channel'];
                   30852:         $package  = $packageinfo['package'];
                   30853:         $state    = isset($packageinfo['state'])   ? $packageinfo['state']   : null;
                   30854:         $version  = isset($packageinfo['version']) ? $packageinfo['version'] : null;
                   30855:         $restFile = $base . 'r/' . strtolower($package) . '/allreleases.xml';
                   30856: 
                   30857:         $info = $this->_rest->retrieveData($restFile, false, false, $channel);
                   30858:         if (PEAR::isError($info)) {
                   30859:             return PEAR::raiseError('No releases available for package "' .
                   30860:                 $channel . '/' . $package . '"');
                   30861:         }
                   30862: 
                   30863:         if (!isset($info['r'])) {
                   30864:             return false;
                   30865:         }
                   30866: 
                   30867:         $release = $found = false;
                   30868:         if (!is_array($info['r']) || !isset($info['r'][0])) {
                   30869:             $info['r'] = array($info['r']);
                   30870:         }
                   30871: 
                   30872:         foreach ($info['r'] as $release) {
                   30873:             if (!isset($this->_rest->_options['force']) && ($installed &&
                   30874:                   version_compare($release['v'], $installed, '<'))) {
                   30875:                 continue;
                   30876:             }
                   30877: 
                   30878:             if (isset($state)) {
                   30879:                 // try our preferred state first
                   30880:                 if ($release['s'] == $state) {
                   30881:                     $found = true;
                   30882:                     break;
                   30883:                 }
                   30884:                 // see if there is something newer and more stable
                   30885:                 // bug #7221
                   30886:                 if (in_array($release['s'], $this->betterStates($state), true)) {
                   30887:                     $found = true;
                   30888:                     break;
                   30889:                 }
                   30890:             } elseif (isset($version)) {
                   30891:                 if ($release['v'] == $version) {
                   30892:                     $found = true;
                   30893:                     break;
                   30894:                 }
                   30895:             } else {
                   30896:                 if (in_array($release['s'], $states)) {
                   30897:                     $found = true;
                   30898:                     break;
                   30899:                 }
                   30900:             }
                   30901:         }
                   30902: 
                   30903:         return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel);
                   30904:     }
                   30905: 
                   30906:     function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage,
                   30907:                                $prefstate = 'stable', $installed = false, $channel = false)
                   30908:     {
                   30909:         $states = $this->betterStates($prefstate, true);
                   30910:         if (!$states) {
                   30911:             return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
                   30912:         }
                   30913: 
                   30914:         $channel  = $dependency['channel'];
                   30915:         $package  = $dependency['name'];
                   30916:         $state    = isset($dependency['state'])   ? $dependency['state']   : null;
                   30917:         $version  = isset($dependency['version']) ? $dependency['version'] : null;
                   30918:         $restFile = $base . 'r/' . strtolower($package) . '/allreleases.xml';
                   30919: 
                   30920:         $info = $this->_rest->retrieveData($restFile, false, false, $channel);
                   30921:         if (PEAR::isError($info)) {
                   30922:             return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package']
                   30923:                 . '" dependency "' . $channel . '/' . $package . '" has no releases');
                   30924:         }
                   30925: 
                   30926:         if (!is_array($info) || !isset($info['r'])) {
                   30927:             return false;
                   30928:         }
                   30929: 
                   30930:         $exclude = array();
                   30931:         $min = $max = $recommended = false;
                   30932:         if ($xsdversion == '1.0') {
                   30933:             switch ($dependency['rel']) {
                   30934:                 case 'ge' :
                   30935:                     $min = $dependency['version'];
                   30936:                 break;
                   30937:                 case 'gt' :
                   30938:                     $min = $dependency['version'];
                   30939:                     $exclude = array($dependency['version']);
                   30940:                 break;
                   30941:                 case 'eq' :
                   30942:                     $recommended = $dependency['version'];
                   30943:                 break;
                   30944:                 case 'lt' :
                   30945:                     $max = $dependency['version'];
                   30946:                     $exclude = array($dependency['version']);
                   30947:                 break;
                   30948:                 case 'le' :
                   30949:                     $max = $dependency['version'];
                   30950:                 break;
                   30951:                 case 'ne' :
                   30952:                     $exclude = array($dependency['version']);
                   30953:                 break;
                   30954:             }
                   30955:         } else {
                   30956:             $min = isset($dependency['min']) ? $dependency['min'] : false;
                   30957:             $max = isset($dependency['max']) ? $dependency['max'] : false;
                   30958:             $recommended = isset($dependency['recommended']) ?
                   30959:                 $dependency['recommended'] : false;
                   30960:             if (isset($dependency['exclude'])) {
                   30961:                 if (!isset($dependency['exclude'][0])) {
                   30962:                     $exclude = array($dependency['exclude']);
                   30963:                 }
                   30964:             }
                   30965:         }
                   30966:         $release = $found = false;
                   30967:         if (!is_array($info['r']) || !isset($info['r'][0])) {
                   30968:             $info['r'] = array($info['r']);
                   30969:         }
                   30970:         foreach ($info['r'] as $release) {
                   30971:             if (!isset($this->_rest->_options['force']) && ($installed &&
                   30972:                   version_compare($release['v'], $installed, '<'))) {
                   30973:                 continue;
                   30974:             }
                   30975:             if (in_array($release['v'], $exclude)) { // skip excluded versions
                   30976:                 continue;
                   30977:             }
                   30978:             // allow newer releases to say "I'm OK with the dependent package"
                   30979:             if ($xsdversion == '2.0' && isset($release['co'])) {
                   30980:                 if (!is_array($release['co']) || !isset($release['co'][0])) {
                   30981:                     $release['co'] = array($release['co']);
                   30982:                 }
                   30983:                 foreach ($release['co'] as $entry) {
                   30984:                     if (isset($entry['x']) && !is_array($entry['x'])) {
                   30985:                         $entry['x'] = array($entry['x']);
                   30986:                     } elseif (!isset($entry['x'])) {
                   30987:                         $entry['x'] = array();
                   30988:                     }
                   30989:                     if ($entry['c'] == $deppackage['channel'] &&
                   30990:                           strtolower($entry['p']) == strtolower($deppackage['package']) &&
                   30991:                           version_compare($deppackage['version'], $entry['min'], '>=') &&
                   30992:                           version_compare($deppackage['version'], $entry['max'], '<=') &&
                   30993:                           !in_array($release['v'], $entry['x'])) {
                   30994:                         $recommended = $release['v'];
                   30995:                         break;
                   30996:                     }
                   30997:                 }
                   30998:             }
                   30999:             if ($recommended) {
                   31000:                 if ($release['v'] != $recommended) { // if we want a specific
                   31001:                     // version, then skip all others
                   31002:                     continue;
                   31003:                 } else {
                   31004:                     if (!in_array($release['s'], $states)) {
                   31005:                         // the stability is too low, but we must return the
                   31006:                         // recommended version if possible
                   31007:                         return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel);
                   31008:                     }
                   31009:                 }
                   31010:             }
                   31011:             if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions
                   31012:                 continue;
                   31013:             }
                   31014:             if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions
                   31015:                 continue;
                   31016:             }
                   31017:             if ($installed && version_compare($release['v'], $installed, '<')) {
                   31018:                 continue;
                   31019:             }
                   31020:             if (in_array($release['s'], $states)) { // if in the preferred state...
                   31021:                 $found = true; // ... then use it
                   31022:                 break;
                   31023:             }
                   31024:         }
                   31025:         return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel);
                   31026:     }
                   31027: 
                   31028:     /**
                   31029:      * Take raw data and return the array needed for processing a download URL
                   31030:      *
                   31031:      * @param string $base REST base uri
                   31032:      * @param string $package Package name
                   31033:      * @param array $release an array of format array('v' => version, 's' => state)
                   31034:      *                       describing the release to download
                   31035:      * @param array $info list of all releases as defined by allreleases.xml
                   31036:      * @param bool|null $found determines whether the release was found or this is the next
                   31037:      *                    best alternative.  If null, then versions were skipped because
                   31038:      *                    of PHP dependency
                   31039:      * @return array|PEAR_Error
                   31040:      * @access private
                   31041:      */
                   31042:     function _returnDownloadURL($base, $package, $release, $info, $found, $phpversion = false, $channel = false)
                   31043:     {
                   31044:         if (!$found) {
                   31045:             $release = $info['r'][0];
                   31046:         }
                   31047: 
                   31048:         $packageLower = strtolower($package);
                   31049:         $pinfo = $this->_rest->retrieveCacheFirst($base . 'p/' . $packageLower . '/' .
                   31050:             'info.xml', false, false, $channel);
                   31051:         if (PEAR::isError($pinfo)) {
                   31052:             return PEAR::raiseError('Package "' . $package .
                   31053:                 '" does not have REST info xml available');
                   31054:         }
                   31055: 
                   31056:         $releaseinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . $packageLower . '/' .
                   31057:             $release['v'] . '.xml', false, false, $channel);
                   31058:         if (PEAR::isError($releaseinfo)) {
                   31059:             return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] .
                   31060:                 '" does not have REST xml available');
                   31061:         }
                   31062: 
                   31063:         $packagexml = $this->_rest->retrieveCacheFirst($base . 'r/' . $packageLower . '/' .
                   31064:             'deps.' . $release['v'] . '.txt', false, true, $channel);
                   31065:         if (PEAR::isError($packagexml)) {
                   31066:             return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] .
                   31067:                 '" does not have REST dependency information available');
                   31068:         }
                   31069: 
                   31070:         $packagexml = unserialize($packagexml);
                   31071:         if (!$packagexml) {
                   31072:             $packagexml = array();
                   31073:         }
                   31074: 
                   31075:         $allinfo = $this->_rest->retrieveData($base . 'r/' . $packageLower .
                   31076:             '/allreleases.xml', false, false, $channel);
                   31077:         if (PEAR::isError($allinfo)) {
                   31078:             return $allinfo;
                   31079:         }
                   31080: 
                   31081:         if (!is_array($allinfo['r']) || !isset($allinfo['r'][0])) {
                   31082:             $allinfo['r'] = array($allinfo['r']);
                   31083:         }
                   31084: 
                   31085:         $compatible = false;
                   31086:         foreach ($allinfo['r'] as $release) {
                   31087:             if ($release['v'] != $releaseinfo['v']) {
                   31088:                 continue;
                   31089:             }
                   31090: 
                   31091:             if (!isset($release['co'])) {
                   31092:                 break;
                   31093:             }
                   31094: 
                   31095:             $compatible = array();
                   31096:             if (!is_array($release['co']) || !isset($release['co'][0])) {
                   31097:                 $release['co'] = array($release['co']);
                   31098:             }
                   31099: 
                   31100:             foreach ($release['co'] as $entry) {
                   31101:                 $comp = array();
                   31102:                 $comp['name']    = $entry['p'];
                   31103:                 $comp['channel'] = $entry['c'];
                   31104:                 $comp['min']     = $entry['min'];
                   31105:                 $comp['max']     = $entry['max'];
                   31106:                 if (isset($entry['x']) && !is_array($entry['x'])) {
                   31107:                     $comp['exclude'] = $entry['x'];
                   31108:                 }
                   31109: 
                   31110:                 $compatible[] = $comp;
                   31111:             }
                   31112: 
                   31113:             if (count($compatible) == 1) {
                   31114:                 $compatible = $compatible[0];
                   31115:             }
                   31116: 
                   31117:             break;
                   31118:         }
                   31119: 
                   31120:         $deprecated = false;
                   31121:         if (isset($pinfo['dc']) && isset($pinfo['dp'])) {
                   31122:             if (is_array($pinfo['dp'])) {
                   31123:                 $deprecated = array('channel' => (string) $pinfo['dc'],
                   31124:                                     'package' => trim($pinfo['dp']['_content']));
                   31125:             } else {
                   31126:                 $deprecated = array('channel' => (string) $pinfo['dc'],
                   31127:                                     'package' => trim($pinfo['dp']));
                   31128:             }
                   31129:         }
                   31130: 
                   31131:         $return = array(
                   31132:             'version'    => $releaseinfo['v'],
                   31133:             'info'       => $packagexml,
                   31134:             'package'    => $releaseinfo['p']['_content'],
                   31135:             'stability'  => $releaseinfo['st'],
                   31136:             'compatible' => $compatible,
                   31137:             'deprecated' => $deprecated,
                   31138:         );
                   31139: 
                   31140:         if ($found) {
                   31141:             $return['url'] = $releaseinfo['g'];
                   31142:             return $return;
                   31143:         }
                   31144: 
                   31145:         $return['php'] = $phpversion;
                   31146:         return $return;
                   31147:     }
                   31148: 
                   31149:     function listPackages($base, $channel = false)
                   31150:     {
                   31151:         $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
                   31152:         if (PEAR::isError($packagelist)) {
                   31153:             return $packagelist;
                   31154:         }
                   31155: 
                   31156:         if (!is_array($packagelist) || !isset($packagelist['p'])) {
                   31157:             return array();
                   31158:         }
                   31159: 
                   31160:         if (!is_array($packagelist['p'])) {
                   31161:             $packagelist['p'] = array($packagelist['p']);
                   31162:         }
                   31163: 
                   31164:         return $packagelist['p'];
                   31165:     }
                   31166: 
                   31167:     /**
                   31168:      * List all categories of a REST server
                   31169:      *
                   31170:      * @param string $base base URL of the server
                   31171:      * @return array of categorynames
                   31172:      */
                   31173:     function listCategories($base, $channel = false)
                   31174:     {
                   31175:         $categories = array();
                   31176: 
                   31177:         // c/categories.xml does not exist;
                   31178:         // check for every package its category manually
                   31179:         // This is SLOOOWWWW : ///
                   31180:         $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
                   31181:         if (PEAR::isError($packagelist)) {
                   31182:             return $packagelist;
                   31183:         }
                   31184: 
                   31185:         if (!is_array($packagelist) || !isset($packagelist['p'])) {
                   31186:             $ret = array();
                   31187:             return $ret;
                   31188:         }
                   31189: 
                   31190:         if (!is_array($packagelist['p'])) {
                   31191:             $packagelist['p'] = array($packagelist['p']);
                   31192:         }
                   31193: 
                   31194:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   31195:         foreach ($packagelist['p'] as $package) {
                   31196:                 $inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
                   31197:                 if (PEAR::isError($inf)) {
                   31198:                     PEAR::popErrorHandling();
                   31199:                     return $inf;
                   31200:                 }
                   31201:                 $cat = $inf['ca']['_content'];
                   31202:                 if (!isset($categories[$cat])) {
                   31203:                     $categories[$cat] = $inf['ca'];
                   31204:                 }
                   31205:         }
                   31206: 
                   31207:         return array_values($categories);
                   31208:     }
                   31209: 
                   31210:     /**
                   31211:      * List a category of a REST server
                   31212:      *
                   31213:      * @param string $base base URL of the server
                   31214:      * @param string $category name of the category
                   31215:      * @param boolean $info also download full package info
                   31216:      * @return array of packagenames
                   31217:      */
                   31218:     function listCategory($base, $category, $info = false, $channel = false)
                   31219:     {
                   31220:         // gives '404 Not Found' error when category doesn't exist
                   31221:         $packagelist = $this->_rest->retrieveData($base.'c/'.urlencode($category).'/packages.xml', false, false, $channel);
                   31222:         if (PEAR::isError($packagelist)) {
                   31223:             return $packagelist;
                   31224:         }
                   31225: 
                   31226:         if (!is_array($packagelist) || !isset($packagelist['p'])) {
                   31227:             return array();
                   31228:         }
                   31229: 
                   31230:         if (!is_array($packagelist['p']) ||
                   31231:             !isset($packagelist['p'][0])) { // only 1 pkg
                   31232:             $packagelist = array($packagelist['p']);
                   31233:         } else {
                   31234:             $packagelist = $packagelist['p'];
                   31235:         }
                   31236: 
                   31237:         if ($info == true) {
                   31238:             // get individual package info
                   31239:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   31240:             foreach ($packagelist as $i => $packageitem) {
                   31241:                 $url = sprintf('%s'.'r/%s/latest.txt',
                   31242:                         $base,
                   31243:                         strtolower($packageitem['_content']));
                   31244:                 $version = $this->_rest->retrieveData($url, false, false, $channel);
                   31245:                 if (PEAR::isError($version)) {
                   31246:                     break; // skipit
                   31247:                 }
                   31248:                 $url = sprintf('%s'.'r/%s/%s.xml',
                   31249:                         $base,
                   31250:                         strtolower($packageitem['_content']),
                   31251:                         $version);
                   31252:                 $info = $this->_rest->retrieveData($url, false, false, $channel);
                   31253:                 if (PEAR::isError($info)) {
                   31254:                     break; // skipit
                   31255:                 }
                   31256:                 $packagelist[$i]['info'] = $info;
                   31257:             }
                   31258:             PEAR::popErrorHandling();
                   31259:         }
                   31260: 
                   31261:         return $packagelist;
                   31262:     }
                   31263: 
                   31264: 
                   31265:     function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false)
                   31266:     {
                   31267:         $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
                   31268:         if (PEAR::isError($packagelist)) {
                   31269:             return $packagelist;
                   31270:         }
                   31271:         if ($this->_rest->config->get('verbose') > 0) {
                   31272:             $ui = &PEAR_Frontend::singleton();
                   31273:             $ui->log('Retrieving data...0%', true);
                   31274:         }
                   31275:         $ret = array();
                   31276:         if (!is_array($packagelist) || !isset($packagelist['p'])) {
                   31277:             return $ret;
                   31278:         }
                   31279:         if (!is_array($packagelist['p'])) {
                   31280:             $packagelist['p'] = array($packagelist['p']);
                   31281:         }
                   31282: 
                   31283:         // only search-packagename = quicksearch !
                   31284:         if ($searchpackage && (!$searchsummary || empty($searchpackage))) {
                   31285:             $newpackagelist = array();
                   31286:             foreach ($packagelist['p'] as $package) {
                   31287:                 if (!empty($searchpackage) && stristr($package, $searchpackage) !== false) {
                   31288:                     $newpackagelist[] = $package;
                   31289:                 }
                   31290:             }
                   31291:             $packagelist['p'] = $newpackagelist;
                   31292:         }
                   31293:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   31294:         $next = .1;
                   31295:         foreach ($packagelist['p'] as $progress => $package) {
                   31296:             if ($this->_rest->config->get('verbose') > 0) {
                   31297:                 if ($progress / count($packagelist['p']) >= $next) {
                   31298:                     if ($next == .5) {
                   31299:                         $ui->log('50%', false);
                   31300:                     } else {
                   31301:                         $ui->log('.', false);
                   31302:                     }
                   31303:                     $next += .1;
                   31304:                 }
                   31305:             }
                   31306: 
                   31307:             if ($basic) { // remote-list command
                   31308:                 if ($dostable) {
                   31309:                     $latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
                   31310:                         '/stable.txt', false, false, $channel);
                   31311:                 } else {
                   31312:                     $latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
                   31313:                         '/latest.txt', false, false, $channel);
                   31314:                 }
                   31315:                 if (PEAR::isError($latest)) {
                   31316:                     $latest = false;
                   31317:                 }
                   31318:                 $info = array('stable' => $latest);
                   31319:             } else { // list-all command
                   31320:                 $inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
                   31321:                 if (PEAR::isError($inf)) {
                   31322:                     PEAR::popErrorHandling();
                   31323:                     return $inf;
                   31324:                 }
                   31325:                 if ($searchpackage) {
                   31326:                     $found = (!empty($searchpackage) && stristr($package, $searchpackage) !== false);
                   31327:                     if (!$found && !(isset($searchsummary) && !empty($searchsummary)
                   31328:                         && (stristr($inf['s'], $searchsummary) !== false
                   31329:                             || stristr($inf['d'], $searchsummary) !== false)))
                   31330:                     {
                   31331:                         continue;
                   31332:                     };
                   31333:                 }
                   31334:                 $releases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
                   31335:                     '/allreleases.xml', false, false, $channel);
                   31336:                 if (PEAR::isError($releases)) {
                   31337:                     continue;
                   31338:                 }
                   31339:                 if (!isset($releases['r'][0])) {
                   31340:                     $releases['r'] = array($releases['r']);
                   31341:                 }
                   31342:                 unset($latest);
                   31343:                 unset($unstable);
                   31344:                 unset($stable);
                   31345:                 unset($state);
                   31346:                 foreach ($releases['r'] as $release) {
                   31347:                     if (!isset($latest)) {
                   31348:                         if ($dostable && $release['s'] == 'stable') {
                   31349:                             $latest = $release['v'];
                   31350:                             $state = 'stable';
                   31351:                         }
                   31352:                         if (!$dostable) {
                   31353:                             $latest = $release['v'];
                   31354:                             $state = $release['s'];
                   31355:                         }
                   31356:                     }
                   31357:                     if (!isset($stable) && $release['s'] == 'stable') {
                   31358:                         $stable = $release['v'];
                   31359:                         if (!isset($unstable)) {
                   31360:                             $unstable = $stable;
                   31361:                         }
                   31362:                     }
                   31363:                     if (!isset($unstable) && $release['s'] != 'stable') {
                   31364:                         $latest = $unstable = $release['v'];
                   31365:                         $state = $release['s'];
                   31366:                     }
                   31367:                     if (isset($latest) && !isset($state)) {
                   31368:                         $state = $release['s'];
                   31369:                     }
                   31370:                     if (isset($latest) && isset($stable) && isset($unstable)) {
                   31371:                         break;
                   31372:                     }
                   31373:                 }
                   31374:                 $deps = array();
                   31375:                 if (!isset($unstable)) {
                   31376:                     $unstable = false;
                   31377:                     $state = 'stable';
                   31378:                     if (isset($stable)) {
                   31379:                         $latest = $unstable = $stable;
                   31380:                     }
                   31381:                 } else {
                   31382:                     $latest = $unstable;
                   31383:                 }
                   31384:                 if (!isset($latest)) {
                   31385:                     $latest = false;
                   31386:                 }
                   31387:                 if ($latest) {
                   31388:                     $d = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' .
                   31389:                         $latest . '.txt', false, false, $channel);
                   31390:                     if (!PEAR::isError($d)) {
                   31391:                         $d = unserialize($d);
                   31392:                         if ($d) {
                   31393:                             if (isset($d['required'])) {
                   31394:                                 if (!class_exists('PEAR_PackageFile_v2')) {
                   31395:                                     require_once 'PEAR/PackageFile/v2.php';
                   31396:                                 }
                   31397:                                 if (!isset($pf)) {
                   31398:                                     $pf = new PEAR_PackageFile_v2;
                   31399:                                 }
                   31400:                                 $pf->setDeps($d);
                   31401:                                 $tdeps = $pf->getDeps();
                   31402:                             } else {
                   31403:                                 $tdeps = $d;
                   31404:                             }
                   31405:                             foreach ($tdeps as $dep) {
                   31406:                                 if ($dep['type'] !== 'pkg') {
                   31407:                                     continue;
                   31408:                                 }
                   31409:                                 $deps[] = $dep;
                   31410:                             }
                   31411:                         }
                   31412:                     }
                   31413:                 }
                   31414:                 if (!isset($stable)) {
                   31415:                     $stable = '-n/a-';
                   31416:                 }
                   31417:                 if (!$searchpackage) {
                   31418:                     $info = array('stable' => $latest, 'summary' => $inf['s'], 'description' =>
                   31419:                         $inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'],
                   31420:                         'unstable' => $unstable, 'state' => $state);
                   31421:                 } else {
                   31422:                     $info = array('stable' => $stable, 'summary' => $inf['s'], 'description' =>
                   31423:                         $inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'],
                   31424:                         'unstable' => $unstable, 'state' => $state);
                   31425:                 }
                   31426:             }
                   31427:             $ret[$package] = $info;
                   31428:         }
                   31429:         PEAR::popErrorHandling();
                   31430:         return $ret;
                   31431:     }
                   31432: 
                   31433:     function listLatestUpgrades($base, $pref_state, $installed, $channel, &$reg)
                   31434:     {
                   31435:         $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
                   31436:         if (PEAR::isError($packagelist)) {
                   31437:             return $packagelist;
                   31438:         }
                   31439: 
                   31440:         $ret = array();
                   31441:         if (!is_array($packagelist) || !isset($packagelist['p'])) {
                   31442:             return $ret;
                   31443:         }
                   31444: 
                   31445:         if (!is_array($packagelist['p'])) {
                   31446:             $packagelist['p'] = array($packagelist['p']);
                   31447:         }
                   31448: 
                   31449:         foreach ($packagelist['p'] as $package) {
                   31450:             if (!isset($installed[strtolower($package)])) {
                   31451:                 continue;
                   31452:             }
                   31453: 
                   31454:             $inst_version = $reg->packageInfo($package, 'version', $channel);
                   31455:             $inst_state   = $reg->packageInfo($package, 'release_state', $channel);
                   31456:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   31457:             $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
                   31458:                 '/allreleases.xml', false, false, $channel);
                   31459:             PEAR::popErrorHandling();
                   31460:             if (PEAR::isError($info)) {
                   31461:                 continue; // no remote releases
                   31462:             }
                   31463: 
                   31464:             if (!isset($info['r'])) {
                   31465:                 continue;
                   31466:             }
                   31467: 
                   31468:             $release = $found = false;
                   31469:             if (!is_array($info['r']) || !isset($info['r'][0])) {
                   31470:                 $info['r'] = array($info['r']);
                   31471:             }
                   31472: 
                   31473:             // $info['r'] is sorted by version number
                   31474:             usort($info['r'], array($this, '_sortReleasesByVersionNumber'));
                   31475:             foreach ($info['r'] as $release) {
                   31476:                 if ($inst_version && version_compare($release['v'], $inst_version, '<=')) {
                   31477:                     // not newer than the one installed
                   31478:                     break;
                   31479:                 }
                   31480: 
                   31481:                 // new version > installed version
                   31482:                 if (!$pref_state) {
                   31483:                     // every state is a good state
                   31484:                     $found = true;
                   31485:                     break;
                   31486:                 } else {
                   31487:                     $new_state = $release['s'];
                   31488:                     // if new state >= installed state: go
                   31489:                     if (in_array($new_state, $this->betterStates($inst_state, true))) {
                   31490:                         $found = true;
                   31491:                         break;
                   31492:                     } else {
                   31493:                         // only allow to lower the state of package,
                   31494:                         // if new state >= preferred state: go
                   31495:                         if (in_array($new_state, $this->betterStates($pref_state, true))) {
                   31496:                             $found = true;
                   31497:                             break;
                   31498:                         }
                   31499:                     }
                   31500:                 }
                   31501:             }
                   31502: 
                   31503:             if (!$found) {
                   31504:                 continue;
                   31505:             }
                   31506: 
                   31507:             $relinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' .
                   31508:                 $release['v'] . '.xml', false, false, $channel);
                   31509:             if (PEAR::isError($relinfo)) {
                   31510:                 return $relinfo;
                   31511:             }
                   31512: 
                   31513:             $ret[$package] = array(
                   31514:                 'version'  => $release['v'],
                   31515:                 'state'    => $release['s'],
                   31516:                 'filesize' => $relinfo['f'],
                   31517:             );
                   31518:         }
                   31519: 
                   31520:         return $ret;
                   31521:     }
                   31522: 
                   31523:     function packageInfo($base, $package, $channel = false)
                   31524:     {
                   31525:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   31526:         $pinfo = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
                   31527:         if (PEAR::isError($pinfo)) {
                   31528:             PEAR::popErrorHandling();
                   31529:             return PEAR::raiseError('Unknown package: "' . $package . '" in channel "' . $channel . '"' . "\n". 'Debug: ' .
                   31530:                 $pinfo->getMessage());
                   31531:         }
                   31532: 
                   31533:         $releases = array();
                   31534:         $allreleases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
                   31535:             '/allreleases.xml', false, false, $channel);
                   31536:         if (!PEAR::isError($allreleases)) {
                   31537:             if (!class_exists('PEAR_PackageFile_v2')) {
                   31538:                 require_once 'PEAR/PackageFile/v2.php';
                   31539:             }
                   31540: 
                   31541:             if (!is_array($allreleases['r']) || !isset($allreleases['r'][0])) {
                   31542:                 $allreleases['r'] = array($allreleases['r']);
                   31543:             }
                   31544: 
                   31545:             $pf = new PEAR_PackageFile_v2;
                   31546:             foreach ($allreleases['r'] as $release) {
                   31547:                 $ds = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' .
                   31548:                     $release['v'] . '.txt', false, false, $channel);
                   31549:                 if (PEAR::isError($ds)) {
                   31550:                     continue;
                   31551:                 }
                   31552: 
                   31553:                 if (!isset($latest)) {
                   31554:                     $latest = $release['v'];
                   31555:                 }
                   31556: 
                   31557:                 $pf->setDeps(unserialize($ds));
                   31558:                 $ds = $pf->getDeps();
                   31559:                 $info = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package)
                   31560:                     . '/' . $release['v'] . '.xml', false, false, $channel);
                   31561: 
                   31562:                 if (PEAR::isError($info)) {
                   31563:                     continue;
                   31564:                 }
                   31565: 
                   31566:                 $releases[$release['v']] = array(
                   31567:                     'doneby' => $info['m'],
                   31568:                     'license' => $info['l'],
                   31569:                     'summary' => $info['s'],
                   31570:                     'description' => $info['d'],
                   31571:                     'releasedate' => $info['da'],
                   31572:                     'releasenotes' => $info['n'],
                   31573:                     'state' => $release['s'],
                   31574:                     'deps' => $ds ? $ds : array(),
                   31575:                 );
                   31576:             }
                   31577:         } else {
                   31578:             $latest = '';
                   31579:         }
                   31580: 
                   31581:         PEAR::popErrorHandling();
                   31582:         if (isset($pinfo['dc']) && isset($pinfo['dp'])) {
                   31583:             if (is_array($pinfo['dp'])) {
                   31584:                 $deprecated = array('channel' => (string) $pinfo['dc'],
                   31585:                                     'package' => trim($pinfo['dp']['_content']));
                   31586:             } else {
                   31587:                 $deprecated = array('channel' => (string) $pinfo['dc'],
                   31588:                                     'package' => trim($pinfo['dp']));
                   31589:             }
                   31590:         } else {
                   31591:             $deprecated = false;
                   31592:         }
                   31593: 
                   31594:         if (!isset($latest)) {
                   31595:             $latest = '';
                   31596:         }
                   31597: 
                   31598:         return array(
                   31599:             'name' => $pinfo['n'],
                   31600:             'channel' => $pinfo['c'],
                   31601:             'category' => $pinfo['ca']['_content'],
                   31602:             'stable' => $latest,
                   31603:             'license' => $pinfo['l'],
                   31604:             'summary' => $pinfo['s'],
                   31605:             'description' => $pinfo['d'],
                   31606:             'releases' => $releases,
                   31607:             'deprecated' => $deprecated,
                   31608:             );
                   31609:     }
                   31610: 
                   31611:     /**
                   31612:      * Return an array containing all of the states that are more stable than
                   31613:      * or equal to the passed in state
                   31614:      *
                   31615:      * @param string Release state
                   31616:      * @param boolean Determines whether to include $state in the list
                   31617:      * @return false|array False if $state is not a valid release state
                   31618:      */
                   31619:     function betterStates($state, $include = false)
                   31620:     {
                   31621:         static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
                   31622:         $i = array_search($state, $states);
                   31623:         if ($i === false) {
                   31624:             return false;
                   31625:         }
                   31626: 
                   31627:         if ($include) {
                   31628:             $i--;
                   31629:         }
                   31630: 
                   31631:         return array_slice($states, $i + 1);
                   31632:     }
                   31633: 
                   31634:     /**
                   31635:      * Sort releases by version number
                   31636:      *
                   31637:      * @access private
                   31638:      */
                   31639:     function _sortReleasesByVersionNumber($a, $b)
                   31640:     {
                   31641:         if (version_compare($a['v'], $b['v'], '=')) {
                   31642:             return 0;
                   31643:         }
                   31644: 
                   31645:         if (version_compare($a['v'], $b['v'], '>')) {
                   31646:             return -1;
                   31647:         }
                   31648: 
                   31649:         if (version_compare($a['v'], $b['v'], '<')) {
                   31650:             return 1;
                   31651:         }
                   31652:     }
1.1.1.2 ! misho    31653: }PEAR-1.9.4/PEAR/REST/11.php0000644000076500000240000002605411605156614013501 0ustar  helgistaff<?php
1.1       misho    31654: /**
                   31655:  * PEAR_REST_11 - implement faster list-all/remote-list command
                   31656:  *
                   31657:  * PHP versions 4 and 5
                   31658:  *
                   31659:  * @category   pear
                   31660:  * @package    PEAR
                   31661:  * @author     Greg Beaver <cellog@php.net>
                   31662:  * @copyright  1997-2009 The Authors
                   31663:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   31664:  * @version    CVS: $Id: 11.php 313023 2011-07-06 19:17:11Z dufuz $
                   31665:  * @link       http://pear.php.net/package/PEAR
                   31666:  * @since      File available since Release 1.4.3
                   31667:  */
                   31668: 
                   31669: /**
                   31670:  * For downloading REST xml/txt files
                   31671:  */
                   31672: require_once 'PEAR/REST.php';
                   31673: 
                   31674: /**
                   31675:  * Implement REST 1.1
                   31676:  *
                   31677:  * @category   pear
                   31678:  * @package    PEAR
                   31679:  * @author     Greg Beaver <cellog@php.net>
                   31680:  * @copyright  1997-2009 The Authors
                   31681:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   31682:  * @version    Release: 1.9.4
                   31683:  * @link       http://pear.php.net/package/PEAR
                   31684:  * @since      Class available since Release 1.4.3
                   31685:  */
                   31686: class PEAR_REST_11
                   31687: {
                   31688:     /**
                   31689:      * @var PEAR_REST
                   31690:      */
                   31691:     var $_rest;
                   31692: 
                   31693:     function PEAR_REST_11($config, $options = array())
                   31694:     {
                   31695:         $this->_rest = &new PEAR_REST($config, $options);
                   31696:     }
                   31697: 
                   31698:     function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false)
                   31699:     {
                   31700:         $categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel);
                   31701:         if (PEAR::isError($categorylist)) {
                   31702:             return $categorylist;
                   31703:         }
                   31704: 
                   31705:         $ret = array();
                   31706:         if (!is_array($categorylist['c']) || !isset($categorylist['c'][0])) {
                   31707:             $categorylist['c'] = array($categorylist['c']);
                   31708:         }
                   31709: 
                   31710:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   31711: 
                   31712:         foreach ($categorylist['c'] as $progress => $category) {
                   31713:             $category = $category['_content'];
                   31714:             $packagesinfo = $this->_rest->retrieveData($base .
                   31715:                 'c/' . urlencode($category) . '/packagesinfo.xml', false, false, $channel);
                   31716: 
                   31717:             if (PEAR::isError($packagesinfo)) {
                   31718:                 continue;
                   31719:             }
                   31720: 
                   31721:             if (!is_array($packagesinfo) || !isset($packagesinfo['pi'])) {
                   31722:                 continue;
                   31723:             }
                   31724: 
                   31725:             if (!is_array($packagesinfo['pi']) || !isset($packagesinfo['pi'][0])) {
                   31726:                 $packagesinfo['pi'] = array($packagesinfo['pi']);
                   31727:             }
                   31728: 
                   31729:             foreach ($packagesinfo['pi'] as $packageinfo) {
                   31730:                 if (empty($packageinfo)) {
                   31731:                     continue;
                   31732:                 }
                   31733: 
                   31734:                 $info     = $packageinfo['p'];
                   31735:                 $package  = $info['n'];
                   31736:                 $releases = isset($packageinfo['a']) ? $packageinfo['a'] : false;
                   31737:                 unset($latest);
                   31738:                 unset($unstable);
                   31739:                 unset($stable);
                   31740:                 unset($state);
                   31741: 
                   31742:                 if ($releases) {
                   31743:                     if (!isset($releases['r'][0])) {
                   31744:                         $releases['r'] = array($releases['r']);
                   31745:                     }
                   31746: 
                   31747:                     foreach ($releases['r'] as $release) {
                   31748:                         if (!isset($latest)) {
                   31749:                             if ($dostable && $release['s'] == 'stable') {
                   31750:                                 $latest = $release['v'];
                   31751:                                 $state = 'stable';
                   31752:                             }
                   31753:                             if (!$dostable) {
                   31754:                                 $latest = $release['v'];
                   31755:                                 $state = $release['s'];
                   31756:                             }
                   31757:                         }
                   31758: 
                   31759:                         if (!isset($stable) && $release['s'] == 'stable') {
                   31760:                             $stable = $release['v'];
                   31761:                             if (!isset($unstable)) {
                   31762:                                 $unstable = $stable;
                   31763:                             }
                   31764:                         }
                   31765: 
                   31766:                         if (!isset($unstable) && $release['s'] != 'stable') {
                   31767:                             $unstable = $release['v'];
                   31768:                             $state = $release['s'];
                   31769:                         }
                   31770: 
                   31771:                         if (isset($latest) && !isset($state)) {
                   31772:                             $state = $release['s'];
                   31773:                         }
                   31774: 
                   31775:                         if (isset($latest) && isset($stable) && isset($unstable)) {
                   31776:                             break;
                   31777:                         }
                   31778:                     }
                   31779:                 }
                   31780: 
                   31781:                 if ($basic) { // remote-list command
                   31782:                     if (!isset($latest)) {
                   31783:                         $latest = false;
                   31784:                     }
                   31785: 
                   31786:                     if ($dostable) {
                   31787:                         // $state is not set if there are no releases
                   31788:                         if (isset($state) && $state == 'stable') {
                   31789:                             $ret[$package] = array('stable' => $latest);
                   31790:                         } else {
                   31791:                             $ret[$package] = array('stable' => '-n/a-');
                   31792:                         }
                   31793:                     } else {
                   31794:                         $ret[$package] = array('stable' => $latest);
                   31795:                     }
                   31796: 
                   31797:                     continue;
                   31798:                 }
                   31799: 
                   31800:                 // list-all command
                   31801:                 if (!isset($unstable)) {
                   31802:                     $unstable = false;
                   31803:                     $state = 'stable';
                   31804:                     if (isset($stable)) {
                   31805:                         $latest = $unstable = $stable;
                   31806:                     }
                   31807:                 } else {
                   31808:                     $latest = $unstable;
                   31809:                 }
                   31810: 
                   31811:                 if (!isset($latest)) {
                   31812:                     $latest = false;
                   31813:                 }
                   31814: 
                   31815:                 $deps = array();
                   31816:                 if ($latest && isset($packageinfo['deps'])) {
                   31817:                     if (!is_array($packageinfo['deps']) ||
                   31818:                           !isset($packageinfo['deps'][0])
                   31819:                     ) {
                   31820:                         $packageinfo['deps'] = array($packageinfo['deps']);
                   31821:                     }
                   31822: 
                   31823:                     $d = false;
                   31824:                     foreach ($packageinfo['deps'] as $dep) {
                   31825:                         if ($dep['v'] == $latest) {
                   31826:                             $d = unserialize($dep['d']);
                   31827:                         }
                   31828:                     }
                   31829: 
                   31830:                     if ($d) {
                   31831:                         if (isset($d['required'])) {
                   31832:                             if (!class_exists('PEAR_PackageFile_v2')) {
                   31833:                                 require_once 'PEAR/PackageFile/v2.php';
                   31834:                             }
                   31835: 
                   31836:                             if (!isset($pf)) {
                   31837:                                 $pf = new PEAR_PackageFile_v2;
                   31838:                             }
                   31839: 
                   31840:                             $pf->setDeps($d);
                   31841:                             $tdeps = $pf->getDeps();
                   31842:                         } else {
                   31843:                             $tdeps = $d;
                   31844:                         }
                   31845: 
                   31846:                         foreach ($tdeps as $dep) {
                   31847:                             if ($dep['type'] !== 'pkg') {
                   31848:                                 continue;
                   31849:                             }
                   31850: 
                   31851:                             $deps[] = $dep;
                   31852:                         }
                   31853:                     }
                   31854:                 }
                   31855: 
                   31856:                 $info = array(
                   31857:                     'stable'      => $latest,
                   31858:                     'summary'     => $info['s'],
                   31859:                     'description' => $info['d'],
                   31860:                     'deps'        => $deps,
                   31861:                     'category'    => $info['ca']['_content'],
                   31862:                     'unstable'    => $unstable,
                   31863:                     'state'       => $state
                   31864:                 );
                   31865:                 $ret[$package] = $info;
                   31866:             }
                   31867:         }
                   31868: 
                   31869:         PEAR::popErrorHandling();
                   31870:         return $ret;
                   31871:     }
                   31872: 
                   31873:     /**
                   31874:      * List all categories of a REST server
                   31875:      *
                   31876:      * @param string $base base URL of the server
                   31877:      * @return array of categorynames
                   31878:      */
                   31879:     function listCategories($base, $channel = false)
                   31880:     {
                   31881:         $categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel);
                   31882:         if (PEAR::isError($categorylist)) {
                   31883:             return $categorylist;
                   31884:         }
                   31885: 
                   31886:         if (!is_array($categorylist) || !isset($categorylist['c'])) {
                   31887:             return array();
                   31888:         }
                   31889: 
                   31890:         if (isset($categorylist['c']['_content'])) {
                   31891:             // only 1 category
                   31892:             $categorylist['c'] = array($categorylist['c']);
                   31893:         }
                   31894: 
                   31895:         return $categorylist['c'];
                   31896:     }
                   31897: 
                   31898:     /**
                   31899:      * List packages in a category of a REST server
                   31900:      *
                   31901:      * @param string $base base URL of the server
                   31902:      * @param string $category name of the category
                   31903:      * @param boolean $info also download full package info
                   31904:      * @return array of packagenames
                   31905:      */
                   31906:     function listCategory($base, $category, $info = false, $channel = false)
                   31907:     {
                   31908:         if ($info == false) {
                   31909:             $url = '%s'.'c/%s/packages.xml';
                   31910:         } else {
                   31911:             $url = '%s'.'c/%s/packagesinfo.xml';
                   31912:         }
                   31913:         $url = sprintf($url,
                   31914:                     $base,
                   31915:                     urlencode($category));
                   31916: 
                   31917:         // gives '404 Not Found' error when category doesn't exist
                   31918:         $packagelist = $this->_rest->retrieveData($url, false, false, $channel);
                   31919:         if (PEAR::isError($packagelist)) {
                   31920:             return $packagelist;
                   31921:         }
                   31922:         if (!is_array($packagelist)) {
                   31923:             return array();
                   31924:         }
                   31925: 
                   31926:         if ($info == false) {
                   31927:             if (!isset($packagelist['p'])) {
                   31928:                 return array();
                   31929:             }
                   31930:             if (!is_array($packagelist['p']) ||
                   31931:                 !isset($packagelist['p'][0])) { // only 1 pkg
                   31932:                 $packagelist = array($packagelist['p']);
                   31933:             } else {
                   31934:                 $packagelist = $packagelist['p'];
                   31935:             }
                   31936:             return $packagelist;
                   31937:         }
                   31938: 
                   31939:         // info == true
                   31940:         if (!isset($packagelist['pi'])) {
                   31941:             return array();
                   31942:         }
                   31943: 
                   31944:         if (!is_array($packagelist['pi']) ||
                   31945:             !isset($packagelist['pi'][0])) { // only 1 pkg
                   31946:             $packagelist_pre = array($packagelist['pi']);
                   31947:         } else {
                   31948:             $packagelist_pre = $packagelist['pi'];
                   31949:         }
                   31950: 
                   31951:         $packagelist = array();
                   31952:         foreach ($packagelist_pre as $i => $item) {
                   31953:             // compatibility with r/<latest.txt>.xml
                   31954:             if (isset($item['a']['r'][0])) {
                   31955:                 // multiple releases
                   31956:                 $item['p']['v'] = $item['a']['r'][0]['v'];
                   31957:                 $item['p']['st'] = $item['a']['r'][0]['s'];
                   31958:             } elseif (isset($item['a'])) {
                   31959:                 // first and only release
                   31960:                 $item['p']['v'] = $item['a']['r']['v'];
                   31961:                 $item['p']['st'] = $item['a']['r']['s'];
                   31962:             }
                   31963: 
                   31964:             $packagelist[$i] = array('attribs' => $item['p']['r'],
                   31965:                                      '_content' => $item['p']['n'],
                   31966:                                      'info' => $item['p']);
                   31967:         }
                   31968: 
                   31969:         return $packagelist;
                   31970:     }
                   31971: 
                   31972:     /**
                   31973:      * Return an array containing all of the states that are more stable than
                   31974:      * or equal to the passed in state
                   31975:      *
                   31976:      * @param string Release state
                   31977:      * @param boolean Determines whether to include $state in the list
                   31978:      * @return false|array False if $state is not a valid release state
                   31979:      */
                   31980:     function betterStates($state, $include = false)
                   31981:     {
                   31982:         static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
                   31983:         $i = array_search($state, $states);
                   31984:         if ($i === false) {
                   31985:             return false;
                   31986:         }
                   31987:         if ($include) {
                   31988:             $i--;
                   31989:         }
                   31990:         return array_slice($states, $i + 1);
                   31991:     }
                   31992: }
1.1.1.2 ! misho    31993: ?>PEAR-1.9.4/PEAR/REST/13.php0000644000076500000240000002654411605156614013507 0ustar  helgistaff<?php
1.1       misho    31994: /**
                   31995:  * PEAR_REST_13
                   31996:  *
                   31997:  * PHP versions 4 and 5
                   31998:  *
                   31999:  * @category   pear
                   32000:  * @package    PEAR
                   32001:  * @author     Greg Beaver <cellog@php.net>
                   32002:  * @copyright  1997-2009 The Authors
                   32003:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32004:  * @version    CVS: $Id: 13.php 313023 2011-07-06 19:17:11Z dufuz $
                   32005:  * @link       http://pear.php.net/package/PEAR
                   32006:  * @since      File available since Release 1.4.0a12
                   32007:  */
                   32008: 
                   32009: /**
                   32010:  * For downloading REST xml/txt files
                   32011:  */
                   32012: require_once 'PEAR/REST.php';
                   32013: require_once 'PEAR/REST/10.php';
                   32014: 
                   32015: /**
                   32016:  * Implement REST 1.3
                   32017:  *
                   32018:  * @category   pear
                   32019:  * @package    PEAR
                   32020:  * @author     Greg Beaver <cellog@php.net>
                   32021:  * @copyright  1997-2009 The Authors
                   32022:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32023:  * @version    Release: 1.9.4
                   32024:  * @link       http://pear.php.net/package/PEAR
                   32025:  * @since      Class available since Release 1.4.0a12
                   32026:  */
                   32027: class PEAR_REST_13 extends PEAR_REST_10
                   32028: {
                   32029:     /**
                   32030:      * Retrieve information about a remote package to be downloaded from a REST server
                   32031:      *
                   32032:      * This is smart enough to resolve the minimum PHP version dependency prior to download
                   32033:      * @param string $base The uri to prepend to all REST calls
                   32034:      * @param array $packageinfo an array of format:
                   32035:      * <pre>
                   32036:      *  array(
                   32037:      *   'package' => 'packagename',
                   32038:      *   'channel' => 'channelname',
                   32039:      *  ['state' => 'alpha' (or valid state),]
                   32040:      *  -or-
                   32041:      *  ['version' => '1.whatever']
                   32042:      * </pre>
                   32043:      * @param string $prefstate Current preferred_state config variable value
                   32044:      * @param bool $installed the installed version of this package to compare against
                   32045:      * @return array|false|PEAR_Error see {@link _returnDownloadURL()}
                   32046:      */
                   32047:     function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false)
                   32048:     {
                   32049:         $states = $this->betterStates($prefstate, true);
                   32050:         if (!$states) {
                   32051:             return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
                   32052:         }
                   32053: 
                   32054:         $channel  = $packageinfo['channel'];
                   32055:         $package  = $packageinfo['package'];
                   32056:         $state    = isset($packageinfo['state'])   ? $packageinfo['state']   : null;
                   32057:         $version  = isset($packageinfo['version']) ? $packageinfo['version'] : null;
                   32058:         $restFile = $base . 'r/' . strtolower($package) . '/allreleases2.xml';
                   32059: 
                   32060:         $info = $this->_rest->retrieveData($restFile, false, false, $channel);
                   32061:         if (PEAR::isError($info)) {
                   32062:             return PEAR::raiseError('No releases available for package "' .
                   32063:                 $channel . '/' . $package . '"');
                   32064:         }
                   32065: 
                   32066:         if (!isset($info['r'])) {
                   32067:             return false;
                   32068:         }
                   32069: 
                   32070:         $release = $found = false;
                   32071:         if (!is_array($info['r']) || !isset($info['r'][0])) {
                   32072:             $info['r'] = array($info['r']);
                   32073:         }
                   32074: 
                   32075:         $skippedphp = false;
                   32076:         foreach ($info['r'] as $release) {
                   32077:             if (!isset($this->_rest->_options['force']) && ($installed &&
                   32078:                   version_compare($release['v'], $installed, '<'))) {
                   32079:                 continue;
                   32080:             }
                   32081: 
                   32082:             if (isset($state)) {
                   32083:                 // try our preferred state first
                   32084:                 if ($release['s'] == $state) {
                   32085:                     if (!isset($version) && version_compare($release['m'], phpversion(), '>')) {
                   32086:                         // skip releases that require a PHP version newer than our PHP version
                   32087:                         $skippedphp = $release;
                   32088:                         continue;
                   32089:                     }
                   32090:                     $found = true;
                   32091:                     break;
                   32092:                 }
                   32093: 
                   32094:                 // see if there is something newer and more stable
                   32095:                 // bug #7221
                   32096:                 if (in_array($release['s'], $this->betterStates($state), true)) {
                   32097:                     if (!isset($version) && version_compare($release['m'], phpversion(), '>')) {
                   32098:                         // skip releases that require a PHP version newer than our PHP version
                   32099:                         $skippedphp = $release;
                   32100:                         continue;
                   32101:                     }
                   32102:                     $found = true;
                   32103:                     break;
                   32104:                 }
                   32105:             } elseif (isset($version)) {
                   32106:                 if ($release['v'] == $version) {
                   32107:                     if (!isset($this->_rest->_options['force']) &&
                   32108:                           !isset($version) &&
                   32109:                           version_compare($release['m'], phpversion(), '>')) {
                   32110:                         // skip releases that require a PHP version newer than our PHP version
                   32111:                         $skippedphp = $release;
                   32112:                         continue;
                   32113:                     }
                   32114:                     $found = true;
                   32115:                     break;
                   32116:                 }
                   32117:             } else {
                   32118:                 if (in_array($release['s'], $states)) {
                   32119:                     if (version_compare($release['m'], phpversion(), '>')) {
                   32120:                         // skip releases that require a PHP version newer than our PHP version
                   32121:                         $skippedphp = $release;
                   32122:                         continue;
                   32123:                     }
                   32124:                     $found = true;
                   32125:                     break;
                   32126:                 }
                   32127:             }
                   32128:         }
                   32129: 
                   32130:         if (!$found && $skippedphp) {
                   32131:             $found = null;
                   32132:         }
                   32133: 
                   32134:         return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel);
                   32135:     }
                   32136: 
                   32137:     function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage,
                   32138:                                $prefstate = 'stable', $installed = false, $channel = false)
                   32139:     {
                   32140:         $states = $this->betterStates($prefstate, true);
                   32141:         if (!$states) {
                   32142:             return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
                   32143:         }
                   32144: 
                   32145:         $channel  = $dependency['channel'];
                   32146:         $package  = $dependency['name'];
                   32147:         $state    = isset($dependency['state'])   ? $dependency['state']   : null;
                   32148:         $version  = isset($dependency['version']) ? $dependency['version'] : null;
                   32149:         $restFile = $base . 'r/' . strtolower($package) .'/allreleases2.xml';
                   32150: 
                   32151:         $info = $this->_rest->retrieveData($restFile, false, false, $channel);
                   32152:         if (PEAR::isError($info)) {
                   32153:             return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package']
                   32154:                 . '" dependency "' . $channel . '/' . $package . '" has no releases');
                   32155:         }
                   32156: 
                   32157:         if (!is_array($info) || !isset($info['r'])) {
                   32158:             return false;
                   32159:         }
                   32160: 
                   32161:         $exclude = array();
                   32162:         $min = $max = $recommended = false;
                   32163:         if ($xsdversion == '1.0') {
                   32164:             $pinfo['package'] = $dependency['name'];
                   32165:             $pinfo['channel'] = 'pear.php.net'; // this is always true - don't change this
                   32166:             switch ($dependency['rel']) {
                   32167:                 case 'ge' :
                   32168:                     $min = $dependency['version'];
                   32169:                 break;
                   32170:                 case 'gt' :
                   32171:                     $min = $dependency['version'];
                   32172:                     $exclude = array($dependency['version']);
                   32173:                 break;
                   32174:                 case 'eq' :
                   32175:                     $recommended = $dependency['version'];
                   32176:                 break;
                   32177:                 case 'lt' :
                   32178:                     $max = $dependency['version'];
                   32179:                     $exclude = array($dependency['version']);
                   32180:                 break;
                   32181:                 case 'le' :
                   32182:                     $max = $dependency['version'];
                   32183:                 break;
                   32184:                 case 'ne' :
                   32185:                     $exclude = array($dependency['version']);
                   32186:                 break;
                   32187:             }
                   32188:         } else {
                   32189:             $pinfo['package'] = $dependency['name'];
                   32190:             $min = isset($dependency['min']) ? $dependency['min'] : false;
                   32191:             $max = isset($dependency['max']) ? $dependency['max'] : false;
                   32192:             $recommended = isset($dependency['recommended']) ?
                   32193:                 $dependency['recommended'] : false;
                   32194:             if (isset($dependency['exclude'])) {
                   32195:                 if (!isset($dependency['exclude'][0])) {
                   32196:                     $exclude = array($dependency['exclude']);
                   32197:                 }
                   32198:             }
                   32199:         }
                   32200: 
                   32201:         $skippedphp = $found = $release = false;
                   32202:         if (!is_array($info['r']) || !isset($info['r'][0])) {
                   32203:             $info['r'] = array($info['r']);
                   32204:         }
                   32205: 
                   32206:         foreach ($info['r'] as $release) {
                   32207:             if (!isset($this->_rest->_options['force']) && ($installed &&
                   32208:                   version_compare($release['v'], $installed, '<'))) {
                   32209:                 continue;
                   32210:             }
                   32211: 
                   32212:             if (in_array($release['v'], $exclude)) { // skip excluded versions
                   32213:                 continue;
                   32214:             }
                   32215: 
                   32216:             // allow newer releases to say "I'm OK with the dependent package"
                   32217:             if ($xsdversion == '2.0' && isset($release['co'])) {
                   32218:                 if (!is_array($release['co']) || !isset($release['co'][0])) {
                   32219:                     $release['co'] = array($release['co']);
                   32220:                 }
                   32221: 
                   32222:                 foreach ($release['co'] as $entry) {
                   32223:                     if (isset($entry['x']) && !is_array($entry['x'])) {
                   32224:                         $entry['x'] = array($entry['x']);
                   32225:                     } elseif (!isset($entry['x'])) {
                   32226:                         $entry['x'] = array();
                   32227:                     }
                   32228: 
                   32229:                     if ($entry['c'] == $deppackage['channel'] &&
                   32230:                           strtolower($entry['p']) == strtolower($deppackage['package']) &&
                   32231:                           version_compare($deppackage['version'], $entry['min'], '>=') &&
                   32232:                           version_compare($deppackage['version'], $entry['max'], '<=') &&
                   32233:                           !in_array($release['v'], $entry['x'])) {
                   32234:                         if (version_compare($release['m'], phpversion(), '>')) {
                   32235:                             // skip dependency releases that require a PHP version
                   32236:                             // newer than our PHP version
                   32237:                             $skippedphp = $release;
                   32238:                             continue;
                   32239:                         }
                   32240: 
                   32241:                         $recommended = $release['v'];
                   32242:                         break;
                   32243:                     }
                   32244:                 }
                   32245:             }
                   32246: 
                   32247:             if ($recommended) {
                   32248:                 if ($release['v'] != $recommended) { // if we want a specific
                   32249:                     // version, then skip all others
                   32250:                     continue;
                   32251:                 }
                   32252: 
                   32253:                 if (!in_array($release['s'], $states)) {
                   32254:                     // the stability is too low, but we must return the
                   32255:                     // recommended version if possible
                   32256:                     return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel);
                   32257:                 }
                   32258:             }
                   32259: 
                   32260:             if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions
                   32261:                 continue;
                   32262:             }
                   32263: 
                   32264:             if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions
                   32265:                 continue;
                   32266:             }
                   32267: 
                   32268:             if ($installed && version_compare($release['v'], $installed, '<')) {
                   32269:                 continue;
                   32270:             }
                   32271: 
                   32272:             if (in_array($release['s'], $states)) { // if in the preferred state...
                   32273:                 if (version_compare($release['m'], phpversion(), '>')) {
                   32274:                     // skip dependency releases that require a PHP version
                   32275:                     // newer than our PHP version
                   32276:                     $skippedphp = $release;
                   32277:                     continue;
                   32278:                 }
                   32279: 
                   32280:                 $found = true; // ... then use it
                   32281:                 break;
                   32282:             }
                   32283:         }
                   32284: 
                   32285:         if (!$found && $skippedphp) {
                   32286:             $found = null;
                   32287:         }
                   32288: 
                   32289:         return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel);
                   32290:     }
1.1.1.2 ! misho    32291: }PEAR-1.9.4/PEAR/Task/Postinstallscript/rw.php0000644000076500000240000001331111605156614017566 0ustar  helgistaff<?php
1.1       misho    32292: /**
                   32293:  * <tasks:postinstallscript> - read/write version
                   32294:  *
                   32295:  * PHP versions 4 and 5
                   32296:  *
                   32297:  * @category   pear
                   32298:  * @package    PEAR
                   32299:  * @author     Greg Beaver <cellog@php.net>
                   32300:  * @copyright  1997-2009 The Authors
                   32301:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32302:  * @version    CVS: $Id: rw.php 313023 2011-07-06 19:17:11Z dufuz $
                   32303:  * @link       http://pear.php.net/package/PEAR
                   32304:  * @since      File available since Release 1.4.0a10
                   32305:  */
                   32306: /**
                   32307:  * Base class
                   32308:  */
                   32309: require_once 'PEAR/Task/Postinstallscript.php';
                   32310: /**
                   32311:  * Abstracts the postinstallscript file task xml.
                   32312:  * @category   pear
                   32313:  * @package    PEAR
                   32314:  * @author     Greg Beaver <cellog@php.net>
                   32315:  * @copyright  1997-2009 The Authors
                   32316:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32317:  * @version    Release: 1.9.4
                   32318:  * @link       http://pear.php.net/package/PEAR
                   32319:  * @since      Class available since Release 1.4.0a10
                   32320:  */
                   32321: class PEAR_Task_Postinstallscript_rw extends PEAR_Task_Postinstallscript
                   32322: {
                   32323:     /**
                   32324:      * parent package file object
                   32325:      *
                   32326:      * @var PEAR_PackageFile_v2_rw
                   32327:      */
                   32328:     var $_pkg;
                   32329:     /**
                   32330:      * Enter description here...
                   32331:      *
                   32332:      * @param PEAR_PackageFile_v2_rw $pkg
                   32333:      * @param PEAR_Config $config
                   32334:      * @param PEAR_Frontend $logger
                   32335:      * @param array $fileXml
                   32336:      * @return PEAR_Task_Postinstallscript_rw
                   32337:      */
                   32338:     function PEAR_Task_Postinstallscript_rw(&$pkg, &$config, &$logger, $fileXml)
                   32339:     {
                   32340:         parent::PEAR_Task_Common($config, $logger, PEAR_TASK_PACKAGE);
                   32341:         $this->_contents = $fileXml;
                   32342:         $this->_pkg = &$pkg;
                   32343:         $this->_params = array();
                   32344:     }
                   32345: 
                   32346:     function validate()
                   32347:     {
                   32348:         return $this->validateXml($this->_pkg, $this->_params, $this->config, $this->_contents);
                   32349:     }
                   32350: 
                   32351:     function getName()
                   32352:     {
                   32353:         return 'postinstallscript';
                   32354:     }
                   32355: 
                   32356:     /**
                   32357:      * add a simple <paramgroup> to the post-install script
                   32358:      *
                   32359:      * Order is significant, so call this method in the same
                   32360:      * sequence the users should see the paramgroups.  The $params
                   32361:      * parameter should either be the result of a call to {@link getParam()}
                   32362:      * or an array of calls to getParam().
                   32363:      *
                   32364:      * Use {@link addConditionTypeGroup()} to add a <paramgroup> containing
                   32365:      * a <conditiontype> tag
                   32366:      * @param string $id <paramgroup> id as seen by the script
                   32367:      * @param array|false $params array of getParam() calls, or false for no params
                   32368:      * @param string|false $instructions
                   32369:      */
                   32370:     function addParamGroup($id, $params = false, $instructions = false)
                   32371:     {
                   32372:         if ($params && isset($params[0]) && !isset($params[1])) {
                   32373:             $params = $params[0];
                   32374:         }
                   32375:         $stuff =
                   32376:             array(
                   32377:                 $this->_pkg->getTasksNs() . ':id' => $id,
                   32378:             );
                   32379:         if ($instructions) {
                   32380:             $stuff[$this->_pkg->getTasksNs() . ':instructions'] = $instructions;
                   32381:         }
                   32382:         if ($params) {
                   32383:             $stuff[$this->_pkg->getTasksNs() . ':param'] = $params;
                   32384:         }
                   32385:         $this->_params[$this->_pkg->getTasksNs() . ':paramgroup'][] = $stuff;
                   32386:     }
                   32387: 
                   32388:     /**
                   32389:      * add a complex <paramgroup> to the post-install script with conditions
                   32390:      *
                   32391:      * This inserts a <paramgroup> with
                   32392:      *
                   32393:      * Order is significant, so call this method in the same
                   32394:      * sequence the users should see the paramgroups.  The $params
                   32395:      * parameter should either be the result of a call to {@link getParam()}
                   32396:      * or an array of calls to getParam().
                   32397:      *
                   32398:      * Use {@link addParamGroup()} to add a simple <paramgroup>
                   32399:      *
                   32400:      * @param string $id <paramgroup> id as seen by the script
                   32401:      * @param string $oldgroup <paramgroup> id of the section referenced by
                   32402:      *                         <conditiontype>
                   32403:      * @param string $param name of the <param> from the older section referenced
                   32404:      *                      by <contitiontype>
                   32405:      * @param string $value value to match of the parameter
                   32406:      * @param string $conditiontype one of '=', '!=', 'preg_match'
                   32407:      * @param array|false $params array of getParam() calls, or false for no params
                   32408:      * @param string|false $instructions
                   32409:      */
                   32410:     function addConditionTypeGroup($id, $oldgroup, $param, $value, $conditiontype = '=',
                   32411:                                    $params = false, $instructions = false)
                   32412:     {
                   32413:         if ($params && isset($params[0]) && !isset($params[1])) {
                   32414:             $params = $params[0];
                   32415:         }
                   32416:         $stuff = array(
                   32417:             $this->_pkg->getTasksNs() . ':id' => $id,
                   32418:         );
                   32419:         if ($instructions) {
                   32420:             $stuff[$this->_pkg->getTasksNs() . ':instructions'] = $instructions;
                   32421:         }
                   32422:         $stuff[$this->_pkg->getTasksNs() . ':name'] = $oldgroup . '::' . $param;
                   32423:         $stuff[$this->_pkg->getTasksNs() . ':conditiontype'] = $conditiontype;
                   32424:         $stuff[$this->_pkg->getTasksNs() . ':value'] = $value;
                   32425:         if ($params) {
                   32426:             $stuff[$this->_pkg->getTasksNs() . ':param'] = $params;
                   32427:         }
                   32428:         $this->_params[$this->_pkg->getTasksNs() . ':paramgroup'][] = $stuff;
                   32429:     }
                   32430: 
                   32431:     function getXml()
                   32432:     {
                   32433:         return $this->_params;
                   32434:     }
                   32435: 
                   32436:     /**
                   32437:      * Use to set up a param tag for use in creating a paramgroup
                   32438:      * @static
                   32439:      */
                   32440:     function getParam($name, $prompt, $type = 'string', $default = null)
                   32441:     {
                   32442:         if ($default !== null) {
                   32443:             return
                   32444:             array(
                   32445:                 $this->_pkg->getTasksNs() . ':name' => $name,
                   32446:                 $this->_pkg->getTasksNs() . ':prompt' => $prompt,
                   32447:                 $this->_pkg->getTasksNs() . ':type' => $type,
                   32448:                 $this->_pkg->getTasksNs() . ':default' => $default
                   32449:             );
                   32450:         }
                   32451:         return
                   32452:             array(
                   32453:                 $this->_pkg->getTasksNs() . ':name' => $name,
                   32454:                 $this->_pkg->getTasksNs() . ':prompt' => $prompt,
                   32455:                 $this->_pkg->getTasksNs() . ':type' => $type,
                   32456:             );
                   32457:     }
                   32458: }
1.1.1.2 ! misho    32459: ?>PEAR-1.9.4/PEAR/Task/Replace/rw.php0000644000076500000240000000311511605156614015401 0ustar  helgistaff<?php
1.1       misho    32460: /**
                   32461:  * <tasks:replace> - read/write version
                   32462:  *
                   32463:  * PHP versions 4 and 5
                   32464:  *
                   32465:  * @category   pear
                   32466:  * @package    PEAR
                   32467:  * @author     Greg Beaver <cellog@php.net>
                   32468:  * @copyright  1997-2009 The Authors
                   32469:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32470:  * @version    CVS: $Id: rw.php 313023 2011-07-06 19:17:11Z dufuz $
                   32471:  * @link       http://pear.php.net/package/PEAR
                   32472:  * @since      File available since Release 1.4.0a10
                   32473:  */
                   32474: /**
                   32475:  * Base class
                   32476:  */
                   32477: require_once 'PEAR/Task/Replace.php';
                   32478: /**
                   32479:  * Abstracts the replace task xml.
                   32480:  * @category   pear
                   32481:  * @package    PEAR
                   32482:  * @author     Greg Beaver <cellog@php.net>
                   32483:  * @copyright  1997-2009 The Authors
                   32484:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32485:  * @version    Release: 1.9.4
                   32486:  * @link       http://pear.php.net/package/PEAR
                   32487:  * @since      Class available since Release 1.4.0a10
                   32488:  */
                   32489: class PEAR_Task_Replace_rw extends PEAR_Task_Replace
                   32490: {
                   32491:     function PEAR_Task_Replace_rw(&$pkg, &$config, &$logger, $fileXml)
                   32492:     {
                   32493:         parent::PEAR_Task_Common($config, $logger, PEAR_TASK_PACKAGE);
                   32494:         $this->_contents = $fileXml;
                   32495:         $this->_pkg = &$pkg;
                   32496:         $this->_params = array();
                   32497:     }
                   32498: 
                   32499:     function validate()
                   32500:     {
                   32501:         return $this->validateXml($this->_pkg, $this->_params, $this->config, $this->_contents);
                   32502:     }
                   32503: 
                   32504:     function setInfo($from, $to, $type)
                   32505:     {
                   32506:         $this->_params = array('attribs' => array('from' => $from, 'to' => $to, 'type' => $type));
                   32507:     }
                   32508: 
                   32509:     function getName()
                   32510:     {
                   32511:         return 'replace';
                   32512:     }
                   32513: 
                   32514:     function getXml()
                   32515:     {
                   32516:         return $this->_params;
                   32517:     }
                   32518: }
1.1.1.2 ! misho    32519: ?>PEAR-1.9.4/PEAR/Task/Unixeol/rw.php0000644000076500000240000000253511605156614015456 0ustar  helgistaff<?php
1.1       misho    32520: /**
                   32521:  * <tasks:unixeol> - read/write version
                   32522:  *
                   32523:  * PHP versions 4 and 5
                   32524:  *
                   32525:  * @category   pear
                   32526:  * @package    PEAR
                   32527:  * @author     Greg Beaver <cellog@php.net>
                   32528:  * @copyright  1997-2009 The Authors
                   32529:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32530:  * @version    CVS: $Id: rw.php 313023 2011-07-06 19:17:11Z dufuz $
                   32531:  * @link       http://pear.php.net/package/PEAR
                   32532:  * @since      File available since Release 1.4.0a10
                   32533:  */
                   32534: /**
                   32535:  * Base class
                   32536:  */
                   32537: require_once 'PEAR/Task/Unixeol.php';
                   32538: /**
                   32539:  * Abstracts the unixeol task xml.
                   32540:  * @category   pear
                   32541:  * @package    PEAR
                   32542:  * @author     Greg Beaver <cellog@php.net>
                   32543:  * @copyright  1997-2009 The Authors
                   32544:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32545:  * @version    Release: 1.9.4
                   32546:  * @link       http://pear.php.net/package/PEAR
                   32547:  * @since      Class available since Release 1.4.0a10
                   32548:  */
                   32549: class PEAR_Task_Unixeol_rw extends PEAR_Task_Unixeol
                   32550: {
                   32551:     function PEAR_Task_Unixeol_rw(&$pkg, &$config, &$logger, $fileXml)
                   32552:     {
                   32553:         parent::PEAR_Task_Common($config, $logger, PEAR_TASK_PACKAGE);
                   32554:         $this->_contents = $fileXml;
                   32555:         $this->_pkg = &$pkg;
                   32556:         $this->_params = array();
                   32557:     }
                   32558: 
                   32559:     function validate()
                   32560:     {
                   32561:         return true;
                   32562:     }
                   32563: 
                   32564:     function getName()
                   32565:     {
                   32566:         return 'unixeol';
                   32567:     }
                   32568: 
                   32569:     function getXml()
                   32570:     {
                   32571:         return '';
                   32572:     }
                   32573: }
1.1.1.2 ! misho    32574: ?>PEAR-1.9.4/PEAR/Task/Windowseol/rw.php0000644000076500000240000000256211605156614016165 0ustar  helgistaff<?php
1.1       misho    32575: /**
                   32576:  * <tasks:windowseol> - read/write version
                   32577:  *
                   32578:  * PHP versions 4 and 5
                   32579:  *
                   32580:  * @category   pear
                   32581:  * @package    PEAR
                   32582:  * @author     Greg Beaver <cellog@php.net>
                   32583:  * @copyright  1997-2009 The Authors
                   32584:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32585:  * @version    CVS: $Id: rw.php 313023 2011-07-06 19:17:11Z dufuz $
                   32586:  * @link       http://pear.php.net/package/PEAR
                   32587:  * @since      File available since Release 1.4.0a10
                   32588:  */
                   32589: /**
                   32590:  * Base class
                   32591:  */
                   32592: require_once 'PEAR/Task/Windowseol.php';
                   32593: /**
                   32594:  * Abstracts the windowseol task xml.
                   32595:  * @category   pear
                   32596:  * @package    PEAR
                   32597:  * @author     Greg Beaver <cellog@php.net>
                   32598:  * @copyright  1997-2009 The Authors
                   32599:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32600:  * @version    Release: 1.9.4
                   32601:  * @link       http://pear.php.net/package/PEAR
                   32602:  * @since      Class available since Release 1.4.0a10
                   32603:  */
                   32604: class PEAR_Task_Windowseol_rw extends PEAR_Task_Windowseol
                   32605: {
                   32606:     function PEAR_Task_Windowseol_rw(&$pkg, &$config, &$logger, $fileXml)
                   32607:     {
                   32608:         parent::PEAR_Task_Common($config, $logger, PEAR_TASK_PACKAGE);
                   32609:         $this->_contents = $fileXml;
                   32610:         $this->_pkg = &$pkg;
                   32611:         $this->_params = array();
                   32612:     }
                   32613: 
                   32614:     function validate()
                   32615:     {
                   32616:         return true;
                   32617:     }
                   32618: 
                   32619:     function getName()
                   32620:     {
                   32621:         return 'windowseol';
                   32622:     }
                   32623: 
                   32624:     function getXml()
                   32625:     {
                   32626:         return '';
                   32627:     }
                   32628: }
1.1.1.2 ! misho    32629: ?>PEAR-1.9.4/PEAR/Task/Common.php0000644000076500000240000001373611605156614014640 0ustar  helgistaff<?php
1.1       misho    32630: /**
                   32631:  * PEAR_Task_Common, base class for installer tasks
                   32632:  *
                   32633:  * PHP versions 4 and 5
                   32634:  *
                   32635:  * @category   pear
                   32636:  * @package    PEAR
                   32637:  * @author     Greg Beaver <cellog@php.net>
                   32638:  * @copyright  1997-2009 The Authors
                   32639:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32640:  * @version    CVS: $Id: Common.php 313023 2011-07-06 19:17:11Z dufuz $
                   32641:  * @link       http://pear.php.net/package/PEAR
                   32642:  * @since      File available since Release 1.4.0a1
                   32643:  */
                   32644: /**#@+
                   32645:  * Error codes for task validation routines
                   32646:  */
                   32647: define('PEAR_TASK_ERROR_NOATTRIBS', 1);
                   32648: define('PEAR_TASK_ERROR_MISSING_ATTRIB', 2);
                   32649: define('PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE', 3);
                   32650: define('PEAR_TASK_ERROR_INVALID', 4);
                   32651: /**#@-*/
                   32652: define('PEAR_TASK_PACKAGE', 1);
                   32653: define('PEAR_TASK_INSTALL', 2);
                   32654: define('PEAR_TASK_PACKAGEANDINSTALL', 3);
                   32655: /**
                   32656:  * A task is an operation that manipulates the contents of a file.
                   32657:  *
                   32658:  * Simple tasks operate on 1 file.  Multiple tasks are executed after all files have been
                   32659:  * processed and installed, and are designed to operate on all files containing the task.
                   32660:  * The Post-install script task simply takes advantage of the fact that it will be run
                   32661:  * after installation, replace is a simple task.
                   32662:  *
                   32663:  * Combining tasks is possible, but ordering is significant.
                   32664:  *
                   32665:  * <file name="test.php" role="php">
                   32666:  *  <tasks:replace from="@data-dir@" to="data_dir" type="pear-config"/>
                   32667:  *  <tasks:postinstallscript/>
                   32668:  * </file>
                   32669:  *
                   32670:  * This will first replace any instance of @data-dir@ in the test.php file
                   32671:  * with the path to the current data directory.  Then, it will include the
                   32672:  * test.php file and run the script it contains to configure the package post-installation.
                   32673:  * @category   pear
                   32674:  * @package    PEAR
                   32675:  * @author     Greg Beaver <cellog@php.net>
                   32676:  * @copyright  1997-2009 The Authors
                   32677:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32678:  * @version    Release: 1.9.4
                   32679:  * @link       http://pear.php.net/package/PEAR
                   32680:  * @since      Class available since Release 1.4.0a1
                   32681:  * @abstract
                   32682:  */
                   32683: class PEAR_Task_Common
                   32684: {
                   32685:     /**
                   32686:      * Valid types for this version are 'simple' and 'multiple'
                   32687:      *
                   32688:      * - simple tasks operate on the contents of a file and write out changes to disk
                   32689:      * - multiple tasks operate on the contents of many files and write out the
                   32690:      *   changes directly to disk
                   32691:      *
                   32692:      * Child task classes must override this property.
                   32693:      * @access protected
                   32694:      */
                   32695:     var $type = 'simple';
                   32696:     /**
                   32697:      * Determines which install phase this task is executed under
                   32698:      */
                   32699:     var $phase = PEAR_TASK_INSTALL;
                   32700:     /**
                   32701:      * @access protected
                   32702:      */
                   32703:     var $config;
                   32704:     /**
                   32705:      * @access protected
                   32706:      */
                   32707:     var $registry;
                   32708:     /**
                   32709:      * @access protected
                   32710:      */
                   32711:     var $logger;
                   32712:     /**
                   32713:      * @access protected
                   32714:      */
                   32715:     var $installphase;
                   32716:     /**
                   32717:      * @param PEAR_Config
                   32718:      * @param PEAR_Common
                   32719:      */
                   32720:     function PEAR_Task_Common(&$config, &$logger, $phase)
                   32721:     {
                   32722:         $this->config = &$config;
                   32723:         $this->registry = &$config->getRegistry();
                   32724:         $this->logger = &$logger;
                   32725:         $this->installphase = $phase;
                   32726:         if ($this->type == 'multiple') {
                   32727:             $GLOBALS['_PEAR_TASK_POSTINSTANCES'][get_class($this)][] = &$this;
                   32728:         }
                   32729:     }
                   32730: 
                   32731:     /**
                   32732:      * Validate the basic contents of a task tag.
                   32733:      * @param PEAR_PackageFile_v2
                   32734:      * @param array
                   32735:      * @param PEAR_Config
                   32736:      * @param array the entire parsed <file> tag
                   32737:      * @return true|array On error, return an array in format:
                   32738:      *    array(PEAR_TASK_ERROR_???[, param1][, param2][, ...])
                   32739:      *
                   32740:      *    For PEAR_TASK_ERROR_MISSING_ATTRIB, pass the attribute name in
                   32741:      *    For PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, pass the attribute name and an array
                   32742:      *    of legal values in
                   32743:      * @static
                   32744:      * @abstract
                   32745:      */
                   32746:     function validateXml($pkg, $xml, $config, $fileXml)
                   32747:     {
                   32748:     }
                   32749: 
                   32750:     /**
                   32751:      * Initialize a task instance with the parameters
                   32752:      * @param array raw, parsed xml
                   32753:      * @param array attributes from the <file> tag containing this task
                   32754:      * @param string|null last installed version of this package
                   32755:      * @abstract
                   32756:      */
                   32757:     function init($xml, $fileAttributes, $lastVersion)
                   32758:     {
                   32759:     }
                   32760: 
                   32761:     /**
                   32762:      * Begin a task processing session.  All multiple tasks will be processed after each file
                   32763:      * has been successfully installed, all simple tasks should perform their task here and
                   32764:      * return any errors using the custom throwError() method to allow forward compatibility
                   32765:      *
                   32766:      * This method MUST NOT write out any changes to disk
                   32767:      * @param PEAR_PackageFile_v2
                   32768:      * @param string file contents
                   32769:      * @param string the eventual final file location (informational only)
                   32770:      * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
                   32771:      *         (use $this->throwError), otherwise return the new contents
                   32772:      * @abstract
                   32773:      */
                   32774:     function startSession($pkg, $contents, $dest)
                   32775:     {
                   32776:     }
                   32777: 
                   32778:     /**
                   32779:      * This method is used to process each of the tasks for a particular multiple class
                   32780:      * type.  Simple tasks need not implement this method.
                   32781:      * @param array an array of tasks
                   32782:      * @access protected
                   32783:      * @static
                   32784:      * @abstract
                   32785:      */
                   32786:     function run($tasks)
                   32787:     {
                   32788:     }
                   32789: 
                   32790:     /**
                   32791:      * @static
                   32792:      * @final
                   32793:      */
                   32794:     function hasPostinstallTasks()
                   32795:     {
                   32796:         return isset($GLOBALS['_PEAR_TASK_POSTINSTANCES']);
                   32797:     }
                   32798: 
                   32799:     /**
                   32800:      * @static
                   32801:      * @final
                   32802:      */
                   32803:      function runPostinstallTasks()
                   32804:      {
                   32805:          foreach ($GLOBALS['_PEAR_TASK_POSTINSTANCES'] as $class => $tasks) {
                   32806:              $err = call_user_func(array($class, 'run'),
                   32807:                   $GLOBALS['_PEAR_TASK_POSTINSTANCES'][$class]);
                   32808:              if ($err) {
                   32809:                  return PEAR_Task_Common::throwError($err);
                   32810:              }
                   32811:          }
                   32812:          unset($GLOBALS['_PEAR_TASK_POSTINSTANCES']);
                   32813:     }
                   32814: 
                   32815:     /**
                   32816:      * Determines whether a role is a script
                   32817:      * @return bool
                   32818:      */
                   32819:     function isScript()
                   32820:     {
                   32821:         return $this->type == 'script';
                   32822:     }
                   32823: 
                   32824:     function throwError($msg, $code = -1)
                   32825:     {
                   32826:         include_once 'PEAR.php';
                   32827:         return PEAR::raiseError($msg, $code);
                   32828:     }
                   32829: }
1.1.1.2 ! misho    32830: ?>PEAR-1.9.4/PEAR/Task/Postinstallscript.php0000644000076500000240000003412211605156614017141 0ustar  helgistaff<?php
1.1       misho    32831: /**
                   32832:  * <tasks:postinstallscript>
                   32833:  *
                   32834:  * PHP versions 4 and 5
                   32835:  *
                   32836:  * @category   pear
                   32837:  * @package    PEAR
                   32838:  * @author     Greg Beaver <cellog@php.net>
                   32839:  * @copyright  1997-2009 The Authors
                   32840:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32841:  * @version    CVS: $Id: Postinstallscript.php 313023 2011-07-06 19:17:11Z dufuz $
                   32842:  * @link       http://pear.php.net/package/PEAR
                   32843:  * @since      File available since Release 1.4.0a1
                   32844:  */
                   32845: /**
                   32846:  * Base class
                   32847:  */
                   32848: require_once 'PEAR/Task/Common.php';
                   32849: /**
                   32850:  * Implements the postinstallscript file task.
                   32851:  *
                   32852:  * Note that post-install scripts are handled separately from installation, by the
                   32853:  * "pear run-scripts" command
                   32854:  * @category   pear
                   32855:  * @package    PEAR
                   32856:  * @author     Greg Beaver <cellog@php.net>
                   32857:  * @copyright  1997-2009 The Authors
                   32858:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   32859:  * @version    Release: 1.9.4
                   32860:  * @link       http://pear.php.net/package/PEAR
                   32861:  * @since      Class available since Release 1.4.0a1
                   32862:  */
                   32863: class PEAR_Task_Postinstallscript extends PEAR_Task_Common
                   32864: {
                   32865:     var $type = 'script';
                   32866:     var $_class;
                   32867:     var $_params;
                   32868:     var $_obj;
                   32869:     /**
                   32870:      *
                   32871:      * @var PEAR_PackageFile_v2
                   32872:      */
                   32873:     var $_pkg;
                   32874:     var $_contents;
                   32875:     var $phase = PEAR_TASK_INSTALL;
                   32876: 
                   32877:     /**
                   32878:      * Validate the raw xml at parsing-time.
                   32879:      *
                   32880:      * This also attempts to validate the script to make sure it meets the criteria
                   32881:      * for a post-install script
                   32882:      * @param PEAR_PackageFile_v2
                   32883:      * @param array The XML contents of the <postinstallscript> tag
                   32884:      * @param PEAR_Config
                   32885:      * @param array the entire parsed <file> tag
                   32886:      * @static
                   32887:      */
                   32888:     function validateXml($pkg, $xml, $config, $fileXml)
                   32889:     {
                   32890:         if ($fileXml['role'] != 'php') {
                   32891:             return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32892:             $fileXml['name'] . '" must be role="php"');
                   32893:         }
                   32894:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   32895:         $file = $pkg->getFileContents($fileXml['name']);
                   32896:         if (PEAR::isError($file)) {
                   32897:             PEAR::popErrorHandling();
                   32898:             return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32899:                 $fileXml['name'] . '" is not valid: ' .
                   32900:                 $file->getMessage());
                   32901:         } elseif ($file === null) {
                   32902:             return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32903:                 $fileXml['name'] . '" could not be retrieved for processing!');
                   32904:         } else {
                   32905:             $analysis = $pkg->analyzeSourceCode($file, true);
                   32906:             if (!$analysis) {
                   32907:                 PEAR::popErrorHandling();
                   32908:                 $warnings = '';
                   32909:                 foreach ($pkg->getValidationWarnings() as $warn) {
                   32910:                     $warnings .= $warn['message'] . "\n";
                   32911:                 }
                   32912:                 return array(PEAR_TASK_ERROR_INVALID, 'Analysis of post-install script "' .
                   32913:                     $fileXml['name'] . '" failed: ' . $warnings);
                   32914:             }
                   32915:             if (count($analysis['declared_classes']) != 1) {
                   32916:                 PEAR::popErrorHandling();
                   32917:                 return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32918:                     $fileXml['name'] . '" must declare exactly 1 class');
                   32919:             }
                   32920:             $class = $analysis['declared_classes'][0];
                   32921:             if ($class != str_replace(array('/', '.php'), array('_', ''),
                   32922:                   $fileXml['name']) . '_postinstall') {
                   32923:                 PEAR::popErrorHandling();
                   32924:                 return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32925:                     $fileXml['name'] . '" class "' . $class . '" must be named "' .
                   32926:                     str_replace(array('/', '.php'), array('_', ''),
                   32927:                     $fileXml['name']) . '_postinstall"');
                   32928:             }
                   32929:             if (!isset($analysis['declared_methods'][$class])) {
                   32930:                 PEAR::popErrorHandling();
                   32931:                 return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32932:                     $fileXml['name'] . '" must declare methods init() and run()');
                   32933:             }
                   32934:             $methods = array('init' => 0, 'run' => 1);
                   32935:             foreach ($analysis['declared_methods'][$class] as $method) {
                   32936:                 if (isset($methods[$method])) {
                   32937:                     unset($methods[$method]);
                   32938:                 }
                   32939:             }
                   32940:             if (count($methods)) {
                   32941:                 PEAR::popErrorHandling();
                   32942:                 return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32943:                     $fileXml['name'] . '" must declare methods init() and run()');
                   32944:             }
                   32945:         }
                   32946:         PEAR::popErrorHandling();
                   32947:         $definedparams = array();
                   32948:         $tasksNamespace = $pkg->getTasksNs() . ':';
                   32949:         if (!isset($xml[$tasksNamespace . 'paramgroup']) && isset($xml['paramgroup'])) {
                   32950:             // in order to support the older betas, which did not expect internal tags
                   32951:             // to also use the namespace
                   32952:             $tasksNamespace = '';
                   32953:         }
                   32954:         if (isset($xml[$tasksNamespace . 'paramgroup'])) {
                   32955:             $params = $xml[$tasksNamespace . 'paramgroup'];
                   32956:             if (!is_array($params) || !isset($params[0])) {
                   32957:                 $params = array($params);
                   32958:             }
                   32959:             foreach ($params as $param) {
                   32960:                 if (!isset($param[$tasksNamespace . 'id'])) {
                   32961:                     return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32962:                         $fileXml['name'] . '" <paramgroup> must have ' .
                   32963:                         'an ' . $tasksNamespace . 'id> tag');
                   32964:                 }
                   32965:                 if (isset($param[$tasksNamespace . 'name'])) {
                   32966:                     if (!in_array($param[$tasksNamespace . 'name'], $definedparams)) {
                   32967:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32968:                             $fileXml['name'] . '" ' . $tasksNamespace .
                   32969:                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
                   32970:                             '" parameter "' . $param[$tasksNamespace . 'name'] .
                   32971:                             '" has not been previously defined');
                   32972:                     }
                   32973:                     if (!isset($param[$tasksNamespace . 'conditiontype'])) {
                   32974:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32975:                             $fileXml['name'] . '" ' . $tasksNamespace .
                   32976:                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
                   32977:                             '" must have a ' . $tasksNamespace .
                   32978:                             'conditiontype> tag containing either "=", ' .
                   32979:                             '"!=", or "preg_match"');
                   32980:                     }
                   32981:                     if (!in_array($param[$tasksNamespace . 'conditiontype'],
                   32982:                           array('=', '!=', 'preg_match'))) {
                   32983:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32984:                             $fileXml['name'] . '" ' . $tasksNamespace .
                   32985:                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
                   32986:                             '" must have a ' . $tasksNamespace .
                   32987:                             'conditiontype> tag containing either "=", ' .
                   32988:                             '"!=", or "preg_match"');
                   32989:                     }
                   32990:                     if (!isset($param[$tasksNamespace . 'value'])) {
                   32991:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   32992:                             $fileXml['name'] . '" ' . $tasksNamespace .
                   32993:                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
                   32994:                             '" must have a ' . $tasksNamespace .
                   32995:                             'value> tag containing expected parameter value');
                   32996:                     }
                   32997:                 }
                   32998:                 if (isset($param[$tasksNamespace . 'instructions'])) {
                   32999:                     if (!is_string($param[$tasksNamespace . 'instructions'])) {
                   33000:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   33001:                             $fileXml['name'] . '" ' . $tasksNamespace .
                   33002:                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
                   33003:                             '" ' . $tasksNamespace . 'instructions> must be simple text');
                   33004:                     }
                   33005:                 }
                   33006:                 if (!isset($param[$tasksNamespace . 'param'])) {
                   33007:                     continue; // <param> is no longer required
                   33008:                 }
                   33009:                 $subparams = $param[$tasksNamespace . 'param'];
                   33010:                 if (!is_array($subparams) || !isset($subparams[0])) {
                   33011:                     $subparams = array($subparams);
                   33012:                 }
                   33013:                 foreach ($subparams as $subparam) {
                   33014:                     if (!isset($subparam[$tasksNamespace . 'name'])) {
                   33015:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   33016:                             $fileXml['name'] . '" parameter for ' .
                   33017:                             $tasksNamespace . 'paramgroup> id "' .
                   33018:                             $param[$tasksNamespace . 'id'] . '" must have ' .
                   33019:                             'a ' . $tasksNamespace . 'name> tag');
                   33020:                     }
                   33021:                     if (!preg_match('/[a-zA-Z0-9]+/',
                   33022:                           $subparam[$tasksNamespace . 'name'])) {
                   33023:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   33024:                             $fileXml['name'] . '" parameter "' .
                   33025:                             $subparam[$tasksNamespace . 'name'] .
                   33026:                             '" for ' . $tasksNamespace . 'paramgroup> id "' .
                   33027:                             $param[$tasksNamespace . 'id'] .
                   33028:                             '" is not a valid name.  Must contain only alphanumeric characters');
                   33029:                     }
                   33030:                     if (!isset($subparam[$tasksNamespace . 'prompt'])) {
                   33031:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   33032:                             $fileXml['name'] . '" parameter "' .
                   33033:                             $subparam[$tasksNamespace . 'name'] .
                   33034:                             '" for ' . $tasksNamespace . 'paramgroup> id "' .
                   33035:                             $param[$tasksNamespace . 'id'] .
                   33036:                             '" must have a ' . $tasksNamespace . 'prompt> tag');
                   33037:                     }
                   33038:                     if (!isset($subparam[$tasksNamespace . 'type'])) {
                   33039:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   33040:                             $fileXml['name'] . '" parameter "' .
                   33041:                             $subparam[$tasksNamespace . 'name'] .
                   33042:                             '" for ' . $tasksNamespace . 'paramgroup> id "' .
                   33043:                             $param[$tasksNamespace . 'id'] .
                   33044:                             '" must have a ' . $tasksNamespace . 'type> tag');
                   33045:                     }
                   33046:                     $definedparams[] = $param[$tasksNamespace . 'id'] . '::' .
                   33047:                     $subparam[$tasksNamespace . 'name'];
                   33048:                 }
                   33049:             }
                   33050:         }
                   33051:         return true;
                   33052:     }
                   33053: 
                   33054:     /**
                   33055:      * Initialize a task instance with the parameters
                   33056:      * @param array raw, parsed xml
                   33057:      * @param array attributes from the <file> tag containing this task
                   33058:      * @param string|null last installed version of this package, if any (useful for upgrades)
                   33059:      */
                   33060:     function init($xml, $fileattribs, $lastversion)
                   33061:     {
                   33062:         $this->_class = str_replace('/', '_', $fileattribs['name']);
                   33063:         $this->_filename = $fileattribs['name'];
                   33064:         $this->_class = str_replace ('.php', '', $this->_class) . '_postinstall';
                   33065:         $this->_params = $xml;
                   33066:         $this->_lastversion = $lastversion;
                   33067:     }
                   33068: 
                   33069:     /**
                   33070:      * Strip the tasks: namespace from internal params
                   33071:      *
                   33072:      * @access private
                   33073:      */
                   33074:     function _stripNamespace($params = null)
                   33075:     {
                   33076:         if ($params === null) {
                   33077:             $params = array();
                   33078:             if (!is_array($this->_params)) {
                   33079:                 return;
                   33080:             }
                   33081:             foreach ($this->_params as $i => $param) {
                   33082:                 if (is_array($param)) {
                   33083:                     $param = $this->_stripNamespace($param);
                   33084:                 }
                   33085:                 $params[str_replace($this->_pkg->getTasksNs() . ':', '', $i)] = $param;
                   33086:             }
                   33087:             $this->_params = $params;
                   33088:         } else {
                   33089:             $newparams = array();
                   33090:             foreach ($params as $i => $param) {
                   33091:                 if (is_array($param)) {
                   33092:                     $param = $this->_stripNamespace($param);
                   33093:                 }
                   33094:                 $newparams[str_replace($this->_pkg->getTasksNs() . ':', '', $i)] = $param;
                   33095:             }
                   33096:             return $newparams;
                   33097:         }
                   33098:     }
                   33099: 
                   33100:     /**
                   33101:      * Unlike other tasks, the installed file name is passed in instead of the file contents,
                   33102:      * because this task is handled post-installation
                   33103:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   33104:      * @param string file name
                   33105:      * @return bool|PEAR_Error false to skip this file, PEAR_Error to fail
                   33106:      *         (use $this->throwError)
                   33107:      */
                   33108:     function startSession($pkg, $contents)
                   33109:     {
                   33110:         if ($this->installphase != PEAR_TASK_INSTALL) {
                   33111:             return false;
                   33112:         }
                   33113:         // remove the tasks: namespace if present
                   33114:         $this->_pkg = $pkg;
                   33115:         $this->_stripNamespace();
                   33116:         $this->logger->log(0, 'Including external post-installation script "' .
                   33117:             $contents . '" - any errors are in this script');
                   33118:         include_once $contents;
                   33119:         if (class_exists($this->_class)) {
                   33120:             $this->logger->log(0, 'Inclusion succeeded');
                   33121:         } else {
                   33122:             return $this->throwError('init of post-install script class "' . $this->_class
                   33123:                 . '" failed');
                   33124:         }
                   33125:         $this->_obj = new $this->_class;
                   33126:         $this->logger->log(1, 'running post-install script "' . $this->_class . '->init()"');
                   33127:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   33128:         $res = $this->_obj->init($this->config, $pkg, $this->_lastversion);
                   33129:         PEAR::popErrorHandling();
                   33130:         if ($res) {
                   33131:             $this->logger->log(0, 'init succeeded');
                   33132:         } else {
                   33133:             return $this->throwError('init of post-install script "' . $this->_class .
                   33134:                 '->init()" failed');
                   33135:         }
                   33136:         $this->_contents = $contents;
                   33137:         return true;
                   33138:     }
                   33139: 
                   33140:     /**
                   33141:      * No longer used
                   33142:      * @see PEAR_PackageFile_v2::runPostinstallScripts()
                   33143:      * @param array an array of tasks
                   33144:      * @param string install or upgrade
                   33145:      * @access protected
                   33146:      * @static
                   33147:      */
                   33148:     function run()
                   33149:     {
                   33150:     }
                   33151: }
1.1.1.2 ! misho    33152: ?>PEAR-1.9.4/PEAR/Task/Replace.php0000644000076500000240000001523211605156614014754 0ustar  helgistaff<?php
1.1       misho    33153: /**
                   33154:  * <tasks:replace>
                   33155:  *
                   33156:  * PHP versions 4 and 5
                   33157:  *
                   33158:  * @category   pear
                   33159:  * @package    PEAR
                   33160:  * @author     Greg Beaver <cellog@php.net>
                   33161:  * @copyright  1997-2009 The Authors
                   33162:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33163:  * @version    CVS: $Id: Replace.php 313023 2011-07-06 19:17:11Z dufuz $
                   33164:  * @link       http://pear.php.net/package/PEAR
                   33165:  * @since      File available since Release 1.4.0a1
                   33166:  */
                   33167: /**
                   33168:  * Base class
                   33169:  */
                   33170: require_once 'PEAR/Task/Common.php';
                   33171: /**
                   33172:  * Implements the replace file task.
                   33173:  * @category   pear
                   33174:  * @package    PEAR
                   33175:  * @author     Greg Beaver <cellog@php.net>
                   33176:  * @copyright  1997-2009 The Authors
                   33177:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33178:  * @version    Release: 1.9.4
                   33179:  * @link       http://pear.php.net/package/PEAR
                   33180:  * @since      Class available since Release 1.4.0a1
                   33181:  */
                   33182: class PEAR_Task_Replace extends PEAR_Task_Common
                   33183: {
                   33184:     var $type = 'simple';
                   33185:     var $phase = PEAR_TASK_PACKAGEANDINSTALL;
                   33186:     var $_replacements;
                   33187: 
                   33188:     /**
                   33189:      * Validate the raw xml at parsing-time.
                   33190:      * @param PEAR_PackageFile_v2
                   33191:      * @param array raw, parsed xml
                   33192:      * @param PEAR_Config
                   33193:      * @static
                   33194:      */
                   33195:     function validateXml($pkg, $xml, $config, $fileXml)
                   33196:     {
                   33197:         if (!isset($xml['attribs'])) {
                   33198:             return array(PEAR_TASK_ERROR_NOATTRIBS);
                   33199:         }
                   33200:         if (!isset($xml['attribs']['type'])) {
                   33201:             return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'type');
                   33202:         }
                   33203:         if (!isset($xml['attribs']['to'])) {
                   33204:             return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'to');
                   33205:         }
                   33206:         if (!isset($xml['attribs']['from'])) {
                   33207:             return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'from');
                   33208:         }
                   33209:         if ($xml['attribs']['type'] == 'pear-config') {
                   33210:             if (!in_array($xml['attribs']['to'], $config->getKeys())) {
                   33211:                 return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'],
                   33212:                     $config->getKeys());
                   33213:             }
                   33214:         } elseif ($xml['attribs']['type'] == 'php-const') {
                   33215:             if (defined($xml['attribs']['to'])) {
                   33216:                 return true;
                   33217:             } else {
                   33218:                 return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'],
                   33219:                     array('valid PHP constant'));
                   33220:             }
                   33221:         } elseif ($xml['attribs']['type'] == 'package-info') {
                   33222:             if (in_array($xml['attribs']['to'],
                   33223:                 array('name', 'summary', 'channel', 'notes', 'extends', 'description',
                   33224:                     'release_notes', 'license', 'release-license', 'license-uri',
                   33225:                     'version', 'api-version', 'state', 'api-state', 'release_date',
                   33226:                     'date', 'time'))) {
                   33227:                 return true;
                   33228:             } else {
                   33229:                 return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'],
                   33230:                     array('name', 'summary', 'channel', 'notes', 'extends', 'description',
                   33231:                     'release_notes', 'license', 'release-license', 'license-uri',
                   33232:                     'version', 'api-version', 'state', 'api-state', 'release_date',
                   33233:                     'date', 'time'));
                   33234:             }
                   33235:         } else {
                   33236:             return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'type', $xml['attribs']['type'],
                   33237:                 array('pear-config', 'package-info', 'php-const'));
                   33238:         }
                   33239:         return true;
                   33240:     }
                   33241: 
                   33242:     /**
                   33243:      * Initialize a task instance with the parameters
                   33244:      * @param array raw, parsed xml
                   33245:      * @param unused
                   33246:      */
                   33247:     function init($xml, $attribs)
                   33248:     {
                   33249:         $this->_replacements = isset($xml['attribs']) ? array($xml) : $xml;
                   33250:     }
                   33251: 
                   33252:     /**
                   33253:      * Do a package.xml 1.0 replacement, with additional package-info fields available
                   33254:      *
                   33255:      * See validateXml() source for the complete list of allowed fields
                   33256:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   33257:      * @param string file contents
                   33258:      * @param string the eventual final file location (informational only)
                   33259:      * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
                   33260:      *         (use $this->throwError), otherwise return the new contents
                   33261:      */
                   33262:     function startSession($pkg, $contents, $dest)
                   33263:     {
                   33264:         $subst_from = $subst_to = array();
                   33265:         foreach ($this->_replacements as $a) {
                   33266:             $a = $a['attribs'];
                   33267:             $to = '';
                   33268:             if ($a['type'] == 'pear-config') {
                   33269:                 if ($this->installphase == PEAR_TASK_PACKAGE) {
                   33270:                     return false;
                   33271:                 }
                   33272:                 if ($a['to'] == 'master_server') {
                   33273:                     $chan = $this->registry->getChannel($pkg->getChannel());
                   33274:                     if (!PEAR::isError($chan)) {
                   33275:                         $to = $chan->getServer();
                   33276:                     } else {
                   33277:                         $this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]");
                   33278:                         return false;
                   33279:                     }
                   33280:                 } else {
                   33281:                     if ($this->config->isDefinedLayer('ftp')) {
                   33282:                         // try the remote config file first
                   33283:                         $to = $this->config->get($a['to'], 'ftp', $pkg->getChannel());
                   33284:                         if (is_null($to)) {
                   33285:                             // then default to local
                   33286:                             $to = $this->config->get($a['to'], null, $pkg->getChannel());
                   33287:                         }
                   33288:                     } else {
                   33289:                         $to = $this->config->get($a['to'], null, $pkg->getChannel());
                   33290:                     }
                   33291:                 }
                   33292:                 if (is_null($to)) {
                   33293:                     $this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]");
                   33294:                     return false;
                   33295:                 }
                   33296:             } elseif ($a['type'] == 'php-const') {
                   33297:                 if ($this->installphase == PEAR_TASK_PACKAGE) {
                   33298:                     return false;
                   33299:                 }
                   33300:                 if (defined($a['to'])) {
                   33301:                     $to = constant($a['to']);
                   33302:                 } else {
                   33303:                     $this->logger->log(0, "$dest: invalid php-const replacement: $a[to]");
                   33304:                     return false;
                   33305:                 }
                   33306:             } else {
                   33307:                 if ($t = $pkg->packageInfo($a['to'])) {
                   33308:                     $to = $t;
                   33309:                 } else {
                   33310:                     $this->logger->log(0, "$dest: invalid package-info replacement: $a[to]");
                   33311:                     return false;
                   33312:                 }
                   33313:             }
                   33314:             if (!is_null($to)) {
                   33315:                 $subst_from[] = $a['from'];
                   33316:                 $subst_to[] = $to;
                   33317:             }
                   33318:         }
                   33319:         $this->logger->log(3, "doing " . sizeof($subst_from) .
                   33320:             " substitution(s) for $dest");
                   33321:         if (sizeof($subst_from)) {
                   33322:             $contents = str_replace($subst_from, $subst_to, $contents);
                   33323:         }
                   33324:         return $contents;
                   33325:     }
                   33326: }
1.1.1.2 ! misho    33327: ?>PEAR-1.9.4/PEAR/Task/Unixeol.php0000644000076500000240000000434111605156614015023 0ustar  helgistaff<?php
1.1       misho    33328: /**
                   33329:  * <tasks:unixeol>
                   33330:  *
                   33331:  * PHP versions 4 and 5
                   33332:  *
                   33333:  * @category   pear
                   33334:  * @package    PEAR
                   33335:  * @author     Greg Beaver <cellog@php.net>
                   33336:  * @copyright  1997-2009 The Authors
                   33337:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33338:  * @version    CVS: $Id: Unixeol.php 313023 2011-07-06 19:17:11Z dufuz $
                   33339:  * @link       http://pear.php.net/package/PEAR
                   33340:  * @since      File available since Release 1.4.0a1
                   33341:  */
                   33342: /**
                   33343:  * Base class
                   33344:  */
                   33345: require_once 'PEAR/Task/Common.php';
                   33346: /**
                   33347:  * Implements the unix line endings file task.
                   33348:  * @category   pear
                   33349:  * @package    PEAR
                   33350:  * @author     Greg Beaver <cellog@php.net>
                   33351:  * @copyright  1997-2009 The Authors
                   33352:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33353:  * @version    Release: 1.9.4
                   33354:  * @link       http://pear.php.net/package/PEAR
                   33355:  * @since      Class available since Release 1.4.0a1
                   33356:  */
                   33357: class PEAR_Task_Unixeol extends PEAR_Task_Common
                   33358: {
                   33359:     var $type = 'simple';
                   33360:     var $phase = PEAR_TASK_PACKAGE;
                   33361:     var $_replacements;
                   33362: 
                   33363:     /**
                   33364:      * Validate the raw xml at parsing-time.
                   33365:      * @param PEAR_PackageFile_v2
                   33366:      * @param array raw, parsed xml
                   33367:      * @param PEAR_Config
                   33368:      * @static
                   33369:      */
                   33370:     function validateXml($pkg, $xml, $config, $fileXml)
                   33371:     {
                   33372:         if ($xml != '') {
                   33373:             return array(PEAR_TASK_ERROR_INVALID, 'no attributes allowed');
                   33374:         }
                   33375:         return true;
                   33376:     }
                   33377: 
                   33378:     /**
                   33379:      * Initialize a task instance with the parameters
                   33380:      * @param array raw, parsed xml
                   33381:      * @param unused
                   33382:      */
                   33383:     function init($xml, $attribs)
                   33384:     {
                   33385:     }
                   33386: 
                   33387:     /**
                   33388:      * Replace all line endings with line endings customized for the current OS
                   33389:      *
                   33390:      * See validateXml() source for the complete list of allowed fields
                   33391:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   33392:      * @param string file contents
                   33393:      * @param string the eventual final file location (informational only)
                   33394:      * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
                   33395:      *         (use $this->throwError), otherwise return the new contents
                   33396:      */
                   33397:     function startSession($pkg, $contents, $dest)
                   33398:     {
                   33399:         $this->logger->log(3, "replacing all line endings with \\n in $dest");
                   33400:         return preg_replace("/\r\n|\n\r|\r|\n/", "\n", $contents);
                   33401:     }
                   33402: }
1.1.1.2 ! misho    33403: ?>PEAR-1.9.4/PEAR/Task/Windowseol.php0000644000076500000240000000433511605156614015535 0ustar  helgistaff<?php
1.1       misho    33404: /**
                   33405:  * <tasks:windowseol>
                   33406:  *
                   33407:  * PHP versions 4 and 5
                   33408:  *
                   33409:  * @category   pear
                   33410:  * @package    PEAR
                   33411:  * @author     Greg Beaver <cellog@php.net>
                   33412:  * @copyright  1997-2009 The Authors
                   33413:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33414:  * @version    CVS: $Id: Windowseol.php 313023 2011-07-06 19:17:11Z dufuz $
                   33415:  * @link       http://pear.php.net/package/PEAR
                   33416:  * @since      File available since Release 1.4.0a1
                   33417:  */
                   33418: /**
                   33419:  * Base class
                   33420:  */
                   33421: require_once 'PEAR/Task/Common.php';
                   33422: /**
                   33423:  * Implements the windows line endsings file task.
                   33424:  * @category   pear
                   33425:  * @package    PEAR
                   33426:  * @author     Greg Beaver <cellog@php.net>
                   33427:  * @copyright  1997-2009 The Authors
                   33428:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33429:  * @version    Release: 1.9.4
                   33430:  * @link       http://pear.php.net/package/PEAR
                   33431:  * @since      Class available since Release 1.4.0a1
                   33432:  */
                   33433: class PEAR_Task_Windowseol extends PEAR_Task_Common
                   33434: {
                   33435:     var $type = 'simple';
                   33436:     var $phase = PEAR_TASK_PACKAGE;
                   33437:     var $_replacements;
                   33438: 
                   33439:     /**
                   33440:      * Validate the raw xml at parsing-time.
                   33441:      * @param PEAR_PackageFile_v2
                   33442:      * @param array raw, parsed xml
                   33443:      * @param PEAR_Config
                   33444:      * @static
                   33445:      */
                   33446:     function validateXml($pkg, $xml, $config, $fileXml)
                   33447:     {
                   33448:         if ($xml != '') {
                   33449:             return array(PEAR_TASK_ERROR_INVALID, 'no attributes allowed');
                   33450:         }
                   33451:         return true;
                   33452:     }
                   33453: 
                   33454:     /**
                   33455:      * Initialize a task instance with the parameters
                   33456:      * @param array raw, parsed xml
                   33457:      * @param unused
                   33458:      */
                   33459:     function init($xml, $attribs)
                   33460:     {
                   33461:     }
                   33462: 
                   33463:     /**
                   33464:      * Replace all line endings with windows line endings
                   33465:      *
                   33466:      * See validateXml() source for the complete list of allowed fields
                   33467:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   33468:      * @param string file contents
                   33469:      * @param string the eventual final file location (informational only)
                   33470:      * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
                   33471:      *         (use $this->throwError), otherwise return the new contents
                   33472:      */
                   33473:     function startSession($pkg, $contents, $dest)
                   33474:     {
                   33475:         $this->logger->log(3, "replacing all line endings with \\r\\n in $dest");
                   33476:         return preg_replace("/\r\n|\n\r|\r|\n/", "\r\n", $contents);
                   33477:     }
                   33478: }
1.1.1.2 ! misho    33479: ?>PEAR-1.9.4/PEAR/Validator/PECL.php0000644000076500000240000000417511605156614015153 0ustar  helgistaff<?php
1.1       misho    33480: /**
                   33481:  * Channel Validator for the pecl.php.net channel
                   33482:  *
                   33483:  * PHP 4 and PHP 5
                   33484:  *
                   33485:  * @category   pear
                   33486:  * @package    PEAR
                   33487:  * @author     Greg Beaver <cellog@php.net>
                   33488:  * @copyright  1997-2006 The PHP Group
                   33489:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33490:  * @version    CVS: $Id: PECL.php 313023 2011-07-06 19:17:11Z dufuz $
                   33491:  * @link       http://pear.php.net/package/PEAR
                   33492:  * @since      File available since Release 1.4.0a5
                   33493:  */
                   33494: /**
                   33495:  * This is the parent class for all validators
                   33496:  */
                   33497: require_once 'PEAR/Validate.php';
                   33498: /**
                   33499:  * Channel Validator for the pecl.php.net channel
                   33500:  * @category   pear
                   33501:  * @package    PEAR
                   33502:  * @author     Greg Beaver <cellog@php.net>
                   33503:  * @copyright  1997-2009 The Authors
                   33504:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33505:  * @version    Release: 1.9.4
                   33506:  * @link       http://pear.php.net/package/PEAR
                   33507:  * @since      Class available since Release 1.4.0a5
                   33508:  */
                   33509: class PEAR_Validator_PECL extends PEAR_Validate
                   33510: {
                   33511:     function validateVersion()
                   33512:     {
                   33513:         if ($this->_state == PEAR_VALIDATE_PACKAGING) {
                   33514:             $version = $this->_packagexml->getVersion();
                   33515:             $versioncomponents = explode('.', $version);
                   33516:             $last = array_pop($versioncomponents);
                   33517:             if (substr($last, 1, 2) == 'rc') {
                   33518:                 $this->_addFailure('version', 'Release Candidate versions must have ' .
                   33519:                 'upper-case RC, not lower-case rc');
                   33520:                 return false;
                   33521:             }
                   33522:         }
                   33523:         return true;
                   33524:     }
                   33525: 
                   33526:     function validatePackageName()
                   33527:     {
                   33528:         $ret = parent::validatePackageName();
                   33529:         if ($this->_packagexml->getPackageType() == 'extsrc' ||
                   33530:               $this->_packagexml->getPackageType() == 'zendextsrc') {
                   33531:             if (strtolower($this->_packagexml->getPackage()) !=
                   33532:                   strtolower($this->_packagexml->getProvidesExtension())) {
                   33533:                 $this->_addWarning('providesextension', 'package name "' .
                   33534:                     $this->_packagexml->getPackage() . '" is different from extension name "' .
                   33535:                     $this->_packagexml->getProvidesExtension() . '"');
                   33536:             }
                   33537:         }
                   33538:         return $ret;
                   33539:     }
                   33540: }
1.1.1.2 ! misho    33541: ?>PEAR-1.9.4/PEAR/Autoloader.php0000644000076500000240000001464511605156614014605 0ustar  helgistaff<?php
1.1       misho    33542: /**
                   33543:  * Class auto-loader
                   33544:  *
                   33545:  * PHP versions 4
                   33546: 
                   33547:  *
                   33548:  * @category   pear
                   33549:  * @package    PEAR
                   33550:  * @author     Stig Bakken <ssb@php.net>
                   33551:  * @copyright  1997-2009 The Authors
                   33552:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33553:  * @version    CVS: $Id: Autoloader.php 313023 2011-07-06 19:17:11Z dufuz $
                   33554:  * @link       http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader
                   33555:  * @since      File available since Release 0.1
                   33556:  * @deprecated File deprecated in Release 1.4.0a1
                   33557:  */
                   33558: 
                   33559: // /* vim: set expandtab tabstop=4 shiftwidth=4: */
                   33560: 
                   33561: if (!extension_loaded("overload")) {
                   33562:     // die hard without ext/overload
                   33563:     die("Rebuild PHP with the `overload' extension to use PEAR_Autoloader");
                   33564: }
                   33565: 
                   33566: /**
                   33567:  * Include for PEAR_Error and PEAR classes
                   33568:  */
                   33569: require_once "PEAR.php";
                   33570: 
                   33571: /**
                   33572:  * This class is for objects where you want to separate the code for
                   33573:  * some methods into separate classes.  This is useful if you have a
                   33574:  * class with not-frequently-used methods that contain lots of code
                   33575:  * that you would like to avoid always parsing.
                   33576:  *
                   33577:  * The PEAR_Autoloader class provides autoloading and aggregation.
                   33578:  * The autoloading lets you set up in which classes the separated
                   33579:  * methods are found.  Aggregation is the technique used to import new
                   33580:  * methods, an instance of each class providing separated methods is
                   33581:  * stored and called every time the aggregated method is called.
                   33582:  *
                   33583:  * @category   pear
                   33584:  * @package    PEAR
                   33585:  * @author Stig Bakken <ssb@php.net>
                   33586:  * @copyright  1997-2009 The Authors
                   33587:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33588:  * @version    Release: 1.9.4
                   33589:  * @link       http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader
                   33590:  * @since      File available since Release 0.1
                   33591:  * @deprecated File deprecated in Release 1.4.0a1
                   33592:  */
                   33593: class PEAR_Autoloader extends PEAR
                   33594: {
                   33595:     // {{{ properties
                   33596: 
                   33597:     /**
                   33598:      * Map of methods and classes where they are defined
                   33599:      *
                   33600:      * @var array
                   33601:      *
                   33602:      * @access private
                   33603:      */
                   33604:     var $_autoload_map = array();
                   33605: 
                   33606:     /**
                   33607:      * Map of methods and aggregate objects
                   33608:      *
                   33609:      * @var array
                   33610:      *
                   33611:      * @access private
                   33612:      */
                   33613:     var $_method_map = array();
                   33614: 
                   33615:     // }}}
                   33616:     // {{{ addAutoload()
                   33617: 
                   33618:     /**
                   33619:      * Add one or more autoload entries.
                   33620:      *
                   33621:      * @param string $method     which method to autoload
                   33622:      *
                   33623:      * @param string $classname  (optional) which class to find the method in.
                   33624:      *                           If the $method parameter is an array, this
                   33625:      *                           parameter may be omitted (and will be ignored
                   33626:      *                           if not), and the $method parameter will be
                   33627:      *                           treated as an associative array with method
                   33628:      *                           names as keys and class names as values.
                   33629:      *
                   33630:      * @return void
                   33631:      *
                   33632:      * @access public
                   33633:      */
                   33634:     function addAutoload($method, $classname = null)
                   33635:     {
                   33636:         if (is_array($method)) {
                   33637:             array_walk($method, create_function('$a,&$b', '$b = strtolower($b);'));
                   33638:             $this->_autoload_map = array_merge($this->_autoload_map, $method);
                   33639:         } else {
                   33640:             $this->_autoload_map[strtolower($method)] = $classname;
                   33641:         }
                   33642:     }
                   33643: 
                   33644:     // }}}
                   33645:     // {{{ removeAutoload()
                   33646: 
                   33647:     /**
                   33648:      * Remove an autoload entry.
                   33649:      *
                   33650:      * @param string $method  which method to remove the autoload entry for
                   33651:      *
                   33652:      * @return bool TRUE if an entry was removed, FALSE if not
                   33653:      *
                   33654:      * @access public
                   33655:      */
                   33656:     function removeAutoload($method)
                   33657:     {
                   33658:         $method = strtolower($method);
                   33659:         $ok = isset($this->_autoload_map[$method]);
                   33660:         unset($this->_autoload_map[$method]);
                   33661:         return $ok;
                   33662:     }
                   33663: 
                   33664:     // }}}
                   33665:     // {{{ addAggregateObject()
                   33666: 
                   33667:     /**
                   33668:      * Add an aggregate object to this object.  If the specified class
                   33669:      * is not defined, loading it will be attempted following PEAR's
                   33670:      * file naming scheme.  All the methods in the class will be
                   33671:      * aggregated, except private ones (name starting with an
                   33672:      * underscore) and constructors.
                   33673:      *
                   33674:      * @param string $classname  what class to instantiate for the object.
                   33675:      *
                   33676:      * @return void
                   33677:      *
                   33678:      * @access public
                   33679:      */
                   33680:     function addAggregateObject($classname)
                   33681:     {
                   33682:         $classname = strtolower($classname);
                   33683:         if (!class_exists($classname)) {
                   33684:             $include_file = preg_replace('/[^a-z0-9]/i', '_', $classname);
                   33685:             include_once $include_file;
                   33686:         }
                   33687:         $obj =& new $classname;
                   33688:         $methods = get_class_methods($classname);
                   33689:         foreach ($methods as $method) {
                   33690:             // don't import priviate methods and constructors
                   33691:             if ($method{0} != '_' && $method != $classname) {
                   33692:                 $this->_method_map[$method] = $obj;
                   33693:             }
                   33694:         }
                   33695:     }
                   33696: 
                   33697:     // }}}
                   33698:     // {{{ removeAggregateObject()
                   33699: 
                   33700:     /**
                   33701:      * Remove an aggregate object.
                   33702:      *
                   33703:      * @param string $classname  the class of the object to remove
                   33704:      *
                   33705:      * @return bool  TRUE if an object was removed, FALSE if not
                   33706:      *
                   33707:      * @access public
                   33708:      */
                   33709:     function removeAggregateObject($classname)
                   33710:     {
                   33711:         $ok = false;
                   33712:         $classname = strtolower($classname);
                   33713:         reset($this->_method_map);
                   33714:         while (list($method, $obj) = each($this->_method_map)) {
                   33715:             if (is_a($obj, $classname)) {
                   33716:                 unset($this->_method_map[$method]);
                   33717:                 $ok = true;
                   33718:             }
                   33719:         }
                   33720:         return $ok;
                   33721:     }
                   33722: 
                   33723:     // }}}
                   33724:     // {{{ __call()
                   33725: 
                   33726:     /**
                   33727:      * Overloaded object call handler, called each time an
                   33728:      * undefined/aggregated method is invoked.  This method repeats
                   33729:      * the call in the right aggregate object and passes on the return
                   33730:      * value.
                   33731:      *
                   33732:      * @param string $method  which method that was called
                   33733:      *
                   33734:      * @param string $args    An array of the parameters passed in the
                   33735:      *                        original call
                   33736:      *
                   33737:      * @return mixed  The return value from the aggregated method, or a PEAR
                   33738:      *                error if the called method was unknown.
                   33739:      */
                   33740:     function __call($method, $args, &$retval)
                   33741:     {
                   33742:         $method = strtolower($method);
                   33743:         if (empty($this->_method_map[$method]) && isset($this->_autoload_map[$method])) {
                   33744:             $this->addAggregateObject($this->_autoload_map[$method]);
                   33745:         }
                   33746:         if (isset($this->_method_map[$method])) {
                   33747:             $retval = call_user_func_array(array($this->_method_map[$method], $method), $args);
                   33748:             return true;
                   33749:         }
                   33750:         return false;
                   33751:     }
                   33752: 
                   33753:     // }}}
                   33754: }
                   33755: 
                   33756: overload("PEAR_Autoloader");
                   33757: 
                   33758: ?>
1.1.1.2 ! misho    33759: PEAR-1.9.4/PEAR/Builder.php0000644000076500000240000004065411605156614014073 0ustar  helgistaff<?php
1.1       misho    33760: /**
                   33761:  * PEAR_Builder for building PHP extensions (PECL packages)
                   33762:  *
                   33763:  * PHP versions 4 and 5
                   33764:  *
                   33765:  * @category   pear
                   33766:  * @package    PEAR
                   33767:  * @author     Stig Bakken <ssb@php.net>
                   33768:  * @author     Greg Beaver <cellog@php.net>
                   33769:  * @copyright  1997-2009 The Authors
                   33770:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33771:  * @version    CVS: $Id: Builder.php 313024 2011-07-06 19:51:24Z dufuz $
                   33772:  * @link       http://pear.php.net/package/PEAR
                   33773:  * @since      File available since Release 0.1
                   33774:  *
                   33775:  * TODO: log output parameters in PECL command line
                   33776:  * TODO: msdev path in configuration
                   33777:  */
                   33778: 
                   33779: /**
                   33780:  * Needed for extending PEAR_Builder
                   33781:  */
                   33782: require_once 'PEAR/Common.php';
                   33783: require_once 'PEAR/PackageFile.php';
                   33784: 
                   33785: /**
                   33786:  * Class to handle building (compiling) extensions.
                   33787:  *
                   33788:  * @category   pear
                   33789:  * @package    PEAR
                   33790:  * @author     Stig Bakken <ssb@php.net>
                   33791:  * @author     Greg Beaver <cellog@php.net>
                   33792:  * @copyright  1997-2009 The Authors
                   33793:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   33794:  * @version    Release: 1.9.4
                   33795:  * @link       http://pear.php.net/package/PEAR
                   33796:  * @since      Class available since PHP 4.0.2
                   33797:  * @see        http://pear.php.net/manual/en/core.ppm.pear-builder.php
                   33798:  */
                   33799: class PEAR_Builder extends PEAR_Common
                   33800: {
                   33801:     var $php_api_version = 0;
                   33802:     var $zend_module_api_no = 0;
                   33803:     var $zend_extension_api_no = 0;
                   33804: 
                   33805:     var $extensions_built = array();
                   33806: 
                   33807:     /**
                   33808:      * @var string Used for reporting when it is not possible to pass function
                   33809:      *             via extra parameter, e.g. log, msdevCallback
                   33810:      */
                   33811:     var $current_callback = null;
                   33812: 
                   33813:     // used for msdev builds
                   33814:     var $_lastline = null;
                   33815:     var $_firstline = null;
                   33816: 
                   33817:     /**
                   33818:      * PEAR_Builder constructor.
                   33819:      *
                   33820:      * @param object $ui user interface object (instance of PEAR_Frontend_*)
                   33821:      *
                   33822:      * @access public
                   33823:      */
                   33824:     function PEAR_Builder(&$ui)
                   33825:     {
                   33826:         parent::PEAR_Common();
                   33827:         $this->setFrontendObject($ui);
                   33828:     }
                   33829: 
                   33830:     /**
                   33831:      * Build an extension from source on windows.
                   33832:      * requires msdev
                   33833:      */
                   33834:     function _build_win32($descfile, $callback = null)
                   33835:     {
                   33836:         if (is_object($descfile)) {
                   33837:             $pkg = $descfile;
                   33838:             $descfile = $pkg->getPackageFile();
                   33839:         } else {
                   33840:             $pf = &new PEAR_PackageFile($this->config, $this->debug);
                   33841:             $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
                   33842:             if (PEAR::isError($pkg)) {
                   33843:                 return $pkg;
                   33844:             }
                   33845:         }
                   33846:         $dir = dirname($descfile);
                   33847:         $old_cwd = getcwd();
                   33848: 
                   33849:         if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) {
                   33850:             return $this->raiseError("could not chdir to $dir");
                   33851:         }
                   33852: 
                   33853:         // packages that were in a .tar have the packagefile in this directory
                   33854:         $vdir = $pkg->getPackage() . '-' . $pkg->getVersion();
                   33855:         if (file_exists($dir) && is_dir($vdir)) {
                   33856:             if (!chdir($vdir)) {
                   33857:                 return $this->raiseError("could not chdir to " . realpath($vdir));
                   33858:             }
                   33859: 
                   33860:             $dir = getcwd();
                   33861:         }
                   33862: 
                   33863:         $this->log(2, "building in $dir");
                   33864: 
                   33865:         $dsp = $pkg->getPackage().'.dsp';
                   33866:         if (!file_exists("$dir/$dsp")) {
                   33867:             return $this->raiseError("The DSP $dsp does not exist.");
                   33868:         }
                   33869:         // XXX TODO: make release build type configurable
                   33870:         $command = 'msdev '.$dsp.' /MAKE "'.$pkg->getPackage(). ' - Release"';
                   33871: 
                   33872:         $err = $this->_runCommand($command, array(&$this, 'msdevCallback'));
                   33873:         if (PEAR::isError($err)) {
                   33874:             return $err;
                   33875:         }
                   33876: 
                   33877:         // figure out the build platform and type
                   33878:         $platform = 'Win32';
                   33879:         $buildtype = 'Release';
                   33880:         if (preg_match('/.*?'.$pkg->getPackage().'\s-\s(\w+)\s(.*?)-+/i',$this->_firstline,$matches)) {
                   33881:             $platform = $matches[1];
                   33882:             $buildtype = $matches[2];
                   33883:         }
                   33884: 
                   33885:         if (preg_match('/(.*)?\s-\s(\d+).*?(\d+)/', $this->_lastline, $matches)) {
                   33886:             if ($matches[2]) {
                   33887:                 // there were errors in the build
                   33888:                 return $this->raiseError("There were errors during compilation.");
                   33889:             }
                   33890:             $out = $matches[1];
                   33891:         } else {
                   33892:             return $this->raiseError("Did not understand the completion status returned from msdev.exe.");
                   33893:         }
                   33894: 
                   33895:         // msdev doesn't tell us the output directory :/
                   33896:         // open the dsp, find /out and use that directory
                   33897:         $dsptext = join(file($dsp),'');
                   33898: 
                   33899:         // this regex depends on the build platform and type having been
                   33900:         // correctly identified above.
                   33901:         $regex ='/.*?!IF\s+"\$\(CFG\)"\s+==\s+("'.
                   33902:                     $pkg->getPackage().'\s-\s'.
                   33903:                     $platform.'\s'.
                   33904:                     $buildtype.'").*?'.
                   33905:                     '\/out:"(.*?)"/is';
                   33906: 
                   33907:         if ($dsptext && preg_match($regex, $dsptext, $matches)) {
                   33908:             // what we get back is a relative path to the output file itself.
                   33909:             $outfile = realpath($matches[2]);
                   33910:         } else {
                   33911:             return $this->raiseError("Could not retrieve output information from $dsp.");
                   33912:         }
                   33913:         // realpath returns false if the file doesn't exist
                   33914:         if ($outfile && copy($outfile, "$dir/$out")) {
                   33915:             $outfile = "$dir/$out";
                   33916:         }
                   33917: 
                   33918:         $built_files[] = array(
                   33919:             'file' => "$outfile",
                   33920:             'php_api' => $this->php_api_version,
                   33921:             'zend_mod_api' => $this->zend_module_api_no,
                   33922:             'zend_ext_api' => $this->zend_extension_api_no,
                   33923:             );
                   33924: 
                   33925:         return $built_files;
                   33926:     }
                   33927:     // }}}
                   33928: 
                   33929:     // {{{ msdevCallback()
                   33930:     function msdevCallback($what, $data)
                   33931:     {
                   33932:         if (!$this->_firstline)
                   33933:             $this->_firstline = $data;
                   33934:         $this->_lastline = $data;
                   33935:         call_user_func($this->current_callback, $what, $data);
                   33936:     }
                   33937: 
                   33938:     /**
                   33939:      * @param string
                   33940:      * @param string
                   33941:      * @param array
                   33942:      * @access private
                   33943:      */
                   33944:     function _harvestInstDir($dest_prefix, $dirname, &$built_files)
                   33945:     {
                   33946:         $d = opendir($dirname);
                   33947:         if (!$d)
                   33948:             return false;
                   33949: 
                   33950:         $ret = true;
                   33951:         while (($ent = readdir($d)) !== false) {
                   33952:             if ($ent{0} == '.')
                   33953:                 continue;
                   33954: 
                   33955:             $full = $dirname . DIRECTORY_SEPARATOR . $ent;
                   33956:             if (is_dir($full)) {
                   33957:                 if (!$this->_harvestInstDir(
                   33958:                         $dest_prefix . DIRECTORY_SEPARATOR . $ent,
                   33959:                         $full, $built_files)) {
                   33960:                     $ret = false;
                   33961:                     break;
                   33962:                 }
                   33963:             } else {
                   33964:                 $dest = $dest_prefix . DIRECTORY_SEPARATOR . $ent;
                   33965:                 $built_files[] = array(
                   33966:                         'file' => $full,
                   33967:                         'dest' => $dest,
                   33968:                         'php_api' => $this->php_api_version,
                   33969:                         'zend_mod_api' => $this->zend_module_api_no,
                   33970:                         'zend_ext_api' => $this->zend_extension_api_no,
                   33971:                         );
                   33972:             }
                   33973:         }
                   33974:         closedir($d);
                   33975:         return $ret;
                   33976:     }
                   33977: 
                   33978:     /**
                   33979:      * Build an extension from source.  Runs "phpize" in the source
                   33980:      * directory, but compiles in a temporary directory
                   33981:      * (TMPDIR/pear-build-USER/PACKAGE-VERSION).
                   33982:      *
                   33983:      * @param string|PEAR_PackageFile_v* $descfile path to XML package description file, or
                   33984:      *               a PEAR_PackageFile object
                   33985:      *
                   33986:      * @param mixed $callback callback function used to report output,
                   33987:      * see PEAR_Builder::_runCommand for details
                   33988:      *
                   33989:      * @return array an array of associative arrays with built files,
                   33990:      * format:
                   33991:      * array( array( 'file' => '/path/to/ext.so',
                   33992:      *               'php_api' => YYYYMMDD,
                   33993:      *               'zend_mod_api' => YYYYMMDD,
                   33994:      *               'zend_ext_api' => YYYYMMDD ),
                   33995:      *        ... )
                   33996:      *
                   33997:      * @access public
                   33998:      *
                   33999:      * @see PEAR_Builder::_runCommand
                   34000:      */
                   34001:     function build($descfile, $callback = null)
                   34002:     {
                   34003:         if (preg_match('/(\\/|\\\\|^)([^\\/\\\\]+)?php(.+)?$/',
                   34004:                        $this->config->get('php_bin'), $matches)) {
                   34005:             if (isset($matches[2]) && strlen($matches[2]) &&
                   34006:                 trim($matches[2]) != trim($this->config->get('php_prefix'))) {
                   34007:                 $this->log(0, 'WARNING: php_bin ' . $this->config->get('php_bin') .
                   34008:                            ' appears to have a prefix ' . $matches[2] . ', but' .
                   34009:                            ' config variable php_prefix does not match');
                   34010:             }
                   34011: 
                   34012:             if (isset($matches[3]) && strlen($matches[3]) &&
                   34013:                 trim($matches[3]) != trim($this->config->get('php_suffix'))) {
                   34014:                 $this->log(0, 'WARNING: php_bin ' . $this->config->get('php_bin') .
                   34015:                            ' appears to have a suffix ' . $matches[3] . ', but' .
                   34016:                            ' config variable php_suffix does not match');
                   34017:             }
                   34018:         }
                   34019: 
                   34020:         $this->current_callback = $callback;
                   34021:         if (PEAR_OS == "Windows") {
                   34022:             return $this->_build_win32($descfile, $callback);
                   34023:         }
                   34024: 
                   34025:         if (PEAR_OS != 'Unix') {
                   34026:             return $this->raiseError("building extensions not supported on this platform");
                   34027:         }
                   34028: 
                   34029:         if (is_object($descfile)) {
                   34030:             $pkg = $descfile;
                   34031:             $descfile = $pkg->getPackageFile();
                   34032:             if (is_a($pkg, 'PEAR_PackageFile_v1')) {
                   34033:                 $dir = dirname($descfile);
                   34034:             } else {
                   34035:                 $dir = $pkg->_config->get('temp_dir') . '/' . $pkg->getName();
                   34036:                 // automatically delete at session end
                   34037:                 $this->addTempFile($dir);
                   34038:             }
                   34039:         } else {
                   34040:             $pf = &new PEAR_PackageFile($this->config);
                   34041:             $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
                   34042:             if (PEAR::isError($pkg)) {
                   34043:                 return $pkg;
                   34044:             }
                   34045:             $dir = dirname($descfile);
                   34046:         }
                   34047: 
                   34048:         // Find config. outside of normal path - e.g. config.m4
                   34049:         foreach (array_keys($pkg->getInstallationFileList()) as $item) {
                   34050:           if (stristr(basename($item), 'config.m4') && dirname($item) != '.') {
                   34051:             $dir .= DIRECTORY_SEPARATOR . dirname($item);
                   34052:             break;
                   34053:           }
                   34054:         }
                   34055: 
                   34056:         $old_cwd = getcwd();
                   34057:         if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) {
                   34058:             return $this->raiseError("could not chdir to $dir");
                   34059:         }
                   34060: 
                   34061:         $vdir = $pkg->getPackage() . '-' . $pkg->getVersion();
                   34062:         if (is_dir($vdir)) {
                   34063:             chdir($vdir);
                   34064:         }
                   34065: 
                   34066:         $dir = getcwd();
                   34067:         $this->log(2, "building in $dir");
                   34068:         putenv('PATH=' . $this->config->get('bin_dir') . ':' . getenv('PATH'));
                   34069:         $err = $this->_runCommand($this->config->get('php_prefix')
                   34070:                                 . "phpize" .
                   34071:                                 $this->config->get('php_suffix'),
                   34072:                                 array(&$this, 'phpizeCallback'));
                   34073:         if (PEAR::isError($err)) {
                   34074:             return $err;
                   34075:         }
                   34076: 
                   34077:         if (!$err) {
                   34078:             return $this->raiseError("`phpize' failed");
                   34079:         }
                   34080: 
                   34081:         // {{{ start of interactive part
                   34082:         $configure_command = "$dir/configure";
                   34083:         $configure_options = $pkg->getConfigureOptions();
                   34084:         if ($configure_options) {
                   34085:             foreach ($configure_options as $o) {
                   34086:                 $default = array_key_exists('default', $o) ? $o['default'] : null;
                   34087:                 list($r) = $this->ui->userDialog('build',
                   34088:                                                  array($o['prompt']),
                   34089:                                                  array('text'),
                   34090:                                                  array($default));
                   34091:                 if (substr($o['name'], 0, 5) == 'with-' &&
                   34092:                     ($r == 'yes' || $r == 'autodetect')) {
                   34093:                     $configure_command .= " --$o[name]";
                   34094:                 } else {
                   34095:                     $configure_command .= " --$o[name]=".trim($r);
                   34096:                 }
                   34097:             }
                   34098:         }
                   34099:         // }}} end of interactive part
                   34100: 
                   34101:         // FIXME make configurable
                   34102:         if (!$user=getenv('USER')) {
                   34103:             $user='defaultuser';
                   34104:         }
                   34105: 
                   34106:         $tmpdir = $this->config->get('temp_dir');
                   34107:         $build_basedir = System::mktemp(' -t "' . $tmpdir . '" -d "pear-build-' . $user . '"');
                   34108:         $build_dir = "$build_basedir/$vdir";
                   34109:         $inst_dir = "$build_basedir/install-$vdir";
                   34110:         $this->log(1, "building in $build_dir");
                   34111:         if (is_dir($build_dir)) {
                   34112:             System::rm(array('-rf', $build_dir));
                   34113:         }
                   34114: 
                   34115:         if (!System::mkDir(array('-p', $build_dir))) {
                   34116:             return $this->raiseError("could not create build dir: $build_dir");
                   34117:         }
                   34118: 
                   34119:         $this->addTempFile($build_dir);
                   34120:         if (!System::mkDir(array('-p', $inst_dir))) {
                   34121:             return $this->raiseError("could not create temporary install dir: $inst_dir");
                   34122:         }
                   34123:         $this->addTempFile($inst_dir);
                   34124: 
                   34125:         $make_command = getenv('MAKE') ? getenv('MAKE') : 'make';
                   34126: 
                   34127:         $to_run = array(
                   34128:             $configure_command,
                   34129:             $make_command,
                   34130:             "$make_command INSTALL_ROOT=\"$inst_dir\" install",
                   34131:             "find \"$inst_dir\" | xargs ls -dils"
                   34132:             );
                   34133:         if (!file_exists($build_dir) || !is_dir($build_dir) || !chdir($build_dir)) {
                   34134:             return $this->raiseError("could not chdir to $build_dir");
                   34135:         }
                   34136:         putenv('PHP_PEAR_VERSION=1.9.4');
                   34137:         foreach ($to_run as $cmd) {
                   34138:             $err = $this->_runCommand($cmd, $callback);
                   34139:             if (PEAR::isError($err)) {
                   34140:                 chdir($old_cwd);
                   34141:                 return $err;
                   34142:             }
                   34143:             if (!$err) {
                   34144:                 chdir($old_cwd);
                   34145:                 return $this->raiseError("`$cmd' failed");
                   34146:             }
                   34147:         }
                   34148:         if (!($dp = opendir("modules"))) {
                   34149:             chdir($old_cwd);
                   34150:             return $this->raiseError("no `modules' directory found");
                   34151:         }
                   34152:         $built_files = array();
                   34153:         $prefix = exec($this->config->get('php_prefix')
                   34154:                         . "php-config" .
                   34155:                        $this->config->get('php_suffix') . " --prefix");
                   34156:         $this->_harvestInstDir($prefix, $inst_dir . DIRECTORY_SEPARATOR . $prefix, $built_files);
                   34157:         chdir($old_cwd);
                   34158:         return $built_files;
                   34159:     }
                   34160: 
                   34161:     /**
                   34162:      * Message callback function used when running the "phpize"
                   34163:      * program.  Extracts the API numbers used.  Ignores other message
                   34164:      * types than "cmdoutput".
                   34165:      *
                   34166:      * @param string $what the type of message
                   34167:      * @param mixed $data the message
                   34168:      *
                   34169:      * @return void
                   34170:      *
                   34171:      * @access public
                   34172:      */
                   34173:     function phpizeCallback($what, $data)
                   34174:     {
                   34175:         if ($what != 'cmdoutput') {
                   34176:             return;
                   34177:         }
                   34178:         $this->log(1, rtrim($data));
                   34179:         if (preg_match('/You should update your .aclocal.m4/', $data)) {
                   34180:             return;
                   34181:         }
                   34182:         $matches = array();
                   34183:         if (preg_match('/^\s+(\S[^:]+):\s+(\d{8})/', $data, $matches)) {
                   34184:             $member = preg_replace('/[^a-z]/', '_', strtolower($matches[1]));
                   34185:             $apino = (int)$matches[2];
                   34186:             if (isset($this->$member)) {
                   34187:                 $this->$member = $apino;
                   34188:                 //$msg = sprintf("%-22s : %d", $matches[1], $apino);
                   34189:                 //$this->log(1, $msg);
                   34190:             }
                   34191:         }
                   34192:     }
                   34193: 
                   34194:     /**
                   34195:      * Run an external command, using a message callback to report
                   34196:      * output.  The command will be run through popen and output is
                   34197:      * reported for every line with a "cmdoutput" message with the
                   34198:      * line string, including newlines, as payload.
                   34199:      *
                   34200:      * @param string $command the command to run
                   34201:      *
                   34202:      * @param mixed $callback (optional) function to use as message
                   34203:      * callback
                   34204:      *
                   34205:      * @return bool whether the command was successful (exit code 0
                   34206:      * means success, any other means failure)
                   34207:      *
                   34208:      * @access private
                   34209:      */
                   34210:     function _runCommand($command, $callback = null)
                   34211:     {
                   34212:         $this->log(1, "running: $command");
                   34213:         $pp = popen("$command 2>&1", "r");
                   34214:         if (!$pp) {
                   34215:             return $this->raiseError("failed to run `$command'");
                   34216:         }
                   34217:         if ($callback && $callback[0]->debug == 1) {
                   34218:             $olddbg = $callback[0]->debug;
                   34219:             $callback[0]->debug = 2;
                   34220:         }
                   34221: 
                   34222:         while ($line = fgets($pp, 1024)) {
                   34223:             if ($callback) {
                   34224:                 call_user_func($callback, 'cmdoutput', $line);
                   34225:             } else {
                   34226:                 $this->log(2, rtrim($line));
                   34227:             }
                   34228:         }
                   34229:         if ($callback && isset($olddbg)) {
                   34230:             $callback[0]->debug = $olddbg;
                   34231:         }
                   34232: 
                   34233:         $exitcode = is_resource($pp) ? pclose($pp) : -1;
                   34234:         return ($exitcode == 0);
                   34235:     }
                   34236: 
                   34237:     function log($level, $msg)
                   34238:     {
                   34239:         if ($this->current_callback) {
                   34240:             if ($this->debug >= $level) {
                   34241:                 call_user_func($this->current_callback, 'output', $msg);
                   34242:             }
                   34243:             return;
                   34244:         }
                   34245:         return PEAR_Common::log($level, $msg);
                   34246:     }
1.1.1.2 ! misho    34247: }PEAR-1.9.4/PEAR/ChannelFile.php0000644000076500000240000014335311605156614014655 0ustar  helgistaff<?php
1.1       misho    34248: /**
                   34249:  * PEAR_ChannelFile, the channel handling class
                   34250:  *
                   34251:  * PHP versions 4 and 5
                   34252:  *
                   34253:  * @category   pear
                   34254:  * @package    PEAR
                   34255:  * @author     Greg Beaver <cellog@php.net>
                   34256:  * @copyright  1997-2009 The Authors
                   34257:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   34258:  * @version    CVS: $Id: ChannelFile.php 313023 2011-07-06 19:17:11Z dufuz $
                   34259:  * @link       http://pear.php.net/package/PEAR
                   34260:  * @since      File available since Release 1.4.0a1
                   34261:  */
                   34262: 
                   34263: /**
                   34264:  * Needed for error handling
                   34265:  */
                   34266: require_once 'PEAR/ErrorStack.php';
                   34267: require_once 'PEAR/XMLParser.php';
                   34268: require_once 'PEAR/Common.php';
                   34269: 
                   34270: /**
                   34271:  * Error code if the channel.xml <channel> tag does not contain a valid version
                   34272:  */
                   34273: define('PEAR_CHANNELFILE_ERROR_NO_VERSION', 1);
                   34274: /**
                   34275:  * Error code if the channel.xml <channel> tag version is not supported (version 1.0 is the only supported version,
                   34276:  * currently
                   34277:  */
                   34278: define('PEAR_CHANNELFILE_ERROR_INVALID_VERSION', 2);
                   34279: 
                   34280: /**
                   34281:  * Error code if parsing is attempted with no xml extension
                   34282:  */
                   34283: define('PEAR_CHANNELFILE_ERROR_NO_XML_EXT', 3);
                   34284: 
                   34285: /**
                   34286:  * Error code if creating the xml parser resource fails
                   34287:  */
                   34288: define('PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER', 4);
                   34289: 
                   34290: /**
                   34291:  * Error code used for all sax xml parsing errors
                   34292:  */
                   34293: define('PEAR_CHANNELFILE_ERROR_PARSER_ERROR', 5);
                   34294: 
                   34295: /**#@+
                   34296:  * Validation errors
                   34297:  */
                   34298: /**
                   34299:  * Error code when channel name is missing
                   34300:  */
                   34301: define('PEAR_CHANNELFILE_ERROR_NO_NAME', 6);
                   34302: /**
                   34303:  * Error code when channel name is invalid
                   34304:  */
                   34305: define('PEAR_CHANNELFILE_ERROR_INVALID_NAME', 7);
                   34306: /**
                   34307:  * Error code when channel summary is missing
                   34308:  */
                   34309: define('PEAR_CHANNELFILE_ERROR_NO_SUMMARY', 8);
                   34310: /**
                   34311:  * Error code when channel summary is multi-line
                   34312:  */
                   34313: define('PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY', 9);
                   34314: /**
                   34315:  * Error code when channel server is missing for protocol
                   34316:  */
                   34317: define('PEAR_CHANNELFILE_ERROR_NO_HOST', 10);
                   34318: /**
                   34319:  * Error code when channel server is invalid for protocol
                   34320:  */
                   34321: define('PEAR_CHANNELFILE_ERROR_INVALID_HOST', 11);
                   34322: /**
                   34323:  * Error code when a mirror name is invalid
                   34324:  */
                   34325: define('PEAR_CHANNELFILE_ERROR_INVALID_MIRROR', 21);
                   34326: /**
                   34327:  * Error code when a mirror type is invalid
                   34328:  */
                   34329: define('PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE', 22);
                   34330: /**
                   34331:  * Error code when an attempt is made to generate xml, but the parsed content is invalid
                   34332:  */
                   34333: define('PEAR_CHANNELFILE_ERROR_INVALID', 23);
                   34334: /**
                   34335:  * Error code when an empty package name validate regex is passed in
                   34336:  */
                   34337: define('PEAR_CHANNELFILE_ERROR_EMPTY_REGEX', 24);
                   34338: /**
                   34339:  * Error code when a <function> tag has no version
                   34340:  */
                   34341: define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION', 25);
                   34342: /**
                   34343:  * Error code when a <function> tag has no name
                   34344:  */
                   34345: define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME', 26);
                   34346: /**
                   34347:  * Error code when a <validatepackage> tag has no name
                   34348:  */
                   34349: define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME', 27);
                   34350: /**
                   34351:  * Error code when a <validatepackage> tag has no version attribute
                   34352:  */
                   34353: define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION', 28);
                   34354: /**
                   34355:  * Error code when a mirror does not exist but is called for in one of the set*
                   34356:  * methods.
                   34357:  */
                   34358: define('PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND', 32);
                   34359: /**
                   34360:  * Error code when a server port is not numeric
                   34361:  */
                   34362: define('PEAR_CHANNELFILE_ERROR_INVALID_PORT', 33);
                   34363: /**
                   34364:  * Error code when <static> contains no version attribute
                   34365:  */
                   34366: define('PEAR_CHANNELFILE_ERROR_NO_STATICVERSION', 34);
                   34367: /**
                   34368:  * Error code when <baseurl> contains no type attribute in a <rest> protocol definition
                   34369:  */
                   34370: define('PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE', 35);
                   34371: /**
                   34372:  * Error code when a mirror is defined and the channel.xml represents the __uri pseudo-channel
                   34373:  */
                   34374: define('PEAR_CHANNELFILE_URI_CANT_MIRROR', 36);
                   34375: /**
                   34376:  * Error code when ssl attribute is present and is not "yes"
                   34377:  */
                   34378: define('PEAR_CHANNELFILE_ERROR_INVALID_SSL', 37);
                   34379: /**#@-*/
                   34380: 
                   34381: /**
                   34382:  * Mirror types allowed.  Currently only internet servers are recognized.
                   34383:  */
                   34384: $GLOBALS['_PEAR_CHANNELS_MIRROR_TYPES'] =  array('server');
                   34385: 
                   34386: 
                   34387: /**
                   34388:  * The Channel handling class
                   34389:  *
                   34390:  * @category   pear
                   34391:  * @package    PEAR
                   34392:  * @author     Greg Beaver <cellog@php.net>
                   34393:  * @copyright  1997-2009 The Authors
                   34394:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   34395:  * @version    Release: 1.9.4
                   34396:  * @link       http://pear.php.net/package/PEAR
                   34397:  * @since      Class available since Release 1.4.0a1
                   34398:  */
                   34399: class PEAR_ChannelFile
                   34400: {
                   34401:     /**
                   34402:      * @access private
                   34403:      * @var PEAR_ErrorStack
                   34404:      * @access private
                   34405:      */
                   34406:     var $_stack;
                   34407: 
                   34408:     /**
                   34409:      * Supported channel.xml versions, for parsing
                   34410:      * @var array
                   34411:      * @access private
                   34412:      */
                   34413:     var $_supportedVersions = array('1.0');
                   34414: 
                   34415:     /**
                   34416:      * Parsed channel information
                   34417:      * @var array
                   34418:      * @access private
                   34419:      */
                   34420:     var $_channelInfo;
                   34421: 
                   34422:     /**
                   34423:      * index into the subchannels array, used for parsing xml
                   34424:      * @var int
                   34425:      * @access private
                   34426:      */
                   34427:     var $_subchannelIndex;
                   34428: 
                   34429:     /**
                   34430:      * index into the mirrors array, used for parsing xml
                   34431:      * @var int
                   34432:      * @access private
                   34433:      */
                   34434:     var $_mirrorIndex;
                   34435: 
                   34436:     /**
                   34437:      * Flag used to determine the validity of parsed content
                   34438:      * @var boolean
                   34439:      * @access private
                   34440:      */
                   34441:     var $_isValid = false;
                   34442: 
                   34443:     function PEAR_ChannelFile()
                   34444:     {
                   34445:         $this->_stack = &new PEAR_ErrorStack('PEAR_ChannelFile');
                   34446:         $this->_stack->setErrorMessageTemplate($this->_getErrorMessage());
                   34447:         $this->_isValid = false;
                   34448:     }
                   34449: 
                   34450:     /**
                   34451:      * @return array
                   34452:      * @access protected
                   34453:      */
                   34454:     function _getErrorMessage()
                   34455:     {
                   34456:         return
                   34457:             array(
                   34458:                 PEAR_CHANNELFILE_ERROR_INVALID_VERSION =>
                   34459:                     'While parsing channel.xml, an invalid version number "%version% was passed in, expecting one of %versions%',
                   34460:                 PEAR_CHANNELFILE_ERROR_NO_VERSION =>
                   34461:                     'No version number found in <channel> tag',
                   34462:                 PEAR_CHANNELFILE_ERROR_NO_XML_EXT =>
                   34463:                     '%error%',
                   34464:                 PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER =>
                   34465:                     'Unable to create XML parser',
                   34466:                 PEAR_CHANNELFILE_ERROR_PARSER_ERROR =>
                   34467:                     '%error%',
                   34468:                 PEAR_CHANNELFILE_ERROR_NO_NAME =>
                   34469:                     'Missing channel name',
                   34470:                 PEAR_CHANNELFILE_ERROR_INVALID_NAME =>
                   34471:                     'Invalid channel %tag% "%name%"',
                   34472:                 PEAR_CHANNELFILE_ERROR_NO_SUMMARY =>
                   34473:                     'Missing channel summary',
                   34474:                 PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY =>
                   34475:                     'Channel summary should be on one line, but is multi-line',
                   34476:                 PEAR_CHANNELFILE_ERROR_NO_HOST =>
                   34477:                     'Missing channel server for %type% server',
                   34478:                 PEAR_CHANNELFILE_ERROR_INVALID_HOST =>
                   34479:                     'Server name "%server%" is invalid for %type% server',
                   34480:                 PEAR_CHANNELFILE_ERROR_INVALID_MIRROR =>
                   34481:                     'Invalid mirror name "%name%", mirror type %type%',
                   34482:                 PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE =>
                   34483:                     'Invalid mirror type "%type%"',
                   34484:                 PEAR_CHANNELFILE_ERROR_INVALID =>
                   34485:                     'Cannot generate xml, contents are invalid',
                   34486:                 PEAR_CHANNELFILE_ERROR_EMPTY_REGEX =>
                   34487:                     'packagenameregex cannot be empty',
                   34488:                 PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION =>
                   34489:                     '%parent% %protocol% function has no version',
                   34490:                 PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME =>
                   34491:                     '%parent% %protocol% function has no name',
                   34492:                 PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE =>
                   34493:                     '%parent% rest baseurl has no type',
                   34494:                 PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME =>
                   34495:                     'Validation package has no name in <validatepackage> tag',
                   34496:                 PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION =>
                   34497:                     'Validation package "%package%" has no version',
                   34498:                 PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND =>
                   34499:                     'Mirror "%mirror%" does not exist',
                   34500:                 PEAR_CHANNELFILE_ERROR_INVALID_PORT =>
                   34501:                     'Port "%port%" must be numeric',
                   34502:                 PEAR_CHANNELFILE_ERROR_NO_STATICVERSION =>
                   34503:                     '<static> tag must contain version attribute',
                   34504:                 PEAR_CHANNELFILE_URI_CANT_MIRROR =>
                   34505:                     'The __uri pseudo-channel cannot have mirrors',
                   34506:                 PEAR_CHANNELFILE_ERROR_INVALID_SSL =>
                   34507:                     '%server% has invalid ssl attribute "%ssl%" can only be yes or not present',
                   34508:             );
                   34509:     }
                   34510: 
                   34511:     /**
                   34512:      * @param string contents of package.xml file
                   34513:      * @return bool success of parsing
                   34514:      */
                   34515:     function fromXmlString($data)
                   34516:     {
                   34517:         if (preg_match('/<channel\s+version="([0-9]+\.[0-9]+)"/', $data, $channelversion)) {
                   34518:             if (!in_array($channelversion[1], $this->_supportedVersions)) {
                   34519:                 $this->_stack->push(PEAR_CHANNELFILE_ERROR_INVALID_VERSION, 'error',
                   34520:                     array('version' => $channelversion[1]));
                   34521:                 return false;
                   34522:             }
                   34523:             $parser = new PEAR_XMLParser;
                   34524:             $result = $parser->parse($data);
                   34525:             if ($result !== true) {
                   34526:                 if ($result->getCode() == 1) {
                   34527:                     $this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_XML_EXT, 'error',
                   34528:                         array('error' => $result->getMessage()));
                   34529:                 } else {
                   34530:                     $this->_stack->push(PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER, 'error');
                   34531:                 }
                   34532:                 return false;
                   34533:             }
                   34534:             $this->_channelInfo = $parser->getData();
                   34535:             return true;
                   34536:         } else {
                   34537:             $this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_VERSION, 'error', array('xml' => $data));
                   34538:             return false;
                   34539:         }
                   34540:     }
                   34541: 
                   34542:     /**
                   34543:      * @return array
                   34544:      */
                   34545:     function toArray()
                   34546:     {
                   34547:         if (!$this->_isValid && !$this->validate()) {
                   34548:             return false;
                   34549:         }
                   34550:         return $this->_channelInfo;
                   34551:     }
                   34552: 
                   34553:     /**
                   34554:      * @param array
                   34555:      * @static
                   34556:      * @return PEAR_ChannelFile|false false if invalid
                   34557:      */
                   34558:     function &fromArray($data, $compatibility = false, $stackClass = 'PEAR_ErrorStack')
                   34559:     {
                   34560:         $a = new PEAR_ChannelFile($compatibility, $stackClass);
                   34561:         $a->_fromArray($data);
                   34562:         if (!$a->validate()) {
                   34563:             $a = false;
                   34564:             return $a;
                   34565:         }
                   34566:         return $a;
                   34567:     }
                   34568: 
                   34569:     /**
                   34570:      * Unlike {@link fromArray()} this does not do any validation
                   34571:      * @param array
                   34572:      * @static
                   34573:      * @return PEAR_ChannelFile
                   34574:      */
                   34575:     function &fromArrayWithErrors($data, $compatibility = false,
                   34576:                                   $stackClass = 'PEAR_ErrorStack')
                   34577:     {
                   34578:         $a = new PEAR_ChannelFile($compatibility, $stackClass);
                   34579:         $a->_fromArray($data);
                   34580:         return $a;
                   34581:     }
                   34582: 
                   34583:     /**
                   34584:      * @param array
                   34585:      * @access private
                   34586:      */
                   34587:     function _fromArray($data)
                   34588:     {
                   34589:         $this->_channelInfo = $data;
                   34590:     }
                   34591: 
                   34592:     /**
                   34593:      * Wrapper to {@link PEAR_ErrorStack::getErrors()}
                   34594:      * @param boolean determines whether to purge the error stack after retrieving
                   34595:      * @return array
                   34596:      */
                   34597:     function getErrors($purge = false)
                   34598:     {
                   34599:         return $this->_stack->getErrors($purge);
                   34600:     }
                   34601: 
                   34602:     /**
                   34603:      * Unindent given string (?)
                   34604:      *
                   34605:      * @param string $str The string that has to be unindented.
                   34606:      * @return string
                   34607:      * @access private
                   34608:      */
                   34609:     function _unIndent($str)
                   34610:     {
                   34611:         // remove leading newlines
                   34612:         $str = preg_replace('/^[\r\n]+/', '', $str);
                   34613:         // find whitespace at the beginning of the first line
                   34614:         $indent_len = strspn($str, " \t");
                   34615:         $indent = substr($str, 0, $indent_len);
                   34616:         $data = '';
                   34617:         // remove the same amount of whitespace from following lines
                   34618:         foreach (explode("\n", $str) as $line) {
                   34619:             if (substr($line, 0, $indent_len) == $indent) {
                   34620:                 $data .= substr($line, $indent_len) . "\n";
                   34621:             }
                   34622:         }
                   34623:         return $data;
                   34624:     }
                   34625: 
                   34626:     /**
                   34627:      * Parse a channel.xml file.  Expects the name of
                   34628:      * a channel xml file as input.
                   34629:      *
                   34630:      * @param string  $descfile  name of channel xml file
                   34631:      * @return bool success of parsing
                   34632:      */
                   34633:     function fromXmlFile($descfile)
                   34634:     {
                   34635:         if (!file_exists($descfile) || !is_file($descfile) || !is_readable($descfile) ||
                   34636:              (!$fp = fopen($descfile, 'r'))) {
                   34637:             require_once 'PEAR.php';
                   34638:             return PEAR::raiseError("Unable to open $descfile");
                   34639:         }
                   34640: 
                   34641:         // read the whole thing so we only get one cdata callback
                   34642:         // for each block of cdata
                   34643:         fclose($fp);
                   34644:         $data = file_get_contents($descfile);
                   34645:         return $this->fromXmlString($data);
                   34646:     }
                   34647: 
                   34648:     /**
                   34649:      * Parse channel information from different sources
                   34650:      *
                   34651:      * This method is able to extract information about a channel
                   34652:      * from an .xml file or a string
                   34653:      *
                   34654:      * @access public
                   34655:      * @param  string Filename of the source or the source itself
                   34656:      * @return bool
                   34657:      */
                   34658:     function fromAny($info)
                   34659:     {
                   34660:         if (is_string($info) && file_exists($info) && strlen($info) < 255) {
                   34661:             $tmp = substr($info, -4);
                   34662:             if ($tmp == '.xml') {
                   34663:                 $info = $this->fromXmlFile($info);
                   34664:             } else {
                   34665:                 $fp = fopen($info, "r");
                   34666:                 $test = fread($fp, 5);
                   34667:                 fclose($fp);
                   34668:                 if ($test == "<?xml") {
                   34669:                     $info = $this->fromXmlFile($info);
                   34670:                 }
                   34671:             }
                   34672:             if (PEAR::isError($info)) {
                   34673:                 require_once 'PEAR.php';
                   34674:                 return PEAR::raiseError($info);
                   34675:             }
                   34676:         }
                   34677:         if (is_string($info)) {
                   34678:             $info = $this->fromXmlString($info);
                   34679:         }
                   34680:         return $info;
                   34681:     }
                   34682: 
                   34683:     /**
                   34684:      * Return an XML document based on previous parsing and modifications
                   34685:      *
                   34686:      * @return string XML data
                   34687:      *
                   34688:      * @access public
                   34689:      */
                   34690:     function toXml()
                   34691:     {
                   34692:         if (!$this->_isValid && !$this->validate()) {
                   34693:             $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID);
                   34694:             return false;
                   34695:         }
                   34696:         if (!isset($this->_channelInfo['attribs']['version'])) {
                   34697:             $this->_channelInfo['attribs']['version'] = '1.0';
                   34698:         }
                   34699:         $channelInfo = $this->_channelInfo;
                   34700:         $ret = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n";
                   34701:         $ret .= "<channel version=\"" .
                   34702:             $channelInfo['attribs']['version'] . "\" xmlns=\"http://pear.php.net/channel-1.0\"
                   34703:   xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
                   34704:   xsi:schemaLocation=\"http://pear.php.net/dtd/channel-"
                   34705:             . $channelInfo['attribs']['version'] . " http://pear.php.net/dtd/channel-" .
                   34706:             $channelInfo['attribs']['version'] . ".xsd\">
                   34707:  <name>$channelInfo[name]</name>
                   34708:  <summary>" . htmlspecialchars($channelInfo['summary'])."</summary>
                   34709: ";
                   34710:         if (isset($channelInfo['suggestedalias'])) {
                   34711:             $ret .= ' <suggestedalias>' . $channelInfo['suggestedalias'] . "</suggestedalias>\n";
                   34712:         }
                   34713:         if (isset($channelInfo['validatepackage'])) {
                   34714:             $ret .= ' <validatepackage version="' .
                   34715:                 $channelInfo['validatepackage']['attribs']['version']. '">' .
                   34716:                 htmlspecialchars($channelInfo['validatepackage']['_content']) .
                   34717:                 "</validatepackage>\n";
                   34718:         }
                   34719:         $ret .= " <servers>\n";
                   34720:         $ret .= '  <primary';
                   34721:         if (isset($channelInfo['servers']['primary']['attribs']['ssl'])) {
                   34722:             $ret .= ' ssl="' . $channelInfo['servers']['primary']['attribs']['ssl'] . '"';
                   34723:         }
                   34724:         if (isset($channelInfo['servers']['primary']['attribs']['port'])) {
                   34725:             $ret .= ' port="' . $channelInfo['servers']['primary']['attribs']['port'] . '"';
                   34726:         }
                   34727:         $ret .= ">\n";
                   34728:         if (isset($channelInfo['servers']['primary']['rest'])) {
                   34729:             $ret .= $this->_makeRestXml($channelInfo['servers']['primary']['rest'], '   ');
                   34730:         }
                   34731:         $ret .= "  </primary>\n";
                   34732:         if (isset($channelInfo['servers']['mirror'])) {
                   34733:             $ret .= $this->_makeMirrorsXml($channelInfo);
                   34734:         }
                   34735:         $ret .= " </servers>\n";
                   34736:         $ret .= "</channel>";
                   34737:         return str_replace("\r", "\n", str_replace("\r\n", "\n", $ret));
                   34738:     }
                   34739: 
                   34740:     /**
                   34741:      * Generate the <rest> tag
                   34742:      * @access private
                   34743:      */
                   34744:     function _makeRestXml($info, $indent)
                   34745:     {
                   34746:         $ret = $indent . "<rest>\n";
                   34747:         if (isset($info['baseurl']) && !isset($info['baseurl'][0])) {
                   34748:             $info['baseurl'] = array($info['baseurl']);
                   34749:         }
                   34750: 
                   34751:         if (isset($info['baseurl'])) {
                   34752:             foreach ($info['baseurl'] as $url) {
                   34753:                 $ret .= "$indent <baseurl type=\"" . $url['attribs']['type'] . "\"";
                   34754:                 $ret .= ">" . $url['_content'] . "</baseurl>\n";
                   34755:             }
                   34756:         }
                   34757:         $ret .= $indent . "</rest>\n";
                   34758:         return $ret;
                   34759:     }
                   34760: 
                   34761:     /**
                   34762:      * Generate the <mirrors> tag
                   34763:      * @access private
                   34764:      */
                   34765:     function _makeMirrorsXml($channelInfo)
                   34766:     {
                   34767:         $ret = "";
                   34768:         if (!isset($channelInfo['servers']['mirror'][0])) {
                   34769:             $channelInfo['servers']['mirror'] = array($channelInfo['servers']['mirror']);
                   34770:         }
                   34771:         foreach ($channelInfo['servers']['mirror'] as $mirror) {
                   34772:             $ret .= '  <mirror host="' . $mirror['attribs']['host'] . '"';
                   34773:             if (isset($mirror['attribs']['port'])) {
                   34774:                 $ret .= ' port="' . $mirror['attribs']['port'] . '"';
                   34775:             }
                   34776:             if (isset($mirror['attribs']['ssl'])) {
                   34777:                 $ret .= ' ssl="' . $mirror['attribs']['ssl'] . '"';
                   34778:             }
                   34779:             $ret .= ">\n";
                   34780:             if (isset($mirror['rest'])) {
                   34781:                 if (isset($mirror['rest'])) {
                   34782:                     $ret .= $this->_makeRestXml($mirror['rest'], '   ');
                   34783:                 }
                   34784:                 $ret .= "  </mirror>\n";
                   34785:             } else {
                   34786:                 $ret .= "/>\n";
                   34787:             }
                   34788:         }
                   34789:         return $ret;
                   34790:     }
                   34791: 
                   34792:     /**
                   34793:      * Generate the <functions> tag
                   34794:      * @access private
                   34795:      */
                   34796:     function _makeFunctionsXml($functions, $indent, $rest = false)
                   34797:     {
                   34798:         $ret = '';
                   34799:         if (!isset($functions[0])) {
                   34800:             $functions = array($functions);
                   34801:         }
                   34802:         foreach ($functions as $function) {
                   34803:             $ret .= "$indent<function version=\"" . $function['attribs']['version'] . "\"";
                   34804:             if ($rest) {
                   34805:                 $ret .= ' uri="' . $function['attribs']['uri'] . '"';
                   34806:             }
                   34807:             $ret .= ">" . $function['_content'] . "</function>\n";
                   34808:         }
                   34809:         return $ret;
                   34810:     }
                   34811: 
                   34812:     /**
                   34813:      * Validation error.  Also marks the object contents as invalid
                   34814:      * @param error code
                   34815:      * @param array error information
                   34816:      * @access private
                   34817:      */
                   34818:     function _validateError($code, $params = array())
                   34819:     {
                   34820:         $this->_stack->push($code, 'error', $params);
                   34821:         $this->_isValid = false;
                   34822:     }
                   34823: 
                   34824:     /**
                   34825:      * Validation warning.  Does not mark the object contents invalid.
                   34826:      * @param error code
                   34827:      * @param array error information
                   34828:      * @access private
                   34829:      */
                   34830:     function _validateWarning($code, $params = array())
                   34831:     {
                   34832:         $this->_stack->push($code, 'warning', $params);
                   34833:     }
                   34834: 
                   34835:     /**
                   34836:      * Validate parsed file.
                   34837:      *
                   34838:      * @access public
                   34839:      * @return boolean
                   34840:      */
                   34841:     function validate()
                   34842:     {
                   34843:         $this->_isValid = true;
                   34844:         $info = $this->_channelInfo;
                   34845:         if (empty($info['name'])) {
                   34846:             $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_NAME);
                   34847:         } elseif (!$this->validChannelServer($info['name'])) {
                   34848:             if ($info['name'] != '__uri') {
                   34849:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, array('tag' => 'name',
                   34850:                     'name' => $info['name']));
                   34851:             }
                   34852:         }
                   34853:         if (empty($info['summary'])) {
                   34854:             $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY);
                   34855:         } elseif (strpos(trim($info['summary']), "\n") !== false) {
                   34856:             $this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY,
                   34857:                 array('summary' => $info['summary']));
                   34858:         }
                   34859:         if (isset($info['suggestedalias'])) {
                   34860:             if (!$this->validChannelServer($info['suggestedalias'])) {
                   34861:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
                   34862:                     array('tag' => 'suggestedalias', 'name' =>$info['suggestedalias']));
                   34863:             }
                   34864:         }
                   34865:         if (isset($info['localalias'])) {
                   34866:             if (!$this->validChannelServer($info['localalias'])) {
                   34867:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
                   34868:                     array('tag' => 'localalias', 'name' =>$info['localalias']));
                   34869:             }
                   34870:         }
                   34871:         if (isset($info['validatepackage'])) {
                   34872:             if (!isset($info['validatepackage']['_content'])) {
                   34873:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME);
                   34874:             }
                   34875:             if (!isset($info['validatepackage']['attribs']['version'])) {
                   34876:                 $content = isset($info['validatepackage']['_content']) ?
                   34877:                     $info['validatepackage']['_content'] :
                   34878:                     null;
                   34879:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION,
                   34880:                     array('package' => $content));
                   34881:             }
                   34882:         }
                   34883: 
                   34884:         if (isset($info['servers']['primary']['attribs'], $info['servers']['primary']['attribs']['port']) &&
                   34885:               !is_numeric($info['servers']['primary']['attribs']['port'])) {
                   34886:             $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_PORT,
                   34887:                 array('port' => $info['servers']['primary']['attribs']['port']));
                   34888:         }
                   34889: 
                   34890:         if (isset($info['servers']['primary']['attribs'], $info['servers']['primary']['attribs']['ssl']) &&
                   34891:               $info['servers']['primary']['attribs']['ssl'] != 'yes') {
                   34892:             $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL,
                   34893:                 array('ssl' => $info['servers']['primary']['attribs']['ssl'],
                   34894:                     'server' => $info['name']));
                   34895:         }
                   34896: 
                   34897:         if (isset($info['servers']['primary']['rest']) &&
                   34898:               isset($info['servers']['primary']['rest']['baseurl'])) {
                   34899:             $this->_validateFunctions('rest', $info['servers']['primary']['rest']['baseurl']);
                   34900:         }
                   34901:         if (isset($info['servers']['mirror'])) {
                   34902:             if ($this->_channelInfo['name'] == '__uri') {
                   34903:                 $this->_validateError(PEAR_CHANNELFILE_URI_CANT_MIRROR);
                   34904:             }
                   34905:             if (!isset($info['servers']['mirror'][0])) {
                   34906:                 $info['servers']['mirror'] = array($info['servers']['mirror']);
                   34907:             }
                   34908:             foreach ($info['servers']['mirror'] as $mirror) {
                   34909:                 if (!isset($mirror['attribs']['host'])) {
                   34910:                     $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_HOST,
                   34911:                       array('type' => 'mirror'));
                   34912:                 } elseif (!$this->validChannelServer($mirror['attribs']['host'])) {
                   34913:                     $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_HOST,
                   34914:                         array('server' => $mirror['attribs']['host'], 'type' => 'mirror'));
                   34915:                 }
                   34916:                 if (isset($mirror['attribs']['ssl']) && $mirror['attribs']['ssl'] != 'yes') {
                   34917:                     $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL,
                   34918:                         array('ssl' => $info['ssl'], 'server' => $mirror['attribs']['host']));
                   34919:                 }
                   34920:                 if (isset($mirror['rest'])) {
                   34921:                     $this->_validateFunctions('rest', $mirror['rest']['baseurl'],
                   34922:                         $mirror['attribs']['host']);
                   34923:                 }
                   34924:             }
                   34925:         }
                   34926:         return $this->_isValid;
                   34927:     }
                   34928: 
                   34929:     /**
                   34930:      * @param string  rest - protocol name this function applies to
                   34931:      * @param array the functions
                   34932:      * @param string the name of the parent element (mirror name, for instance)
                   34933:      */
                   34934:     function _validateFunctions($protocol, $functions, $parent = '')
                   34935:     {
                   34936:         if (!isset($functions[0])) {
                   34937:             $functions = array($functions);
                   34938:         }
                   34939: 
                   34940:         foreach ($functions as $function) {
                   34941:             if (!isset($function['_content']) || empty($function['_content'])) {
                   34942:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME,
                   34943:                     array('parent' => $parent, 'protocol' => $protocol));
                   34944:             }
                   34945: 
                   34946:             if ($protocol == 'rest') {
                   34947:                 if (!isset($function['attribs']['type']) ||
                   34948:                       empty($function['attribs']['type'])) {
                   34949:                     $this->_validateError(PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE,
                   34950:                         array('parent' => $parent, 'protocol' => $protocol));
                   34951:                 }
                   34952:             } else {
                   34953:                 if (!isset($function['attribs']['version']) ||
                   34954:                       empty($function['attribs']['version'])) {
                   34955:                     $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION,
                   34956:                         array('parent' => $parent, 'protocol' => $protocol));
                   34957:                 }
                   34958:             }
                   34959:         }
                   34960:     }
                   34961: 
                   34962:     /**
                   34963:      * Test whether a string contains a valid channel server.
                   34964:      * @param string $ver the package version to test
                   34965:      * @return bool
                   34966:      */
                   34967:     function validChannelServer($server)
                   34968:     {
                   34969:         if ($server == '__uri') {
                   34970:             return true;
                   34971:         }
                   34972:         return (bool) preg_match(PEAR_CHANNELS_SERVER_PREG, $server);
                   34973:     }
                   34974: 
                   34975:     /**
                   34976:      * @return string|false
                   34977:      */
                   34978:     function getName()
                   34979:     {
                   34980:         if (isset($this->_channelInfo['name'])) {
                   34981:             return $this->_channelInfo['name'];
                   34982:         }
                   34983: 
                   34984:         return false;
                   34985:     }
                   34986: 
                   34987:     /**
                   34988:      * @return string|false
                   34989:      */
                   34990:     function getServer()
                   34991:     {
                   34992:         if (isset($this->_channelInfo['name'])) {
                   34993:             return $this->_channelInfo['name'];
                   34994:         }
                   34995: 
                   34996:         return false;
                   34997:     }
                   34998: 
                   34999:     /**
                   35000:      * @return int|80 port number to connect to
                   35001:      */
                   35002:     function getPort($mirror = false)
                   35003:     {
                   35004:         if ($mirror) {
                   35005:             if ($mir = $this->getMirror($mirror)) {
                   35006:                 if (isset($mir['attribs']['port'])) {
                   35007:                     return $mir['attribs']['port'];
                   35008:                 }
                   35009: 
                   35010:                 if ($this->getSSL($mirror)) {
                   35011:                     return 443;
                   35012:                 }
                   35013: 
                   35014:                 return 80;
                   35015:             }
                   35016: 
                   35017:             return false;
                   35018:         }
                   35019: 
                   35020:         if (isset($this->_channelInfo['servers']['primary']['attribs']['port'])) {
                   35021:             return $this->_channelInfo['servers']['primary']['attribs']['port'];
                   35022:         }
                   35023: 
                   35024:         if ($this->getSSL()) {
                   35025:             return 443;
                   35026:         }
                   35027: 
                   35028:         return 80;
                   35029:     }
                   35030: 
                   35031:     /**
                   35032:      * @return bool Determines whether secure sockets layer (SSL) is used to connect to this channel
                   35033:      */
                   35034:     function getSSL($mirror = false)
                   35035:     {
                   35036:         if ($mirror) {
                   35037:             if ($mir = $this->getMirror($mirror)) {
                   35038:                 if (isset($mir['attribs']['ssl'])) {
                   35039:                     return true;
                   35040:                 }
                   35041: 
                   35042:                 return false;
                   35043:             }
                   35044: 
                   35045:             return false;
                   35046:         }
                   35047: 
                   35048:         if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) {
                   35049:             return true;
                   35050:         }
                   35051: 
                   35052:         return false;
                   35053:     }
                   35054: 
                   35055:     /**
                   35056:      * @return string|false
                   35057:      */
                   35058:     function getSummary()
                   35059:     {
                   35060:         if (isset($this->_channelInfo['summary'])) {
                   35061:             return $this->_channelInfo['summary'];
                   35062:         }
                   35063: 
                   35064:         return false;
                   35065:     }
                   35066: 
                   35067:     /**
                   35068:      * @param string protocol type
                   35069:      * @param string Mirror name
                   35070:      * @return array|false
                   35071:      */
                   35072:     function getFunctions($protocol, $mirror = false)
                   35073:     {
                   35074:         if ($this->getName() == '__uri') {
                   35075:             return false;
                   35076:         }
                   35077: 
                   35078:         $function = $protocol == 'rest' ? 'baseurl' : 'function';
                   35079:         if ($mirror) {
                   35080:             if ($mir = $this->getMirror($mirror)) {
                   35081:                 if (isset($mir[$protocol][$function])) {
                   35082:                     return $mir[$protocol][$function];
                   35083:                 }
                   35084:             }
                   35085: 
                   35086:             return false;
                   35087:         }
                   35088: 
                   35089:         if (isset($this->_channelInfo['servers']['primary'][$protocol][$function])) {
                   35090:             return $this->_channelInfo['servers']['primary'][$protocol][$function];
                   35091:         }
                   35092: 
                   35093:         return false;
                   35094:     }
                   35095: 
                   35096:     /**
                   35097:      * @param string Protocol type
                   35098:      * @param string Function name (null to return the
                   35099:      *               first protocol of the type requested)
                   35100:      * @param string Mirror name, if any
                   35101:      * @return array
                   35102:      */
                   35103:      function getFunction($type, $name = null, $mirror = false)
                   35104:      {
                   35105:         $protocols = $this->getFunctions($type, $mirror);
                   35106:         if (!$protocols) {
                   35107:             return false;
                   35108:         }
                   35109: 
                   35110:         foreach ($protocols as $protocol) {
                   35111:             if ($name === null) {
                   35112:                 return $protocol;
                   35113:             }
                   35114: 
                   35115:             if ($protocol['_content'] != $name) {
                   35116:                 continue;
                   35117:             }
                   35118: 
                   35119:             return $protocol;
                   35120:         }
                   35121: 
                   35122:         return false;
                   35123:      }
                   35124: 
                   35125:     /**
                   35126:      * @param string protocol type
                   35127:      * @param string protocol name
                   35128:      * @param string version
                   35129:      * @param string mirror name
                   35130:      * @return boolean
                   35131:      */
                   35132:     function supports($type, $name = null, $mirror = false, $version = '1.0')
                   35133:     {
                   35134:         $protocols = $this->getFunctions($type, $mirror);
                   35135:         if (!$protocols) {
                   35136:             return false;
                   35137:         }
                   35138: 
                   35139:         foreach ($protocols as $protocol) {
                   35140:             if ($protocol['attribs']['version'] != $version) {
                   35141:                 continue;
                   35142:             }
                   35143: 
                   35144:             if ($name === null) {
                   35145:                 return true;
                   35146:             }
                   35147: 
                   35148:             if ($protocol['_content'] != $name) {
                   35149:                 continue;
                   35150:             }
                   35151: 
                   35152:             return true;
                   35153:         }
                   35154: 
                   35155:         return false;
                   35156:     }
                   35157: 
                   35158:     /**
                   35159:      * Determines whether a channel supports Representational State Transfer (REST) protocols
                   35160:      * for retrieving channel information
                   35161:      * @param string
                   35162:      * @return bool
                   35163:      */
                   35164:     function supportsREST($mirror = false)
                   35165:     {
                   35166:         if ($mirror == $this->_channelInfo['name']) {
                   35167:             $mirror = false;
                   35168:         }
                   35169: 
                   35170:         if ($mirror) {
                   35171:             if ($mir = $this->getMirror($mirror)) {
                   35172:                 return isset($mir['rest']);
                   35173:             }
                   35174: 
                   35175:             return false;
                   35176:         }
                   35177: 
                   35178:         return isset($this->_channelInfo['servers']['primary']['rest']);
                   35179:     }
                   35180: 
                   35181:     /**
                   35182:      * Get the URL to access a base resource.
                   35183:      *
                   35184:      * Hyperlinks in the returned xml will be used to retrieve the proper information
                   35185:      * needed.  This allows extreme extensibility and flexibility in implementation
                   35186:      * @param string Resource Type to retrieve
                   35187:      */
                   35188:     function getBaseURL($resourceType, $mirror = false)
                   35189:     {
                   35190:         if ($mirror == $this->_channelInfo['name']) {
                   35191:             $mirror = false;
                   35192:         }
                   35193: 
                   35194:         if ($mirror) {
                   35195:             $mir = $this->getMirror($mirror);
                   35196:             if (!$mir) {
                   35197:                 return false;
                   35198:             }
                   35199: 
                   35200:             $rest = $mir['rest'];
                   35201:         } else {
                   35202:             $rest = $this->_channelInfo['servers']['primary']['rest'];
                   35203:         }
                   35204: 
                   35205:         if (!isset($rest['baseurl'][0])) {
                   35206:             $rest['baseurl'] = array($rest['baseurl']);
                   35207:         }
                   35208: 
                   35209:         foreach ($rest['baseurl'] as $baseurl) {
                   35210:             if (strtolower($baseurl['attribs']['type']) == strtolower($resourceType)) {
                   35211:                 return $baseurl['_content'];
                   35212:             }
                   35213:         }
                   35214: 
                   35215:         return false;
                   35216:     }
                   35217: 
                   35218:     /**
                   35219:      * Since REST does not implement RPC, provide this as a logical wrapper around
                   35220:      * resetFunctions for REST
                   35221:      * @param string|false mirror name, if any
                   35222:      */
                   35223:     function resetREST($mirror = false)
                   35224:     {
                   35225:         return $this->resetFunctions('rest', $mirror);
                   35226:     }
                   35227: 
                   35228:     /**
                   35229:      * Empty all protocol definitions
                   35230:      * @param string protocol type
                   35231:      * @param string|false mirror name, if any
                   35232:      */
                   35233:     function resetFunctions($type, $mirror = false)
                   35234:     {
                   35235:         if ($mirror) {
                   35236:             if (isset($this->_channelInfo['servers']['mirror'])) {
                   35237:                 $mirrors = $this->_channelInfo['servers']['mirror'];
                   35238:                 if (!isset($mirrors[0])) {
                   35239:                     $mirrors = array($mirrors);
                   35240:                 }
                   35241: 
                   35242:                 foreach ($mirrors as $i => $mir) {
                   35243:                     if ($mir['attribs']['host'] == $mirror) {
                   35244:                         if (isset($this->_channelInfo['servers']['mirror'][$i][$type])) {
                   35245:                             unset($this->_channelInfo['servers']['mirror'][$i][$type]);
                   35246:                         }
                   35247: 
                   35248:                         return true;
                   35249:                     }
                   35250:                 }
                   35251: 
                   35252:                 return false;
                   35253:             }
                   35254: 
                   35255:             return false;
                   35256:         }
                   35257: 
                   35258:         if (isset($this->_channelInfo['servers']['primary'][$type])) {
                   35259:             unset($this->_channelInfo['servers']['primary'][$type]);
                   35260:         }
                   35261: 
                   35262:         return true;
                   35263:     }
                   35264: 
                   35265:     /**
                   35266:      * Set a channel's protocols to the protocols supported by pearweb
                   35267:      */
                   35268:     function setDefaultPEARProtocols($version = '1.0', $mirror = false)
                   35269:     {
                   35270:         switch ($version) {
                   35271:             case '1.0' :
                   35272:                 $this->resetREST($mirror);
                   35273: 
                   35274:                 if (!isset($this->_channelInfo['servers'])) {
                   35275:                     $this->_channelInfo['servers'] = array('primary' =>
                   35276:                         array('rest' => array()));
                   35277:                 } elseif (!isset($this->_channelInfo['servers']['primary'])) {
                   35278:                     $this->_channelInfo['servers']['primary'] = array('rest' => array());
                   35279:                 }
                   35280: 
                   35281:                 return true;
                   35282:             break;
                   35283:             default :
                   35284:                 return false;
                   35285:             break;
                   35286:         }
                   35287:     }
                   35288: 
                   35289:     /**
                   35290:      * @return array
                   35291:      */
                   35292:     function getMirrors()
                   35293:     {
                   35294:         if (isset($this->_channelInfo['servers']['mirror'])) {
                   35295:             $mirrors = $this->_channelInfo['servers']['mirror'];
                   35296:             if (!isset($mirrors[0])) {
                   35297:                 $mirrors = array($mirrors);
                   35298:             }
                   35299: 
                   35300:             return $mirrors;
                   35301:         }
                   35302: 
                   35303:         return array();
                   35304:     }
                   35305: 
                   35306:     /**
                   35307:      * Get the unserialized XML representing a mirror
                   35308:      * @return array|false
                   35309:      */
                   35310:     function getMirror($server)
                   35311:     {
                   35312:         foreach ($this->getMirrors() as $mirror) {
                   35313:             if ($mirror['attribs']['host'] == $server) {
                   35314:                 return $mirror;
                   35315:             }
                   35316:         }
                   35317: 
                   35318:         return false;
                   35319:     }
                   35320: 
                   35321:     /**
                   35322:      * @param string
                   35323:      * @return string|false
                   35324:      * @error PEAR_CHANNELFILE_ERROR_NO_NAME
                   35325:      * @error PEAR_CHANNELFILE_ERROR_INVALID_NAME
                   35326:      */
                   35327:     function setName($name)
                   35328:     {
                   35329:         return $this->setServer($name);
                   35330:     }
                   35331: 
                   35332:     /**
                   35333:      * Set the socket number (port) that is used to connect to this channel
                   35334:      * @param integer
                   35335:      * @param string|false name of the mirror server, or false for the primary
                   35336:      */
                   35337:     function setPort($port, $mirror = false)
                   35338:     {
                   35339:         if ($mirror) {
                   35340:             if (!isset($this->_channelInfo['servers']['mirror'])) {
                   35341:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                   35342:                     array('mirror' => $mirror));
                   35343:                 return false;
                   35344:             }
                   35345: 
                   35346:             if (isset($this->_channelInfo['servers']['mirror'][0])) {
                   35347:                 foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
                   35348:                     if ($mirror == $mir['attribs']['host']) {
                   35349:                         $this->_channelInfo['servers']['mirror'][$i]['attribs']['port'] = $port;
                   35350:                         return true;
                   35351:                     }
                   35352:                 }
                   35353: 
                   35354:                 return false;
                   35355:             } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
                   35356:                 $this->_channelInfo['servers']['mirror']['attribs']['port'] = $port;
                   35357:                 $this->_isValid = false;
                   35358:                 return true;
                   35359:             }
                   35360:         }
                   35361: 
                   35362:         $this->_channelInfo['servers']['primary']['attribs']['port'] = $port;
                   35363:         $this->_isValid = false;
                   35364:         return true;
                   35365:     }
                   35366: 
                   35367:     /**
                   35368:      * Set the socket number (port) that is used to connect to this channel
                   35369:      * @param bool Determines whether to turn on SSL support or turn it off
                   35370:      * @param string|false name of the mirror server, or false for the primary
                   35371:      */
                   35372:     function setSSL($ssl = true, $mirror = false)
                   35373:     {
                   35374:         if ($mirror) {
                   35375:             if (!isset($this->_channelInfo['servers']['mirror'])) {
                   35376:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                   35377:                     array('mirror' => $mirror));
                   35378:                 return false;
                   35379:             }
                   35380: 
                   35381:             if (isset($this->_channelInfo['servers']['mirror'][0])) {
                   35382:                 foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
                   35383:                     if ($mirror == $mir['attribs']['host']) {
                   35384:                         if (!$ssl) {
                   35385:                             if (isset($this->_channelInfo['servers']['mirror'][$i]
                   35386:                                   ['attribs']['ssl'])) {
                   35387:                                 unset($this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl']);
                   35388:                             }
                   35389:                         } else {
                   35390:                             $this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl'] = 'yes';
                   35391:                         }
                   35392: 
                   35393:                         return true;
                   35394:                     }
                   35395:                 }
                   35396: 
                   35397:                 return false;
                   35398:             } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
                   35399:                 if (!$ssl) {
                   35400:                     if (isset($this->_channelInfo['servers']['mirror']['attribs']['ssl'])) {
                   35401:                         unset($this->_channelInfo['servers']['mirror']['attribs']['ssl']);
                   35402:                     }
                   35403:                 } else {
                   35404:                     $this->_channelInfo['servers']['mirror']['attribs']['ssl'] = 'yes';
                   35405:                 }
                   35406: 
                   35407:                 $this->_isValid = false;
                   35408:                 return true;
                   35409:             }
                   35410:         }
                   35411: 
                   35412:         if ($ssl) {
                   35413:             $this->_channelInfo['servers']['primary']['attribs']['ssl'] = 'yes';
                   35414:         } else {
                   35415:             if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) {
                   35416:                 unset($this->_channelInfo['servers']['primary']['attribs']['ssl']);
                   35417:             }
                   35418:         }
                   35419: 
                   35420:         $this->_isValid = false;
                   35421:         return true;
                   35422:     }
                   35423: 
                   35424:     /**
                   35425:      * @param string
                   35426:      * @return string|false
                   35427:      * @error PEAR_CHANNELFILE_ERROR_NO_SERVER
                   35428:      * @error PEAR_CHANNELFILE_ERROR_INVALID_SERVER
                   35429:      */
                   35430:     function setServer($server, $mirror = false)
                   35431:     {
                   35432:         if (empty($server)) {
                   35433:             $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SERVER);
                   35434:             return false;
                   35435:         } elseif (!$this->validChannelServer($server)) {
                   35436:             $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
                   35437:                 array('tag' => 'name', 'name' => $server));
                   35438:             return false;
                   35439:         }
                   35440: 
                   35441:         if ($mirror) {
                   35442:             $found = false;
                   35443:             foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
                   35444:                 if ($mirror == $mir['attribs']['host']) {
                   35445:                     $found = true;
                   35446:                     break;
                   35447:                 }
                   35448:             }
                   35449: 
                   35450:             if (!$found) {
                   35451:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                   35452:                     array('mirror' => $mirror));
                   35453:                 return false;
                   35454:             }
                   35455: 
                   35456:             $this->_channelInfo['mirror'][$i]['attribs']['host'] = $server;
                   35457:             return true;
                   35458:         }
                   35459: 
                   35460:         $this->_channelInfo['name'] = $server;
                   35461:         return true;
                   35462:     }
                   35463: 
                   35464:     /**
                   35465:      * @param string
                   35466:      * @return boolean success
                   35467:      * @error PEAR_CHANNELFILE_ERROR_NO_SUMMARY
                   35468:      * @warning PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY
                   35469:      */
                   35470:     function setSummary($summary)
                   35471:     {
                   35472:         if (empty($summary)) {
                   35473:             $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY);
                   35474:             return false;
                   35475:         } elseif (strpos(trim($summary), "\n") !== false) {
                   35476:             $this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY,
                   35477:                 array('summary' => $summary));
                   35478:         }
                   35479: 
                   35480:         $this->_channelInfo['summary'] = $summary;
                   35481:         return true;
                   35482:     }
                   35483: 
                   35484:     /**
                   35485:      * @param string
                   35486:      * @param boolean determines whether the alias is in channel.xml or local
                   35487:      * @return boolean success
                   35488:      */
                   35489:     function setAlias($alias, $local = false)
                   35490:     {
                   35491:         if (!$this->validChannelServer($alias)) {
                   35492:             $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
                   35493:                 array('tag' => 'suggestedalias', 'name' => $alias));
                   35494:             return false;
                   35495:         }
                   35496: 
                   35497:         if ($local) {
                   35498:             $this->_channelInfo['localalias'] = $alias;
                   35499:         } else {
                   35500:             $this->_channelInfo['suggestedalias'] = $alias;
                   35501:         }
                   35502: 
                   35503:         return true;
                   35504:     }
                   35505: 
                   35506:     /**
                   35507:      * @return string
                   35508:      */
                   35509:     function getAlias()
                   35510:     {
                   35511:         if (isset($this->_channelInfo['localalias'])) {
                   35512:             return $this->_channelInfo['localalias'];
                   35513:         }
                   35514:         if (isset($this->_channelInfo['suggestedalias'])) {
                   35515:             return $this->_channelInfo['suggestedalias'];
                   35516:         }
                   35517:         if (isset($this->_channelInfo['name'])) {
                   35518:             return $this->_channelInfo['name'];
                   35519:         }
                   35520:         return '';
                   35521:     }
                   35522: 
                   35523:     /**
                   35524:      * Set the package validation object if it differs from PEAR's default
                   35525:      * The class must be includeable via changing _ in the classname to path separator,
                   35526:      * but no checking of this is made.
                   35527:      * @param string|false pass in false to reset to the default packagename regex
                   35528:      * @return boolean success
                   35529:      */
                   35530:     function setValidationPackage($validateclass, $version)
                   35531:     {
                   35532:         if (empty($validateclass)) {
                   35533:             unset($this->_channelInfo['validatepackage']);
                   35534:         }
                   35535:         $this->_channelInfo['validatepackage'] = array('_content' => $validateclass);
                   35536:         $this->_channelInfo['validatepackage']['attribs'] = array('version' => $version);
                   35537:     }
                   35538: 
                   35539:     /**
                   35540:      * Add a protocol to the provides section
                   35541:      * @param string protocol type
                   35542:      * @param string protocol version
                   35543:      * @param string protocol name, if any
                   35544:      * @param string mirror name, if this is a mirror's protocol
                   35545:      * @return bool
                   35546:      */
                   35547:     function addFunction($type, $version, $name = '', $mirror = false)
                   35548:     {
                   35549:         if ($mirror) {
                   35550:             return $this->addMirrorFunction($mirror, $type, $version, $name);
                   35551:         }
                   35552: 
                   35553:         $set = array('attribs' => array('version' => $version), '_content' => $name);
                   35554:         if (!isset($this->_channelInfo['servers']['primary'][$type]['function'])) {
                   35555:             if (!isset($this->_channelInfo['servers'])) {
                   35556:                 $this->_channelInfo['servers'] = array('primary' =>
                   35557:                     array($type => array()));
                   35558:             } elseif (!isset($this->_channelInfo['servers']['primary'])) {
                   35559:                 $this->_channelInfo['servers']['primary'] = array($type => array());
                   35560:             }
                   35561: 
                   35562:             $this->_channelInfo['servers']['primary'][$type]['function'] = $set;
                   35563:             $this->_isValid = false;
                   35564:             return true;
                   35565:         } elseif (!isset($this->_channelInfo['servers']['primary'][$type]['function'][0])) {
                   35566:             $this->_channelInfo['servers']['primary'][$type]['function'] = array(
                   35567:                 $this->_channelInfo['servers']['primary'][$type]['function']);
                   35568:         }
                   35569: 
                   35570:         $this->_channelInfo['servers']['primary'][$type]['function'][] = $set;
                   35571:         return true;
                   35572:     }
                   35573:     /**
                   35574:      * Add a protocol to a mirror's provides section
                   35575:      * @param string mirror name (server)
                   35576:      * @param string protocol type
                   35577:      * @param string protocol version
                   35578:      * @param string protocol name, if any
                   35579:      */
                   35580:     function addMirrorFunction($mirror, $type, $version, $name = '')
                   35581:     {
                   35582:         if (!isset($this->_channelInfo['servers']['mirror'])) {
                   35583:             $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                   35584:                 array('mirror' => $mirror));
                   35585:             return false;
                   35586:         }
                   35587: 
                   35588:         $setmirror = false;
                   35589:         if (isset($this->_channelInfo['servers']['mirror'][0])) {
                   35590:             foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
                   35591:                 if ($mirror == $mir['attribs']['host']) {
                   35592:                     $setmirror = &$this->_channelInfo['servers']['mirror'][$i];
                   35593:                     break;
                   35594:                 }
                   35595:             }
                   35596:         } else {
                   35597:             if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
                   35598:                 $setmirror = &$this->_channelInfo['servers']['mirror'];
                   35599:             }
                   35600:         }
                   35601: 
                   35602:         if (!$setmirror) {
                   35603:             $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                   35604:                 array('mirror' => $mirror));
                   35605:             return false;
                   35606:         }
                   35607: 
                   35608:         $set = array('attribs' => array('version' => $version), '_content' => $name);
                   35609:         if (!isset($setmirror[$type]['function'])) {
                   35610:             $setmirror[$type]['function'] = $set;
                   35611:             $this->_isValid = false;
                   35612:             return true;
                   35613:         } elseif (!isset($setmirror[$type]['function'][0])) {
                   35614:             $setmirror[$type]['function'] = array($setmirror[$type]['function']);
                   35615:         }
                   35616: 
                   35617:         $setmirror[$type]['function'][] = $set;
                   35618:         $this->_isValid = false;
                   35619:         return true;
                   35620:     }
                   35621: 
                   35622:     /**
                   35623:      * @param string Resource Type this url links to
                   35624:      * @param string URL
                   35625:      * @param string|false mirror name, if this is not a primary server REST base URL
                   35626:      */
                   35627:     function setBaseURL($resourceType, $url, $mirror = false)
                   35628:     {
                   35629:         if ($mirror) {
                   35630:             if (!isset($this->_channelInfo['servers']['mirror'])) {
                   35631:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
                   35632:                     array('mirror' => $mirror));
                   35633:                 return false;
                   35634:             }
                   35635: 
                   35636:             $setmirror = false;
                   35637:             if (isset($this->_channelInfo['servers']['mirror'][0])) {
                   35638:                 foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
                   35639:                     if ($mirror == $mir['attribs']['host']) {
                   35640:                         $setmirror = &$this->_channelInfo['servers']['mirror'][$i];
                   35641:                         break;
                   35642:                     }
                   35643:                 }
                   35644:             } else {
                   35645:                 if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
                   35646:                     $setmirror = &$this->_channelInfo['servers']['mirror'];
                   35647:                 }
                   35648:             }
                   35649:         } else {
                   35650:             $setmirror = &$this->_channelInfo['servers']['primary'];
                   35651:         }
                   35652: 
                   35653:         $set = array('attribs' => array('type' => $resourceType), '_content' => $url);
                   35654:         if (!isset($setmirror['rest'])) {
                   35655:             $setmirror['rest'] = array();
                   35656:         }
                   35657: 
                   35658:         if (!isset($setmirror['rest']['baseurl'])) {
                   35659:             $setmirror['rest']['baseurl'] = $set;
                   35660:             $this->_isValid = false;
                   35661:             return true;
                   35662:         } elseif (!isset($setmirror['rest']['baseurl'][0])) {
                   35663:             $setmirror['rest']['baseurl'] = array($setmirror['rest']['baseurl']);
                   35664:         }
                   35665: 
                   35666:         foreach ($setmirror['rest']['baseurl'] as $i => $url) {
                   35667:             if ($url['attribs']['type'] == $resourceType) {
                   35668:                 $this->_isValid = false;
                   35669:                 $setmirror['rest']['baseurl'][$i] = $set;
                   35670:                 return true;
                   35671:             }
                   35672:         }
                   35673: 
                   35674:         $setmirror['rest']['baseurl'][] = $set;
                   35675:         $this->_isValid = false;
                   35676:         return true;
                   35677:     }
                   35678: 
                   35679:     /**
                   35680:      * @param string mirror server
                   35681:      * @param int mirror http port
                   35682:      * @return boolean
                   35683:      */
                   35684:     function addMirror($server, $port = null)
                   35685:     {
                   35686:         if ($this->_channelInfo['name'] == '__uri') {
                   35687:             return false; // the __uri channel cannot have mirrors by definition
                   35688:         }
                   35689: 
                   35690:         $set = array('attribs' => array('host' => $server));
                   35691:         if (is_numeric($port)) {
                   35692:             $set['attribs']['port'] = $port;
                   35693:         }
                   35694: 
                   35695:         if (!isset($this->_channelInfo['servers']['mirror'])) {
                   35696:             $this->_channelInfo['servers']['mirror'] = $set;
                   35697:             return true;
                   35698:         }
                   35699: 
                   35700:         if (!isset($this->_channelInfo['servers']['mirror'][0])) {
                   35701:             $this->_channelInfo['servers']['mirror'] =
                   35702:                 array($this->_channelInfo['servers']['mirror']);
                   35703:         }
                   35704: 
                   35705:         $this->_channelInfo['servers']['mirror'][] = $set;
                   35706:         return true;
                   35707:     }
                   35708: 
                   35709:     /**
                   35710:      * Retrieve the name of the validation package for this channel
                   35711:      * @return string|false
                   35712:      */
                   35713:     function getValidationPackage()
                   35714:     {
                   35715:         if (!$this->_isValid && !$this->validate()) {
                   35716:             return false;
                   35717:         }
                   35718: 
                   35719:         if (!isset($this->_channelInfo['validatepackage'])) {
                   35720:             return array('attribs' => array('version' => 'default'),
                   35721:                 '_content' => 'PEAR_Validate');
                   35722:         }
                   35723: 
                   35724:         return $this->_channelInfo['validatepackage'];
                   35725:     }
                   35726: 
                   35727:     /**
                   35728:      * Retrieve the object that can be used for custom validation
                   35729:      * @param string|false the name of the package to validate.  If the package is
                   35730:      *                     the channel validation package, PEAR_Validate is returned
                   35731:      * @return PEAR_Validate|false false is returned if the validation package
                   35732:      *         cannot be located
                   35733:      */
                   35734:     function &getValidationObject($package = false)
                   35735:     {
                   35736:         if (!class_exists('PEAR_Validate')) {
                   35737:             require_once 'PEAR/Validate.php';
                   35738:         }
                   35739: 
                   35740:         if (!$this->_isValid) {
                   35741:             if (!$this->validate()) {
                   35742:                 $a = false;
                   35743:                 return $a;
                   35744:             }
                   35745:         }
                   35746: 
                   35747:         if (isset($this->_channelInfo['validatepackage'])) {
                   35748:             if ($package == $this->_channelInfo['validatepackage']) {
                   35749:                 // channel validation packages are always validated by PEAR_Validate
                   35750:                 $val = &new PEAR_Validate;
                   35751:                 return $val;
                   35752:             }
                   35753: 
                   35754:             if (!class_exists(str_replace('.', '_',
                   35755:                   $this->_channelInfo['validatepackage']['_content']))) {
                   35756:                 if ($this->isIncludeable(str_replace('_', '/',
                   35757:                       $this->_channelInfo['validatepackage']['_content']) . '.php')) {
                   35758:                     include_once str_replace('_', '/',
                   35759:                         $this->_channelInfo['validatepackage']['_content']) . '.php';
                   35760:                     $vclass = str_replace('.', '_',
                   35761:                         $this->_channelInfo['validatepackage']['_content']);
                   35762:                     $val = &new $vclass;
                   35763:                 } else {
                   35764:                     $a = false;
                   35765:                     return $a;
                   35766:                 }
                   35767:             } else {
                   35768:                 $vclass = str_replace('.', '_',
                   35769:                     $this->_channelInfo['validatepackage']['_content']);
                   35770:                 $val = &new $vclass;
                   35771:             }
                   35772:         } else {
                   35773:             $val = &new PEAR_Validate;
                   35774:         }
                   35775: 
                   35776:         return $val;
                   35777:     }
                   35778: 
                   35779:     function isIncludeable($path)
                   35780:     {
                   35781:         $possibilities = explode(PATH_SEPARATOR, ini_get('include_path'));
                   35782:         foreach ($possibilities as $dir) {
                   35783:             if (file_exists($dir . DIRECTORY_SEPARATOR . $path)
                   35784:                   && is_readable($dir . DIRECTORY_SEPARATOR . $path)) {
                   35785:                 return true;
                   35786:             }
                   35787:         }
                   35788: 
                   35789:         return false;
                   35790:     }
                   35791: 
                   35792:     /**
                   35793:      * This function is used by the channel updater and retrieves a value set by
                   35794:      * the registry, or the current time if it has not been set
                   35795:      * @return string
                   35796:      */
                   35797:     function lastModified()
                   35798:     {
                   35799:         if (isset($this->_channelInfo['_lastmodified'])) {
                   35800:             return $this->_channelInfo['_lastmodified'];
                   35801:         }
                   35802: 
                   35803:         return time();
                   35804:     }
1.1.1.2 ! misho    35805: }PEAR-1.9.4/PEAR/Command.php0000644000076500000240000003063311605156614014057 0ustar  helgistaff<?php
1.1       misho    35806: /**
                   35807:  * PEAR_Command, command pattern class
                   35808:  *
                   35809:  * PHP versions 4 and 5
                   35810:  *
                   35811:  * @category   pear
                   35812:  * @package    PEAR
                   35813:  * @author     Stig Bakken <ssb@php.net>
                   35814:  * @author     Greg Beaver <cellog@php.net>
                   35815:  * @copyright  1997-2009 The Authors
                   35816:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   35817:  * @version    CVS: $Id: Command.php 313023 2011-07-06 19:17:11Z dufuz $
                   35818:  * @link       http://pear.php.net/package/PEAR
                   35819:  * @since      File available since Release 0.1
                   35820:  */
                   35821: 
                   35822: /**
                   35823:  * Needed for error handling
                   35824:  */
                   35825: require_once 'PEAR.php';
                   35826: require_once 'PEAR/Frontend.php';
                   35827: require_once 'PEAR/XMLParser.php';
                   35828: 
                   35829: /**
                   35830:  * List of commands and what classes they are implemented in.
                   35831:  * @var array command => implementing class
                   35832:  */
                   35833: $GLOBALS['_PEAR_Command_commandlist'] = array();
                   35834: 
                   35835: /**
                   35836:  * List of commands and their descriptions
                   35837:  * @var array command => description
                   35838:  */
                   35839: $GLOBALS['_PEAR_Command_commanddesc'] = array();
                   35840: 
                   35841: /**
                   35842:  * List of shortcuts to common commands.
                   35843:  * @var array shortcut => command
                   35844:  */
                   35845: $GLOBALS['_PEAR_Command_shortcuts'] = array();
                   35846: 
                   35847: /**
                   35848:  * Array of command objects
                   35849:  * @var array class => object
                   35850:  */
                   35851: $GLOBALS['_PEAR_Command_objects'] = array();
                   35852: 
                   35853: /**
                   35854:  * PEAR command class, a simple factory class for administrative
                   35855:  * commands.
                   35856:  *
                   35857:  * How to implement command classes:
                   35858:  *
                   35859:  * - The class must be called PEAR_Command_Nnn, installed in the
                   35860:  *   "PEAR/Common" subdir, with a method called getCommands() that
                   35861:  *   returns an array of the commands implemented by the class (see
                   35862:  *   PEAR/Command/Install.php for an example).
                   35863:  *
                   35864:  * - The class must implement a run() function that is called with three
                   35865:  *   params:
                   35866:  *
                   35867:  *    (string) command name
                   35868:  *    (array)  assoc array with options, freely defined by each
                   35869:  *             command, for example:
                   35870:  *             array('force' => true)
                   35871:  *    (array)  list of the other parameters
                   35872:  *
                   35873:  *   The run() function returns a PEAR_CommandResponse object.  Use
                   35874:  *   these methods to get information:
                   35875:  *
                   35876:  *    int getStatus()   Returns PEAR_COMMAND_(SUCCESS|FAILURE|PARTIAL)
                   35877:  *                      *_PARTIAL means that you need to issue at least
                   35878:  *                      one more command to complete the operation
                   35879:  *                      (used for example for validation steps).
                   35880:  *
                   35881:  *    string getMessage()  Returns a message for the user.  Remember,
                   35882:  *                         no HTML or other interface-specific markup.
                   35883:  *
                   35884:  *   If something unexpected happens, run() returns a PEAR error.
                   35885:  *
                   35886:  * - DON'T OUTPUT ANYTHING! Return text for output instead.
                   35887:  *
                   35888:  * - DON'T USE HTML! The text you return will be used from both Gtk,
                   35889:  *   web and command-line interfaces, so for now, keep everything to
                   35890:  *   plain text.
                   35891:  *
                   35892:  * - DON'T USE EXIT OR DIE! Always use pear errors.  From static
                   35893:  *   classes do PEAR::raiseError(), from other classes do
                   35894:  *   $this->raiseError().
                   35895:  * @category   pear
                   35896:  * @package    PEAR
                   35897:  * @author     Stig Bakken <ssb@php.net>
                   35898:  * @author     Greg Beaver <cellog@php.net>
                   35899:  * @copyright  1997-2009 The Authors
                   35900:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   35901:  * @version    Release: 1.9.4
                   35902:  * @link       http://pear.php.net/package/PEAR
                   35903:  * @since      Class available since Release 0.1
                   35904:  */
                   35905: class PEAR_Command
                   35906: {
                   35907:     // {{{ factory()
                   35908: 
                   35909:     /**
                   35910:      * Get the right object for executing a command.
                   35911:      *
                   35912:      * @param string $command The name of the command
                   35913:      * @param object $config  Instance of PEAR_Config object
                   35914:      *
                   35915:      * @return object the command object or a PEAR error
                   35916:      *
                   35917:      * @access public
                   35918:      * @static
                   35919:      */
                   35920:     function &factory($command, &$config)
                   35921:     {
                   35922:         if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
                   35923:             PEAR_Command::registerCommands();
                   35924:         }
                   35925:         if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
                   35926:             $command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
                   35927:         }
                   35928:         if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
                   35929:             $a = PEAR::raiseError("unknown command `$command'");
                   35930:             return $a;
                   35931:         }
                   35932:         $class = $GLOBALS['_PEAR_Command_commandlist'][$command];
                   35933:         if (!class_exists($class)) {
                   35934:             require_once $GLOBALS['_PEAR_Command_objects'][$class];
                   35935:         }
                   35936:         if (!class_exists($class)) {
                   35937:             $a = PEAR::raiseError("unknown command `$command'");
                   35938:             return $a;
                   35939:         }
                   35940:         $ui =& PEAR_Command::getFrontendObject();
                   35941:         $obj = &new $class($ui, $config);
                   35942:         return $obj;
                   35943:     }
                   35944: 
                   35945:     // }}}
                   35946:     // {{{ & getObject()
                   35947:     function &getObject($command)
                   35948:     {
                   35949:         $class = $GLOBALS['_PEAR_Command_commandlist'][$command];
                   35950:         if (!class_exists($class)) {
                   35951:             require_once $GLOBALS['_PEAR_Command_objects'][$class];
                   35952:         }
                   35953:         if (!class_exists($class)) {
                   35954:             return PEAR::raiseError("unknown command `$command'");
                   35955:         }
                   35956:         $ui =& PEAR_Command::getFrontendObject();
                   35957:         $config = &PEAR_Config::singleton();
                   35958:         $obj = &new $class($ui, $config);
                   35959:         return $obj;
                   35960:     }
                   35961: 
                   35962:     // }}}
                   35963:     // {{{ & getFrontendObject()
                   35964: 
                   35965:     /**
                   35966:      * Get instance of frontend object.
                   35967:      *
                   35968:      * @return object|PEAR_Error
                   35969:      * @static
                   35970:      */
                   35971:     function &getFrontendObject()
                   35972:     {
                   35973:         $a = &PEAR_Frontend::singleton();
                   35974:         return $a;
                   35975:     }
                   35976: 
                   35977:     // }}}
                   35978:     // {{{ & setFrontendClass()
                   35979: 
                   35980:     /**
                   35981:      * Load current frontend class.
                   35982:      *
                   35983:      * @param string $uiclass Name of class implementing the frontend
                   35984:      *
                   35985:      * @return object the frontend object, or a PEAR error
                   35986:      * @static
                   35987:      */
                   35988:     function &setFrontendClass($uiclass)
                   35989:     {
                   35990:         $a = &PEAR_Frontend::setFrontendClass($uiclass);
                   35991:         return $a;
                   35992:     }
                   35993: 
                   35994:     // }}}
                   35995:     // {{{ setFrontendType()
                   35996: 
                   35997:     /**
                   35998:      * Set current frontend.
                   35999:      *
                   36000:      * @param string $uitype Name of the frontend type (for example "CLI")
                   36001:      *
                   36002:      * @return object the frontend object, or a PEAR error
                   36003:      * @static
                   36004:      */
                   36005:     function setFrontendType($uitype)
                   36006:     {
                   36007:         $uiclass = 'PEAR_Frontend_' . $uitype;
                   36008:         return PEAR_Command::setFrontendClass($uiclass);
                   36009:     }
                   36010: 
                   36011:     // }}}
                   36012:     // {{{ registerCommands()
                   36013: 
                   36014:     /**
                   36015:      * Scan through the Command directory looking for classes
                   36016:      * and see what commands they implement.
                   36017:      *
                   36018:      * @param bool   (optional) if FALSE (default), the new list of
                   36019:      *               commands should replace the current one.  If TRUE,
                   36020:      *               new entries will be merged with old.
                   36021:      *
                   36022:      * @param string (optional) where (what directory) to look for
                   36023:      *               classes, defaults to the Command subdirectory of
                   36024:      *               the directory from where this file (__FILE__) is
                   36025:      *               included.
                   36026:      *
                   36027:      * @return bool TRUE on success, a PEAR error on failure
                   36028:      *
                   36029:      * @access public
                   36030:      * @static
                   36031:      */
                   36032:     function registerCommands($merge = false, $dir = null)
                   36033:     {
                   36034:         $parser = new PEAR_XMLParser;
                   36035:         if ($dir === null) {
                   36036:             $dir = dirname(__FILE__) . '/Command';
                   36037:         }
                   36038:         if (!is_dir($dir)) {
                   36039:             return PEAR::raiseError("registerCommands: opendir($dir) '$dir' does not exist or is not a directory");
                   36040:         }
                   36041:         $dp = @opendir($dir);
                   36042:         if (empty($dp)) {
                   36043:             return PEAR::raiseError("registerCommands: opendir($dir) failed");
                   36044:         }
                   36045:         if (!$merge) {
                   36046:             $GLOBALS['_PEAR_Command_commandlist'] = array();
                   36047:         }
                   36048: 
                   36049:         while ($file = readdir($dp)) {
                   36050:             if ($file{0} == '.' || substr($file, -4) != '.xml') {
                   36051:                 continue;
                   36052:             }
                   36053: 
                   36054:             $f = substr($file, 0, -4);
                   36055:             $class = "PEAR_Command_" . $f;
                   36056:             // List of commands
                   36057:             if (empty($GLOBALS['_PEAR_Command_objects'][$class])) {
                   36058:                 $GLOBALS['_PEAR_Command_objects'][$class] = "$dir/" . $f . '.php';
                   36059:             }
                   36060: 
                   36061:             $parser->parse(file_get_contents("$dir/$file"));
                   36062:             $implements = $parser->getData();
                   36063:             foreach ($implements as $command => $desc) {
                   36064:                 if ($command == 'attribs') {
                   36065:                     continue;
                   36066:                 }
                   36067: 
                   36068:                 if (isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
                   36069:                     return PEAR::raiseError('Command "' . $command . '" already registered in ' .
                   36070:                         'class "' . $GLOBALS['_PEAR_Command_commandlist'][$command] . '"');
                   36071:                 }
                   36072: 
                   36073:                 $GLOBALS['_PEAR_Command_commandlist'][$command] = $class;
                   36074:                 $GLOBALS['_PEAR_Command_commanddesc'][$command] = $desc['summary'];
                   36075:                 if (isset($desc['shortcut'])) {
                   36076:                     $shortcut = $desc['shortcut'];
                   36077:                     if (isset($GLOBALS['_PEAR_Command_shortcuts'][$shortcut])) {
                   36078:                         return PEAR::raiseError('Command shortcut "' . $shortcut . '" already ' .
                   36079:                             'registered to command "' . $command . '" in class "' .
                   36080:                             $GLOBALS['_PEAR_Command_commandlist'][$command] . '"');
                   36081:                     }
                   36082:                     $GLOBALS['_PEAR_Command_shortcuts'][$shortcut] = $command;
                   36083:                 }
                   36084: 
                   36085:                 if (isset($desc['options']) && $desc['options']) {
                   36086:                     foreach ($desc['options'] as $oname => $option) {
                   36087:                         if (isset($option['shortopt']) && strlen($option['shortopt']) > 1) {
                   36088:                             return PEAR::raiseError('Option "' . $oname . '" short option "' .
                   36089:                                 $option['shortopt'] . '" must be ' .
                   36090:                                 'only 1 character in Command "' . $command . '" in class "' .
                   36091:                                 $class . '"');
                   36092:                         }
                   36093:                     }
                   36094:                 }
                   36095:             }
                   36096:         }
                   36097: 
                   36098:         ksort($GLOBALS['_PEAR_Command_shortcuts']);
                   36099:         ksort($GLOBALS['_PEAR_Command_commandlist']);
                   36100:         @closedir($dp);
                   36101:         return true;
                   36102:     }
                   36103: 
                   36104:     // }}}
                   36105:     // {{{ getCommands()
                   36106: 
                   36107:     /**
                   36108:      * Get the list of currently supported commands, and what
                   36109:      * classes implement them.
                   36110:      *
                   36111:      * @return array command => implementing class
                   36112:      *
                   36113:      * @access public
                   36114:      * @static
                   36115:      */
                   36116:     function getCommands()
                   36117:     {
                   36118:         if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
                   36119:             PEAR_Command::registerCommands();
                   36120:         }
                   36121:         return $GLOBALS['_PEAR_Command_commandlist'];
                   36122:     }
                   36123: 
                   36124:     // }}}
                   36125:     // {{{ getShortcuts()
                   36126: 
                   36127:     /**
                   36128:      * Get the list of command shortcuts.
                   36129:      *
                   36130:      * @return array shortcut => command
                   36131:      *
                   36132:      * @access public
                   36133:      * @static
                   36134:      */
                   36135:     function getShortcuts()
                   36136:     {
                   36137:         if (empty($GLOBALS['_PEAR_Command_shortcuts'])) {
                   36138:             PEAR_Command::registerCommands();
                   36139:         }
                   36140:         return $GLOBALS['_PEAR_Command_shortcuts'];
                   36141:     }
                   36142: 
                   36143:     // }}}
                   36144:     // {{{ getGetoptArgs()
                   36145: 
                   36146:     /**
                   36147:      * Compiles arguments for getopt.
                   36148:      *
                   36149:      * @param string $command     command to get optstring for
                   36150:      * @param string $short_args  (reference) short getopt format
                   36151:      * @param array  $long_args   (reference) long getopt format
                   36152:      *
                   36153:      * @return void
                   36154:      *
                   36155:      * @access public
                   36156:      * @static
                   36157:      */
                   36158:     function getGetoptArgs($command, &$short_args, &$long_args)
                   36159:     {
                   36160:         if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
                   36161:             PEAR_Command::registerCommands();
                   36162:         }
                   36163:         if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
                   36164:             $command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
                   36165:         }
                   36166:         if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
                   36167:             return null;
                   36168:         }
                   36169:         $obj = &PEAR_Command::getObject($command);
                   36170:         return $obj->getGetoptArgs($command, $short_args, $long_args);
                   36171:     }
                   36172: 
                   36173:     // }}}
                   36174:     // {{{ getDescription()
                   36175: 
                   36176:     /**
                   36177:      * Get description for a command.
                   36178:      *
                   36179:      * @param  string $command Name of the command
                   36180:      *
                   36181:      * @return string command description
                   36182:      *
                   36183:      * @access public
                   36184:      * @static
                   36185:      */
                   36186:     function getDescription($command)
                   36187:     {
                   36188:         if (!isset($GLOBALS['_PEAR_Command_commanddesc'][$command])) {
                   36189:             return null;
                   36190:         }
                   36191:         return $GLOBALS['_PEAR_Command_commanddesc'][$command];
                   36192:     }
                   36193: 
                   36194:     // }}}
                   36195:     // {{{ getHelp()
                   36196: 
                   36197:     /**
                   36198:      * Get help for command.
                   36199:      *
                   36200:      * @param string $command Name of the command to return help for
                   36201:      *
                   36202:      * @access public
                   36203:      * @static
                   36204:      */
                   36205:     function getHelp($command)
                   36206:     {
                   36207:         $cmds = PEAR_Command::getCommands();
                   36208:         if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
                   36209:             $command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
                   36210:         }
                   36211:         if (isset($cmds[$command])) {
                   36212:             $obj = &PEAR_Command::getObject($command);
                   36213:             return $obj->getHelp($command);
                   36214:         }
                   36215:         return false;
                   36216:     }
                   36217:     // }}}
1.1.1.2 ! misho    36218: }PEAR-1.9.4/PEAR/Common.php0000644000076500000240000006225511605156614013736 0ustar  helgistaff<?php
1.1       misho    36219: /**
                   36220:  * PEAR_Common, the base class for the PEAR Installer
                   36221:  *
                   36222:  * PHP versions 4 and 5
                   36223:  *
                   36224:  * @category   pear
                   36225:  * @package    PEAR
                   36226:  * @author     Stig Bakken <ssb@php.net>
                   36227:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   36228:  * @author     Greg Beaver <cellog@php.net>
                   36229:  * @copyright  1997-2009 The Authors
                   36230:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   36231:  * @version    CVS: $Id: Common.php 313023 2011-07-06 19:17:11Z dufuz $
                   36232:  * @link       http://pear.php.net/package/PEAR
                   36233:  * @since      File available since Release 0.1.0
                   36234:  * @deprecated File deprecated since Release 1.4.0a1
                   36235:  */
                   36236: 
                   36237: /**
                   36238:  * Include error handling
                   36239:  */
                   36240: require_once 'PEAR.php';
                   36241: 
                   36242: /**
                   36243:  * PEAR_Common error when an invalid PHP file is passed to PEAR_Common::analyzeSourceCode()
                   36244:  */
                   36245: define('PEAR_COMMON_ERROR_INVALIDPHP', 1);
                   36246: define('_PEAR_COMMON_PACKAGE_NAME_PREG', '[A-Za-z][a-zA-Z0-9_]+');
                   36247: define('PEAR_COMMON_PACKAGE_NAME_PREG', '/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/');
                   36248: 
                   36249: // this should allow: 1, 1.0, 1.0RC1, 1.0dev, 1.0dev123234234234, 1.0a1, 1.0b1, 1.0pl1
                   36250: define('_PEAR_COMMON_PACKAGE_VERSION_PREG', '\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?');
                   36251: define('PEAR_COMMON_PACKAGE_VERSION_PREG', '/^' . _PEAR_COMMON_PACKAGE_VERSION_PREG . '\\z/i');
                   36252: 
                   36253: // XXX far from perfect :-)
                   36254: define('_PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '(' . _PEAR_COMMON_PACKAGE_NAME_PREG .
                   36255:     ')(-([.0-9a-zA-Z]+))?');
                   36256: define('PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_PACKAGE_DOWNLOAD_PREG .
                   36257:     '\\z/');
                   36258: 
                   36259: define('_PEAR_CHANNELS_NAME_PREG', '[A-Za-z][a-zA-Z0-9\.]+');
                   36260: define('PEAR_CHANNELS_NAME_PREG', '/^' . _PEAR_CHANNELS_NAME_PREG . '\\z/');
                   36261: 
                   36262: // this should allow any dns or IP address, plus a path - NO UNDERSCORES ALLOWED
                   36263: define('_PEAR_CHANNELS_SERVER_PREG', '[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*(\/[a-zA-Z0-9\-]+)*');
                   36264: define('PEAR_CHANNELS_SERVER_PREG', '/^' . _PEAR_CHANNELS_SERVER_PREG . '\\z/i');
                   36265: 
                   36266: define('_PEAR_CHANNELS_PACKAGE_PREG',  '(' ._PEAR_CHANNELS_SERVER_PREG . ')\/('
                   36267:          . _PEAR_COMMON_PACKAGE_NAME_PREG . ')');
                   36268: define('PEAR_CHANNELS_PACKAGE_PREG', '/^' . _PEAR_CHANNELS_PACKAGE_PREG . '\\z/i');
                   36269: 
                   36270: define('_PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '(' . _PEAR_CHANNELS_NAME_PREG . ')::('
                   36271:     . _PEAR_COMMON_PACKAGE_NAME_PREG . ')(-([.0-9a-zA-Z]+))?');
                   36272: define('PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_CHANNEL_DOWNLOAD_PREG . '\\z/');
                   36273: 
                   36274: /**
                   36275:  * List of temporary files and directories registered by
                   36276:  * PEAR_Common::addTempFile().
                   36277:  * @var array
                   36278:  */
                   36279: $GLOBALS['_PEAR_Common_tempfiles'] = array();
                   36280: 
                   36281: /**
                   36282:  * Valid maintainer roles
                   36283:  * @var array
                   36284:  */
                   36285: $GLOBALS['_PEAR_Common_maintainer_roles'] = array('lead','developer','contributor','helper');
                   36286: 
                   36287: /**
                   36288:  * Valid release states
                   36289:  * @var array
                   36290:  */
                   36291: $GLOBALS['_PEAR_Common_release_states'] = array('alpha','beta','stable','snapshot','devel');
                   36292: 
                   36293: /**
                   36294:  * Valid dependency types
                   36295:  * @var array
                   36296:  */
                   36297: $GLOBALS['_PEAR_Common_dependency_types'] = array('pkg','ext','php','prog','ldlib','rtlib','os','websrv','sapi');
                   36298: 
                   36299: /**
                   36300:  * Valid dependency relations
                   36301:  * @var array
                   36302:  */
                   36303: $GLOBALS['_PEAR_Common_dependency_relations'] = array('has','eq','lt','le','gt','ge','not', 'ne');
                   36304: 
                   36305: /**
                   36306:  * Valid file roles
                   36307:  * @var array
                   36308:  */
                   36309: $GLOBALS['_PEAR_Common_file_roles'] = array('php','ext','test','doc','data','src','script');
                   36310: 
                   36311: /**
                   36312:  * Valid replacement types
                   36313:  * @var array
                   36314:  */
                   36315: $GLOBALS['_PEAR_Common_replacement_types'] = array('php-const', 'pear-config', 'package-info');
                   36316: 
                   36317: /**
                   36318:  * Valid "provide" types
                   36319:  * @var array
                   36320:  */
                   36321: $GLOBALS['_PEAR_Common_provide_types'] = array('ext', 'prog', 'class', 'function', 'feature', 'api');
                   36322: 
                   36323: /**
                   36324:  * Valid "provide" types
                   36325:  * @var array
                   36326:  */
                   36327: $GLOBALS['_PEAR_Common_script_phases'] = array('pre-install', 'post-install', 'pre-uninstall', 'post-uninstall', 'pre-build', 'post-build', 'pre-configure', 'post-configure', 'pre-setup', 'post-setup');
                   36328: 
                   36329: /**
                   36330:  * Class providing common functionality for PEAR administration classes.
                   36331:  * @category   pear
                   36332:  * @package    PEAR
                   36333:  * @author     Stig Bakken <ssb@php.net>
                   36334:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   36335:  * @author     Greg Beaver <cellog@php.net>
                   36336:  * @copyright  1997-2009 The Authors
                   36337:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   36338:  * @version    Release: 1.9.4
                   36339:  * @link       http://pear.php.net/package/PEAR
                   36340:  * @since      Class available since Release 1.4.0a1
                   36341:  * @deprecated This class will disappear, and its components will be spread
                   36342:  *             into smaller classes, like the AT&T breakup, as of Release 1.4.0a1
                   36343:  */
                   36344: class PEAR_Common extends PEAR
                   36345: {
                   36346:     /**
                   36347:      * User Interface object (PEAR_Frontend_* class).  If null,
                   36348:      * the log() method uses print.
                   36349:      * @var object
                   36350:      */
                   36351:     var $ui = null;
                   36352: 
                   36353:     /**
                   36354:      * Configuration object (PEAR_Config).
                   36355:      * @var PEAR_Config
                   36356:      */
                   36357:     var $config = null;
                   36358: 
                   36359:     /** stack of elements, gives some sort of XML context */
                   36360:     var $element_stack = array();
                   36361: 
                   36362:     /** name of currently parsed XML element */
                   36363:     var $current_element;
                   36364: 
                   36365:     /** array of attributes of the currently parsed XML element */
                   36366:     var $current_attributes = array();
                   36367: 
                   36368:     /** assoc with information about a package */
                   36369:     var $pkginfo = array();
                   36370: 
                   36371:     var $current_path = null;
                   36372: 
                   36373:     /**
                   36374:      * Flag variable used to mark a valid package file
                   36375:      * @var boolean
                   36376:      * @access private
                   36377:      */
                   36378:     var $_validPackageFile;
                   36379: 
                   36380:     /**
                   36381:      * PEAR_Common constructor
                   36382:      *
                   36383:      * @access public
                   36384:      */
                   36385:     function PEAR_Common()
                   36386:     {
                   36387:         parent::PEAR();
                   36388:         $this->config = &PEAR_Config::singleton();
                   36389:         $this->debug = $this->config->get('verbose');
                   36390:     }
                   36391: 
                   36392:     /**
                   36393:      * PEAR_Common destructor
                   36394:      *
                   36395:      * @access private
                   36396:      */
                   36397:     function _PEAR_Common()
                   36398:     {
                   36399:         // doesn't work due to bug #14744
                   36400:         //$tempfiles = $this->_tempfiles;
                   36401:         $tempfiles =& $GLOBALS['_PEAR_Common_tempfiles'];
                   36402:         while ($file = array_shift($tempfiles)) {
                   36403:             if (@is_dir($file)) {
                   36404:                 if (!class_exists('System')) {
                   36405:                     require_once 'System.php';
                   36406:                 }
                   36407: 
                   36408:                 System::rm(array('-rf', $file));
                   36409:             } elseif (file_exists($file)) {
                   36410:                 unlink($file);
                   36411:             }
                   36412:         }
                   36413:     }
                   36414: 
                   36415:     /**
                   36416:      * Register a temporary file or directory.  When the destructor is
                   36417:      * executed, all registered temporary files and directories are
                   36418:      * removed.
                   36419:      *
                   36420:      * @param string  $file  name of file or directory
                   36421:      *
                   36422:      * @return void
                   36423:      *
                   36424:      * @access public
                   36425:      */
                   36426:     function addTempFile($file)
                   36427:     {
                   36428:         if (!class_exists('PEAR_Frontend')) {
                   36429:             require_once 'PEAR/Frontend.php';
                   36430:         }
                   36431:         PEAR_Frontend::addTempFile($file);
                   36432:     }
                   36433: 
                   36434:     /**
                   36435:      * Wrapper to System::mkDir(), creates a directory as well as
                   36436:      * any necessary parent directories.
                   36437:      *
                   36438:      * @param string  $dir  directory name
                   36439:      *
                   36440:      * @return bool TRUE on success, or a PEAR error
                   36441:      *
                   36442:      * @access public
                   36443:      */
                   36444:     function mkDirHier($dir)
                   36445:     {
                   36446:         // Only used in Installer - move it there ?
                   36447:         $this->log(2, "+ create dir $dir");
                   36448:         if (!class_exists('System')) {
                   36449:             require_once 'System.php';
                   36450:         }
                   36451:         return System::mkDir(array('-p', $dir));
                   36452:     }
                   36453: 
                   36454:     /**
                   36455:      * Logging method.
                   36456:      *
                   36457:      * @param int    $level  log level (0 is quiet, higher is noisier)
                   36458:      * @param string $msg    message to write to the log
                   36459:      *
                   36460:      * @return void
                   36461:      *
                   36462:      * @access public
                   36463:      * @static
                   36464:      */
                   36465:     function log($level, $msg, $append_crlf = true)
                   36466:     {
                   36467:         if ($this->debug >= $level) {
                   36468:             if (!class_exists('PEAR_Frontend')) {
                   36469:                 require_once 'PEAR/Frontend.php';
                   36470:             }
                   36471: 
                   36472:             $ui = &PEAR_Frontend::singleton();
                   36473:             if (is_a($ui, 'PEAR_Frontend')) {
                   36474:                 $ui->log($msg, $append_crlf);
                   36475:             } else {
                   36476:                 print "$msg\n";
                   36477:             }
                   36478:         }
                   36479:     }
                   36480: 
                   36481:     /**
                   36482:      * Create and register a temporary directory.
                   36483:      *
                   36484:      * @param string $tmpdir (optional) Directory to use as tmpdir.
                   36485:      *                       Will use system defaults (for example
                   36486:      *                       /tmp or c:\windows\temp) if not specified
                   36487:      *
                   36488:      * @return string name of created directory
                   36489:      *
                   36490:      * @access public
                   36491:      */
                   36492:     function mkTempDir($tmpdir = '')
                   36493:     {
                   36494:         $topt = $tmpdir ? array('-t', $tmpdir) : array();
                   36495:         $topt = array_merge($topt, array('-d', 'pear'));
                   36496:         if (!class_exists('System')) {
                   36497:             require_once 'System.php';
                   36498:         }
                   36499: 
                   36500:         if (!$tmpdir = System::mktemp($topt)) {
                   36501:             return false;
                   36502:         }
                   36503: 
                   36504:         $this->addTempFile($tmpdir);
                   36505:         return $tmpdir;
                   36506:     }
                   36507: 
                   36508:     /**
                   36509:      * Set object that represents the frontend to be used.
                   36510:      *
                   36511:      * @param  object Reference of the frontend object
                   36512:      * @return void
                   36513:      * @access public
                   36514:      */
                   36515:     function setFrontendObject(&$ui)
                   36516:     {
                   36517:         $this->ui = &$ui;
                   36518:     }
                   36519: 
                   36520:     /**
                   36521:      * Return an array containing all of the states that are more stable than
                   36522:      * or equal to the passed in state
                   36523:      *
                   36524:      * @param string Release state
                   36525:      * @param boolean Determines whether to include $state in the list
                   36526:      * @return false|array False if $state is not a valid release state
                   36527:      */
                   36528:     function betterStates($state, $include = false)
                   36529:     {
                   36530:         static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
                   36531:         $i = array_search($state, $states);
                   36532:         if ($i === false) {
                   36533:             return false;
                   36534:         }
                   36535:         if ($include) {
                   36536:             $i--;
                   36537:         }
                   36538:         return array_slice($states, $i + 1);
                   36539:     }
                   36540: 
                   36541:     /**
                   36542:      * Get the valid roles for a PEAR package maintainer
                   36543:      *
                   36544:      * @return array
                   36545:      * @static
                   36546:      */
                   36547:     function getUserRoles()
                   36548:     {
                   36549:         return $GLOBALS['_PEAR_Common_maintainer_roles'];
                   36550:     }
                   36551: 
                   36552:     /**
                   36553:      * Get the valid package release states of packages
                   36554:      *
                   36555:      * @return array
                   36556:      * @static
                   36557:      */
                   36558:     function getReleaseStates()
                   36559:     {
                   36560:         return $GLOBALS['_PEAR_Common_release_states'];
                   36561:     }
                   36562: 
                   36563:     /**
                   36564:      * Get the implemented dependency types (php, ext, pkg etc.)
                   36565:      *
                   36566:      * @return array
                   36567:      * @static
                   36568:      */
                   36569:     function getDependencyTypes()
                   36570:     {
                   36571:         return $GLOBALS['_PEAR_Common_dependency_types'];
                   36572:     }
                   36573: 
                   36574:     /**
                   36575:      * Get the implemented dependency relations (has, lt, ge etc.)
                   36576:      *
                   36577:      * @return array
                   36578:      * @static
                   36579:      */
                   36580:     function getDependencyRelations()
                   36581:     {
                   36582:         return $GLOBALS['_PEAR_Common_dependency_relations'];
                   36583:     }
                   36584: 
                   36585:     /**
                   36586:      * Get the implemented file roles
                   36587:      *
                   36588:      * @return array
                   36589:      * @static
                   36590:      */
                   36591:     function getFileRoles()
                   36592:     {
                   36593:         return $GLOBALS['_PEAR_Common_file_roles'];
                   36594:     }
                   36595: 
                   36596:     /**
                   36597:      * Get the implemented file replacement types in
                   36598:      *
                   36599:      * @return array
                   36600:      * @static
                   36601:      */
                   36602:     function getReplacementTypes()
                   36603:     {
                   36604:         return $GLOBALS['_PEAR_Common_replacement_types'];
                   36605:     }
                   36606: 
                   36607:     /**
                   36608:      * Get the implemented file replacement types in
                   36609:      *
                   36610:      * @return array
                   36611:      * @static
                   36612:      */
                   36613:     function getProvideTypes()
                   36614:     {
                   36615:         return $GLOBALS['_PEAR_Common_provide_types'];
                   36616:     }
                   36617: 
                   36618:     /**
                   36619:      * Get the implemented file replacement types in
                   36620:      *
                   36621:      * @return array
                   36622:      * @static
                   36623:      */
                   36624:     function getScriptPhases()
                   36625:     {
                   36626:         return $GLOBALS['_PEAR_Common_script_phases'];
                   36627:     }
                   36628: 
                   36629:     /**
                   36630:      * Test whether a string contains a valid package name.
                   36631:      *
                   36632:      * @param string $name the package name to test
                   36633:      *
                   36634:      * @return bool
                   36635:      *
                   36636:      * @access public
                   36637:      */
                   36638:     function validPackageName($name)
                   36639:     {
                   36640:         return (bool)preg_match(PEAR_COMMON_PACKAGE_NAME_PREG, $name);
                   36641:     }
                   36642: 
                   36643:     /**
                   36644:      * Test whether a string contains a valid package version.
                   36645:      *
                   36646:      * @param string $ver the package version to test
                   36647:      *
                   36648:      * @return bool
                   36649:      *
                   36650:      * @access public
                   36651:      */
                   36652:     function validPackageVersion($ver)
                   36653:     {
                   36654:         return (bool)preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver);
                   36655:     }
                   36656: 
                   36657:     /**
                   36658:      * @param string $path relative or absolute include path
                   36659:      * @return boolean
                   36660:      * @static
                   36661:      */
                   36662:     function isIncludeable($path)
                   36663:     {
                   36664:         if (file_exists($path) && is_readable($path)) {
                   36665:             return true;
                   36666:         }
                   36667: 
                   36668:         $ipath = explode(PATH_SEPARATOR, ini_get('include_path'));
                   36669:         foreach ($ipath as $include) {
                   36670:             $test = realpath($include . DIRECTORY_SEPARATOR . $path);
                   36671:             if (file_exists($test) && is_readable($test)) {
                   36672:                 return true;
                   36673:             }
                   36674:         }
                   36675: 
                   36676:         return false;
                   36677:     }
                   36678: 
                   36679:     function _postProcessChecks($pf)
                   36680:     {
                   36681:         if (!PEAR::isError($pf)) {
                   36682:             return $this->_postProcessValidPackagexml($pf);
                   36683:         }
                   36684: 
                   36685:         $errs = $pf->getUserinfo();
                   36686:         if (is_array($errs)) {
                   36687:             foreach ($errs as $error) {
                   36688:                 $e = $this->raiseError($error['message'], $error['code'], null, null, $error);
                   36689:             }
                   36690:         }
                   36691: 
                   36692:         return $pf;
                   36693:     }
                   36694: 
                   36695:     /**
                   36696:      * Returns information about a package file.  Expects the name of
                   36697:      * a gzipped tar file as input.
                   36698:      *
                   36699:      * @param string  $file  name of .tgz file
                   36700:      *
                   36701:      * @return array  array with package information
                   36702:      *
                   36703:      * @access public
                   36704:      * @deprecated use PEAR_PackageFile->fromTgzFile() instead
                   36705:      *
                   36706:      */
                   36707:     function infoFromTgzFile($file)
                   36708:     {
                   36709:         $packagefile = &new PEAR_PackageFile($this->config);
                   36710:         $pf = &$packagefile->fromTgzFile($file, PEAR_VALIDATE_NORMAL);
                   36711:         return $this->_postProcessChecks($pf);
                   36712:     }
                   36713: 
                   36714:     /**
                   36715:      * Returns information about a package file.  Expects the name of
                   36716:      * a package xml file as input.
                   36717:      *
                   36718:      * @param string  $descfile  name of package xml file
                   36719:      *
                   36720:      * @return array  array with package information
                   36721:      *
                   36722:      * @access public
                   36723:      * @deprecated use PEAR_PackageFile->fromPackageFile() instead
                   36724:      *
                   36725:      */
                   36726:     function infoFromDescriptionFile($descfile)
                   36727:     {
                   36728:         $packagefile = &new PEAR_PackageFile($this->config);
                   36729:         $pf = &$packagefile->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
                   36730:         return $this->_postProcessChecks($pf);
                   36731:     }
                   36732: 
                   36733:     /**
                   36734:      * Returns information about a package file.  Expects the contents
                   36735:      * of a package xml file as input.
                   36736:      *
                   36737:      * @param string  $data  contents of package.xml file
                   36738:      *
                   36739:      * @return array   array with package information
                   36740:      *
                   36741:      * @access public
                   36742:      * @deprecated use PEAR_PackageFile->fromXmlstring() instead
                   36743:      *
                   36744:      */
                   36745:     function infoFromString($data)
                   36746:     {
                   36747:         $packagefile = &new PEAR_PackageFile($this->config);
                   36748:         $pf = &$packagefile->fromXmlString($data, PEAR_VALIDATE_NORMAL, false);
                   36749:         return $this->_postProcessChecks($pf);
                   36750:     }
                   36751: 
                   36752:     /**
                   36753:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   36754:      * @return array
                   36755:      */
                   36756:     function _postProcessValidPackagexml(&$pf)
                   36757:     {
                   36758:         if (!is_a($pf, 'PEAR_PackageFile_v2')) {
                   36759:             $this->pkginfo = $pf->toArray();
                   36760:             return $this->pkginfo;
                   36761:         }
                   36762: 
                   36763:         // sort of make this into a package.xml 1.0-style array
                   36764:         // changelog is not converted to old format.
                   36765:         $arr = $pf->toArray(true);
                   36766:         $arr = array_merge($arr, $arr['old']);
                   36767:         unset($arr['old'], $arr['xsdversion'], $arr['contents'], $arr['compatible'],
                   36768:               $arr['channel'], $arr['uri'], $arr['dependencies'], $arr['phprelease'],
                   36769:               $arr['extsrcrelease'], $arr['zendextsrcrelease'], $arr['extbinrelease'],
                   36770:               $arr['zendextbinrelease'], $arr['bundle'], $arr['lead'], $arr['developer'],
                   36771:               $arr['helper'], $arr['contributor']);
                   36772:         $arr['filelist'] = $pf->getFilelist();
                   36773:         $this->pkginfo = $arr;
                   36774:         return $arr;
                   36775:     }
                   36776: 
                   36777:     /**
                   36778:      * Returns package information from different sources
                   36779:      *
                   36780:      * This method is able to extract information about a package
                   36781:      * from a .tgz archive or from a XML package definition file.
                   36782:      *
                   36783:      * @access public
                   36784:      * @param  string Filename of the source ('package.xml', '<package>.tgz')
                   36785:      * @return string
                   36786:      * @deprecated use PEAR_PackageFile->fromAnyFile() instead
                   36787:      */
                   36788:     function infoFromAny($info)
                   36789:     {
                   36790:         if (is_string($info) && file_exists($info)) {
                   36791:             $packagefile = &new PEAR_PackageFile($this->config);
                   36792:             $pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL);
                   36793:             if (PEAR::isError($pf)) {
                   36794:                 $errs = $pf->getUserinfo();
                   36795:                 if (is_array($errs)) {
                   36796:                     foreach ($errs as $error) {
                   36797:                         $e = $this->raiseError($error['message'], $error['code'], null, null, $error);
                   36798:                     }
                   36799:                 }
                   36800: 
                   36801:                 return $pf;
                   36802:             }
                   36803: 
                   36804:             return $this->_postProcessValidPackagexml($pf);
                   36805:         }
                   36806: 
                   36807:         return $info;
                   36808:     }
                   36809: 
                   36810:     /**
                   36811:      * Return an XML document based on the package info (as returned
                   36812:      * by the PEAR_Common::infoFrom* methods).
                   36813:      *
                   36814:      * @param array  $pkginfo  package info
                   36815:      *
                   36816:      * @return string XML data
                   36817:      *
                   36818:      * @access public
                   36819:      * @deprecated use a PEAR_PackageFile_v* object's generator instead
                   36820:      */
                   36821:     function xmlFromInfo($pkginfo)
                   36822:     {
                   36823:         $config      = &PEAR_Config::singleton();
                   36824:         $packagefile = &new PEAR_PackageFile($config);
                   36825:         $pf = &$packagefile->fromArray($pkginfo);
                   36826:         $gen = &$pf->getDefaultGenerator();
                   36827:         return $gen->toXml(PEAR_VALIDATE_PACKAGING);
                   36828:     }
                   36829: 
                   36830:     /**
                   36831:      * Validate XML package definition file.
                   36832:      *
                   36833:      * @param  string $info Filename of the package archive or of the
                   36834:      *                package definition file
                   36835:      * @param  array $errors Array that will contain the errors
                   36836:      * @param  array $warnings Array that will contain the warnings
                   36837:      * @param  string $dir_prefix (optional) directory where source files
                   36838:      *                may be found, or empty if they are not available
                   36839:      * @access public
                   36840:      * @return boolean
                   36841:      * @deprecated use the validation of PEAR_PackageFile objects
                   36842:      */
                   36843:     function validatePackageInfo($info, &$errors, &$warnings, $dir_prefix = '')
                   36844:     {
                   36845:         $config      = &PEAR_Config::singleton();
                   36846:         $packagefile = &new PEAR_PackageFile($config);
                   36847:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   36848:         if (strpos($info, '<?xml') !== false) {
                   36849:             $pf = &$packagefile->fromXmlString($info, PEAR_VALIDATE_NORMAL, '');
                   36850:         } else {
                   36851:             $pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL);
                   36852:         }
                   36853: 
                   36854:         PEAR::staticPopErrorHandling();
                   36855:         if (PEAR::isError($pf)) {
                   36856:             $errs = $pf->getUserinfo();
                   36857:             if (is_array($errs)) {
                   36858:                 foreach ($errs as $error) {
                   36859:                     if ($error['level'] == 'error') {
                   36860:                         $errors[] = $error['message'];
                   36861:                     } else {
                   36862:                         $warnings[] = $error['message'];
                   36863:                     }
                   36864:                 }
                   36865:             }
                   36866: 
                   36867:             return false;
                   36868:         }
                   36869: 
                   36870:         return true;
                   36871:     }
                   36872: 
                   36873:     /**
                   36874:      * Build a "provides" array from data returned by
                   36875:      * analyzeSourceCode().  The format of the built array is like
                   36876:      * this:
                   36877:      *
                   36878:      *  array(
                   36879:      *    'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
                   36880:      *    ...
                   36881:      *  )
                   36882:      *
                   36883:      *
                   36884:      * @param array $srcinfo array with information about a source file
                   36885:      * as returned by the analyzeSourceCode() method.
                   36886:      *
                   36887:      * @return void
                   36888:      *
                   36889:      * @access public
                   36890:      *
                   36891:      */
                   36892:     function buildProvidesArray($srcinfo)
                   36893:     {
                   36894:         $file = basename($srcinfo['source_file']);
                   36895:         $pn = '';
                   36896:         if (isset($this->_packageName)) {
                   36897:             $pn = $this->_packageName;
                   36898:         }
                   36899: 
                   36900:         $pnl = strlen($pn);
                   36901:         foreach ($srcinfo['declared_classes'] as $class) {
                   36902:             $key = "class;$class";
                   36903:             if (isset($this->pkginfo['provides'][$key])) {
                   36904:                 continue;
                   36905:             }
                   36906: 
                   36907:             $this->pkginfo['provides'][$key] =
                   36908:                 array('file'=> $file, 'type' => 'class', 'name' => $class);
                   36909:             if (isset($srcinfo['inheritance'][$class])) {
                   36910:                 $this->pkginfo['provides'][$key]['extends'] =
                   36911:                     $srcinfo['inheritance'][$class];
                   36912:             }
                   36913:         }
                   36914: 
                   36915:         foreach ($srcinfo['declared_methods'] as $class => $methods) {
                   36916:             foreach ($methods as $method) {
                   36917:                 $function = "$class::$method";
                   36918:                 $key = "function;$function";
                   36919:                 if ($method{0} == '_' || !strcasecmp($method, $class) ||
                   36920:                     isset($this->pkginfo['provides'][$key])) {
                   36921:                     continue;
                   36922:                 }
                   36923: 
                   36924:                 $this->pkginfo['provides'][$key] =
                   36925:                     array('file'=> $file, 'type' => 'function', 'name' => $function);
                   36926:             }
                   36927:         }
                   36928: 
                   36929:         foreach ($srcinfo['declared_functions'] as $function) {
                   36930:             $key = "function;$function";
                   36931:             if ($function{0} == '_' || isset($this->pkginfo['provides'][$key])) {
                   36932:                 continue;
                   36933:             }
                   36934: 
                   36935:             if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
                   36936:                 $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
                   36937:             }
                   36938: 
                   36939:             $this->pkginfo['provides'][$key] =
                   36940:                 array('file'=> $file, 'type' => 'function', 'name' => $function);
                   36941:         }
                   36942:     }
                   36943: 
                   36944:     /**
                   36945:      * Analyze the source code of the given PHP file
                   36946:      *
                   36947:      * @param  string Filename of the PHP file
                   36948:      * @return mixed
                   36949:      * @access public
                   36950:      */
                   36951:     function analyzeSourceCode($file)
                   36952:     {
                   36953:         if (!class_exists('PEAR_PackageFile_v2_Validator')) {
                   36954:             require_once 'PEAR/PackageFile/v2/Validator.php';
                   36955:         }
                   36956: 
                   36957:         $a = new PEAR_PackageFile_v2_Validator;
                   36958:         return $a->analyzeSourceCode($file);
                   36959:     }
                   36960: 
                   36961:     function detectDependencies($any, $status_callback = null)
                   36962:     {
                   36963:         if (!function_exists("token_get_all")) {
                   36964:             return false;
                   36965:         }
                   36966: 
                   36967:         if (PEAR::isError($info = $this->infoFromAny($any))) {
                   36968:             return $this->raiseError($info);
                   36969:         }
                   36970: 
                   36971:         if (!is_array($info)) {
                   36972:             return false;
                   36973:         }
                   36974: 
                   36975:         $deps = array();
                   36976:         $used_c = $decl_c = $decl_f = $decl_m = array();
                   36977:         foreach ($info['filelist'] as $file => $fa) {
                   36978:             $tmp = $this->analyzeSourceCode($file);
                   36979:             $used_c = @array_merge($used_c, $tmp['used_classes']);
                   36980:             $decl_c = @array_merge($decl_c, $tmp['declared_classes']);
                   36981:             $decl_f = @array_merge($decl_f, $tmp['declared_functions']);
                   36982:             $decl_m = @array_merge($decl_m, $tmp['declared_methods']);
                   36983:             $inheri = @array_merge($inheri, $tmp['inheritance']);
                   36984:         }
                   36985: 
                   36986:         $used_c = array_unique($used_c);
                   36987:         $decl_c = array_unique($decl_c);
                   36988:         $undecl_c = array_diff($used_c, $decl_c);
                   36989: 
                   36990:         return array('used_classes' => $used_c,
                   36991:                      'declared_classes' => $decl_c,
                   36992:                      'declared_methods' => $decl_m,
                   36993:                      'declared_functions' => $decl_f,
                   36994:                      'undeclared_classes' => $undecl_c,
                   36995:                      'inheritance' => $inheri,
                   36996:                      );
                   36997:     }
                   36998: 
                   36999:     /**
                   37000:      * Download a file through HTTP.  Considers suggested file name in
                   37001:      * Content-disposition: header and can run a callback function for
                   37002:      * different events.  The callback will be called with two
                   37003:      * parameters: the callback type, and parameters.  The implemented
                   37004:      * callback types are:
                   37005:      *
                   37006:      *  'setup'       called at the very beginning, parameter is a UI object
                   37007:      *                that should be used for all output
                   37008:      *  'message'     the parameter is a string with an informational message
                   37009:      *  'saveas'      may be used to save with a different file name, the
                   37010:      *                parameter is the filename that is about to be used.
                   37011:      *                If a 'saveas' callback returns a non-empty string,
                   37012:      *                that file name will be used as the filename instead.
                   37013:      *                Note that $save_dir will not be affected by this, only
                   37014:      *                the basename of the file.
                   37015:      *  'start'       download is starting, parameter is number of bytes
                   37016:      *                that are expected, or -1 if unknown
                   37017:      *  'bytesread'   parameter is the number of bytes read so far
                   37018:      *  'done'        download is complete, parameter is the total number
                   37019:      *                of bytes read
                   37020:      *  'connfailed'  if the TCP connection fails, this callback is called
                   37021:      *                with array(host,port,errno,errmsg)
                   37022:      *  'writefailed' if writing to disk fails, this callback is called
                   37023:      *                with array(destfile,errmsg)
                   37024:      *
                   37025:      * If an HTTP proxy has been configured (http_proxy PEAR_Config
                   37026:      * setting), the proxy will be used.
                   37027:      *
                   37028:      * @param string  $url       the URL to download
                   37029:      * @param object  $ui        PEAR_Frontend_* instance
                   37030:      * @param object  $config    PEAR_Config instance
                   37031:      * @param string  $save_dir  (optional) directory to save file in
                   37032:      * @param mixed   $callback  (optional) function/method to call for status
                   37033:      *                           updates
                   37034:      *
                   37035:      * @return string  Returns the full path of the downloaded file or a PEAR
                   37036:      *                 error on failure.  If the error is caused by
                   37037:      *                 socket-related errors, the error object will
                   37038:      *                 have the fsockopen error code available through
                   37039:      *                 getCode().
                   37040:      *
                   37041:      * @access public
                   37042:      * @deprecated in favor of PEAR_Downloader::downloadHttp()
                   37043:      */
                   37044:     function downloadHttp($url, &$ui, $save_dir = '.', $callback = null)
                   37045:     {
                   37046:         if (!class_exists('PEAR_Downloader')) {
                   37047:             require_once 'PEAR/Downloader.php';
                   37048:         }
                   37049:         return PEAR_Downloader::downloadHttp($url, $ui, $save_dir, $callback);
                   37050:     }
                   37051: }
                   37052: 
                   37053: require_once 'PEAR/Config.php';
1.1.1.2 ! misho    37054: require_once 'PEAR/PackageFile.php';PEAR-1.9.4/PEAR/Config.php0000644000076500000240000020445211605156614013710 0ustar  helgistaff<?php
1.1       misho    37055: /**
                   37056:  * PEAR_Config, customized configuration handling for the PEAR Installer
                   37057:  *
                   37058:  * PHP versions 4 and 5
                   37059:  *
                   37060:  * @category   pear
                   37061:  * @package    PEAR
                   37062:  * @author     Stig Bakken <ssb@php.net>
                   37063:  * @author     Greg Beaver <cellog@php.net>
                   37064:  * @copyright  1997-2009 The Authors
                   37065:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   37066:  * @version    CVS: $Id: Config.php 313023 2011-07-06 19:17:11Z dufuz $
                   37067:  * @link       http://pear.php.net/package/PEAR
                   37068:  * @since      File available since Release 0.1
                   37069:  */
                   37070: 
                   37071: /**
                   37072:  * Required for error handling
                   37073:  */
                   37074: require_once 'PEAR.php';
                   37075: require_once 'PEAR/Registry.php';
                   37076: require_once 'PEAR/Installer/Role.php';
                   37077: require_once 'System.php';
                   37078: 
                   37079: /**
                   37080:  * Last created PEAR_Config instance.
                   37081:  * @var object
                   37082:  */
                   37083: $GLOBALS['_PEAR_Config_instance'] = null;
                   37084: if (!defined('PEAR_INSTALL_DIR') || !PEAR_INSTALL_DIR) {
                   37085:     $PEAR_INSTALL_DIR = PHP_LIBDIR . DIRECTORY_SEPARATOR . 'pear';
                   37086: } else {
                   37087:     $PEAR_INSTALL_DIR = PEAR_INSTALL_DIR;
                   37088: }
                   37089: 
                   37090: // Below we define constants with default values for all configuration
                   37091: // parameters except username/password.  All of them can have their
                   37092: // defaults set through environment variables.  The reason we use the
                   37093: // PHP_ prefix is for some security, PHP protects environment
                   37094: // variables starting with PHP_*.
                   37095: 
                   37096: // default channel and preferred mirror is based on whether we are invoked through
                   37097: // the "pear" or the "pecl" command
                   37098: if (!defined('PEAR_RUNTYPE')) {
                   37099:     define('PEAR_RUNTYPE', 'pear');
                   37100: }
                   37101: 
                   37102: if (PEAR_RUNTYPE == 'pear') {
                   37103:     define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pear.php.net');
                   37104: } else {
                   37105:     define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pecl.php.net');
                   37106: }
                   37107: 
                   37108: if (getenv('PHP_PEAR_SYSCONF_DIR')) {
                   37109:     define('PEAR_CONFIG_SYSCONFDIR', getenv('PHP_PEAR_SYSCONF_DIR'));
                   37110: } elseif (getenv('SystemRoot')) {
                   37111:     define('PEAR_CONFIG_SYSCONFDIR', getenv('SystemRoot'));
                   37112: } else {
                   37113:     define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR);
                   37114: }
                   37115: 
                   37116: // Default for master_server
                   37117: if (getenv('PHP_PEAR_MASTER_SERVER')) {
                   37118:     define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', getenv('PHP_PEAR_MASTER_SERVER'));
                   37119: } else {
                   37120:     define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', 'pear.php.net');
                   37121: }
                   37122: 
                   37123: // Default for http_proxy
                   37124: if (getenv('PHP_PEAR_HTTP_PROXY')) {
                   37125:     define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('PHP_PEAR_HTTP_PROXY'));
                   37126: } elseif (getenv('http_proxy')) {
                   37127:     define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('http_proxy'));
                   37128: } else {
                   37129:     define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', '');
                   37130: }
                   37131: 
                   37132: // Default for php_dir
                   37133: if (getenv('PHP_PEAR_INSTALL_DIR')) {
                   37134:     define('PEAR_CONFIG_DEFAULT_PHP_DIR', getenv('PHP_PEAR_INSTALL_DIR'));
                   37135: } else {
                   37136:     if (@file_exists($PEAR_INSTALL_DIR) && is_dir($PEAR_INSTALL_DIR)) {
                   37137:         define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR);
                   37138:     } else {
                   37139:         define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR);
                   37140:     }
                   37141: }
                   37142: 
                   37143: // Default for ext_dir
                   37144: if (getenv('PHP_PEAR_EXTENSION_DIR')) {
                   37145:     define('PEAR_CONFIG_DEFAULT_EXT_DIR', getenv('PHP_PEAR_EXTENSION_DIR'));
                   37146: } else {
                   37147:     if (ini_get('extension_dir')) {
                   37148:         define('PEAR_CONFIG_DEFAULT_EXT_DIR', ini_get('extension_dir'));
                   37149:     } elseif (defined('PEAR_EXTENSION_DIR') &&
                   37150:               file_exists(PEAR_EXTENSION_DIR) && is_dir(PEAR_EXTENSION_DIR)) {
                   37151:         define('PEAR_CONFIG_DEFAULT_EXT_DIR', PEAR_EXTENSION_DIR);
                   37152:     } elseif (defined('PHP_EXTENSION_DIR')) {
                   37153:         define('PEAR_CONFIG_DEFAULT_EXT_DIR', PHP_EXTENSION_DIR);
                   37154:     } else {
                   37155:         define('PEAR_CONFIG_DEFAULT_EXT_DIR', '.');
                   37156:     }
                   37157: }
                   37158: 
                   37159: // Default for doc_dir
                   37160: if (getenv('PHP_PEAR_DOC_DIR')) {
                   37161:     define('PEAR_CONFIG_DEFAULT_DOC_DIR', getenv('PHP_PEAR_DOC_DIR'));
                   37162: } else {
                   37163:     define('PEAR_CONFIG_DEFAULT_DOC_DIR',
                   37164:            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'docs');
                   37165: }
                   37166: 
                   37167: // Default for bin_dir
                   37168: if (getenv('PHP_PEAR_BIN_DIR')) {
                   37169:     define('PEAR_CONFIG_DEFAULT_BIN_DIR', getenv('PHP_PEAR_BIN_DIR'));
                   37170: } else {
                   37171:     define('PEAR_CONFIG_DEFAULT_BIN_DIR', PHP_BINDIR);
                   37172: }
                   37173: 
                   37174: // Default for data_dir
                   37175: if (getenv('PHP_PEAR_DATA_DIR')) {
                   37176:     define('PEAR_CONFIG_DEFAULT_DATA_DIR', getenv('PHP_PEAR_DATA_DIR'));
                   37177: } else {
                   37178:     define('PEAR_CONFIG_DEFAULT_DATA_DIR',
                   37179:            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'data');
                   37180: }
                   37181: 
                   37182: // Default for cfg_dir
                   37183: if (getenv('PHP_PEAR_CFG_DIR')) {
                   37184:     define('PEAR_CONFIG_DEFAULT_CFG_DIR', getenv('PHP_PEAR_CFG_DIR'));
                   37185: } else {
                   37186:     define('PEAR_CONFIG_DEFAULT_CFG_DIR',
                   37187:            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'cfg');
                   37188: }
                   37189: 
                   37190: // Default for www_dir
                   37191: if (getenv('PHP_PEAR_WWW_DIR')) {
                   37192:     define('PEAR_CONFIG_DEFAULT_WWW_DIR', getenv('PHP_PEAR_WWW_DIR'));
                   37193: } else {
                   37194:     define('PEAR_CONFIG_DEFAULT_WWW_DIR',
                   37195:            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'www');
                   37196: }
                   37197: 
                   37198: // Default for test_dir
                   37199: if (getenv('PHP_PEAR_TEST_DIR')) {
                   37200:     define('PEAR_CONFIG_DEFAULT_TEST_DIR', getenv('PHP_PEAR_TEST_DIR'));
                   37201: } else {
                   37202:     define('PEAR_CONFIG_DEFAULT_TEST_DIR',
                   37203:            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'tests');
                   37204: }
                   37205: 
                   37206: // Default for temp_dir
                   37207: if (getenv('PHP_PEAR_TEMP_DIR')) {
                   37208:     define('PEAR_CONFIG_DEFAULT_TEMP_DIR', getenv('PHP_PEAR_TEMP_DIR'));
                   37209: } else {
                   37210:     define('PEAR_CONFIG_DEFAULT_TEMP_DIR',
                   37211:            System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
                   37212:            DIRECTORY_SEPARATOR . 'temp');
                   37213: }
                   37214: 
                   37215: // Default for cache_dir
                   37216: if (getenv('PHP_PEAR_CACHE_DIR')) {
                   37217:     define('PEAR_CONFIG_DEFAULT_CACHE_DIR', getenv('PHP_PEAR_CACHE_DIR'));
                   37218: } else {
                   37219:     define('PEAR_CONFIG_DEFAULT_CACHE_DIR',
                   37220:            System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
                   37221:            DIRECTORY_SEPARATOR . 'cache');
                   37222: }
                   37223: 
                   37224: // Default for download_dir
                   37225: if (getenv('PHP_PEAR_DOWNLOAD_DIR')) {
                   37226:     define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR', getenv('PHP_PEAR_DOWNLOAD_DIR'));
                   37227: } else {
                   37228:     define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR',
                   37229:            System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
                   37230:            DIRECTORY_SEPARATOR . 'download');
                   37231: }
                   37232: 
                   37233: // Default for php_bin
                   37234: if (getenv('PHP_PEAR_PHP_BIN')) {
                   37235:     define('PEAR_CONFIG_DEFAULT_PHP_BIN', getenv('PHP_PEAR_PHP_BIN'));
                   37236: } else {
                   37237:     define('PEAR_CONFIG_DEFAULT_PHP_BIN', PEAR_CONFIG_DEFAULT_BIN_DIR.
                   37238:            DIRECTORY_SEPARATOR.'php'.(OS_WINDOWS ? '.exe' : ''));
                   37239: }
                   37240: 
                   37241: // Default for verbose
                   37242: if (getenv('PHP_PEAR_VERBOSE')) {
                   37243:     define('PEAR_CONFIG_DEFAULT_VERBOSE', getenv('PHP_PEAR_VERBOSE'));
                   37244: } else {
                   37245:     define('PEAR_CONFIG_DEFAULT_VERBOSE', 1);
                   37246: }
                   37247: 
                   37248: // Default for preferred_state
                   37249: if (getenv('PHP_PEAR_PREFERRED_STATE')) {
                   37250:     define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', getenv('PHP_PEAR_PREFERRED_STATE'));
                   37251: } else {
                   37252:     define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', 'stable');
                   37253: }
                   37254: 
                   37255: // Default for umask
                   37256: if (getenv('PHP_PEAR_UMASK')) {
                   37257:     define('PEAR_CONFIG_DEFAULT_UMASK', getenv('PHP_PEAR_UMASK'));
                   37258: } else {
                   37259:     define('PEAR_CONFIG_DEFAULT_UMASK', decoct(umask()));
                   37260: }
                   37261: 
                   37262: // Default for cache_ttl
                   37263: if (getenv('PHP_PEAR_CACHE_TTL')) {
                   37264:     define('PEAR_CONFIG_DEFAULT_CACHE_TTL', getenv('PHP_PEAR_CACHE_TTL'));
                   37265: } else {
                   37266:     define('PEAR_CONFIG_DEFAULT_CACHE_TTL', 3600);
                   37267: }
                   37268: 
                   37269: // Default for sig_type
                   37270: if (getenv('PHP_PEAR_SIG_TYPE')) {
                   37271:     define('PEAR_CONFIG_DEFAULT_SIG_TYPE', getenv('PHP_PEAR_SIG_TYPE'));
                   37272: } else {
                   37273:     define('PEAR_CONFIG_DEFAULT_SIG_TYPE', 'gpg');
                   37274: }
                   37275: 
                   37276: // Default for sig_bin
                   37277: if (getenv('PHP_PEAR_SIG_BIN')) {
                   37278:     define('PEAR_CONFIG_DEFAULT_SIG_BIN', getenv('PHP_PEAR_SIG_BIN'));
                   37279: } else {
                   37280:     define('PEAR_CONFIG_DEFAULT_SIG_BIN',
                   37281:            System::which(
                   37282:                'gpg', OS_WINDOWS ? 'c:\gnupg\gpg.exe' : '/usr/local/bin/gpg'));
                   37283: }
                   37284: 
                   37285: // Default for sig_keydir
                   37286: if (getenv('PHP_PEAR_SIG_KEYDIR')) {
                   37287:     define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', getenv('PHP_PEAR_SIG_KEYDIR'));
                   37288: } else {
                   37289:     define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR',
                   37290:            PEAR_CONFIG_SYSCONFDIR . DIRECTORY_SEPARATOR . 'pearkeys');
                   37291: }
                   37292: 
                   37293: /**
                   37294:  * This is a class for storing configuration data, keeping track of
                   37295:  * which are system-defined, user-defined or defaulted.
                   37296:  * @category   pear
                   37297:  * @package    PEAR
                   37298:  * @author     Stig Bakken <ssb@php.net>
                   37299:  * @author     Greg Beaver <cellog@php.net>
                   37300:  * @copyright  1997-2009 The Authors
                   37301:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   37302:  * @version    Release: 1.9.4
                   37303:  * @link       http://pear.php.net/package/PEAR
                   37304:  * @since      Class available since Release 0.1
                   37305:  */
                   37306: class PEAR_Config extends PEAR
                   37307: {
                   37308:     /**
                   37309:      * Array of config files used.
                   37310:      *
                   37311:      * @var array layer => config file
                   37312:      */
                   37313:     var $files = array(
                   37314:         'system' => '',
                   37315:         'user' => '',
                   37316:         );
                   37317: 
                   37318:     var $layers = array();
                   37319: 
                   37320:     /**
                   37321:      * Configuration data, two-dimensional array where the first
                   37322:      * dimension is the config layer ('user', 'system' and 'default'),
                   37323:      * and the second dimension is keyname => value.
                   37324:      *
                   37325:      * The order in the first dimension is important!  Earlier
                   37326:      * layers will shadow later ones when a config value is
                   37327:      * requested (if a 'user' value exists, it will be returned first,
                   37328:      * then 'system' and finally 'default').
                   37329:      *
                   37330:      * @var array layer => array(keyname => value, ...)
                   37331:      */
                   37332:     var $configuration = array(
                   37333:         'user' => array(),
                   37334:         'system' => array(),
                   37335:         'default' => array(),
                   37336:         );
                   37337: 
                   37338:     /**
                   37339:      * Configuration values that can be set for a channel
                   37340:      *
                   37341:      * All other configuration values can only have a global value
                   37342:      * @var array
                   37343:      * @access private
                   37344:      */
                   37345:     var $_channelConfigInfo = array(
                   37346:         'php_dir', 'ext_dir', 'doc_dir', 'bin_dir', 'data_dir', 'cfg_dir',
                   37347:         'test_dir', 'www_dir', 'php_bin', 'php_prefix', 'php_suffix', 'username',
                   37348:         'password', 'verbose', 'preferred_state', 'umask', 'preferred_mirror', 'php_ini'
                   37349:         );
                   37350: 
                   37351:     /**
                   37352:      * Channels that can be accessed
                   37353:      * @see setChannels()
                   37354:      * @var array
                   37355:      * @access private
                   37356:      */
                   37357:     var $_channels = array('pear.php.net', 'pecl.php.net', '__uri');
                   37358: 
                   37359:     /**
                   37360:      * This variable is used to control the directory values returned
                   37361:      * @see setInstallRoot();
                   37362:      * @var string|false
                   37363:      * @access private
                   37364:      */
                   37365:     var $_installRoot = false;
                   37366: 
                   37367:     /**
                   37368:      * If requested, this will always refer to the registry
                   37369:      * contained in php_dir
                   37370:      * @var PEAR_Registry
                   37371:      */
                   37372:     var $_registry = array();
                   37373: 
                   37374:     /**
                   37375:      * @var array
                   37376:      * @access private
                   37377:      */
                   37378:     var $_regInitialized = array();
                   37379: 
                   37380:     /**
                   37381:      * @var bool
                   37382:      * @access private
                   37383:      */
                   37384:     var $_noRegistry = false;
                   37385: 
                   37386:     /**
                   37387:      * amount of errors found while parsing config
                   37388:      * @var integer
                   37389:      * @access private
                   37390:      */
                   37391:     var $_errorsFound = 0;
                   37392:     var $_lastError = null;
                   37393: 
                   37394:     /**
                   37395:      * Information about the configuration data.  Stores the type,
                   37396:      * default value and a documentation string for each configuration
                   37397:      * value.
                   37398:      *
                   37399:      * @var array layer => array(infotype => value, ...)
                   37400:      */
                   37401:     var $configuration_info = array(
                   37402:         // Channels/Internet Access
                   37403:         'default_channel' => array(
                   37404:             'type' => 'string',
                   37405:             'default' => PEAR_CONFIG_DEFAULT_CHANNEL,
                   37406:             'doc' => 'the default channel to use for all non explicit commands',
                   37407:             'prompt' => 'Default Channel',
                   37408:             'group' => 'Internet Access',
                   37409:             ),
                   37410:         'preferred_mirror' => array(
                   37411:             'type' => 'string',
                   37412:             'default' => PEAR_CONFIG_DEFAULT_CHANNEL,
                   37413:             'doc' => 'the default server or mirror to use for channel actions',
                   37414:             'prompt' => 'Default Channel Mirror',
                   37415:             'group' => 'Internet Access',
                   37416:             ),
                   37417:         'remote_config' => array(
                   37418:             'type' => 'password',
                   37419:             'default' => '',
                   37420:             'doc' => 'ftp url of remote configuration file to use for synchronized install',
                   37421:             'prompt' => 'Remote Configuration File',
                   37422:             'group' => 'Internet Access',
                   37423:             ),
                   37424:         'auto_discover' => array(
                   37425:             'type' => 'integer',
                   37426:             'default' => 0,
                   37427:             'doc' => 'whether to automatically discover new channels',
                   37428:             'prompt' => 'Auto-discover new Channels',
                   37429:             'group' => 'Internet Access',
                   37430:             ),
                   37431:         // Internet Access
                   37432:         'master_server' => array(
                   37433:             'type' => 'string',
                   37434:             'default' => 'pear.php.net',
                   37435:             'doc' => 'name of the main PEAR server [NOT USED IN THIS VERSION]',
                   37436:             'prompt' => 'PEAR server [DEPRECATED]',
                   37437:             'group' => 'Internet Access',
                   37438:             ),
                   37439:         'http_proxy' => array(
                   37440:             'type' => 'string',
                   37441:             'default' => PEAR_CONFIG_DEFAULT_HTTP_PROXY,
                   37442:             'doc' => 'HTTP proxy (host:port) to use when downloading packages',
                   37443:             'prompt' => 'HTTP Proxy Server Address',
                   37444:             'group' => 'Internet Access',
                   37445:             ),
                   37446:         // File Locations
                   37447:         'php_dir' => array(
                   37448:             'type' => 'directory',
                   37449:             'default' => PEAR_CONFIG_DEFAULT_PHP_DIR,
                   37450:             'doc' => 'directory where .php files are installed',
                   37451:             'prompt' => 'PEAR directory',
                   37452:             'group' => 'File Locations',
                   37453:             ),
                   37454:         'ext_dir' => array(
                   37455:             'type' => 'directory',
                   37456:             'default' => PEAR_CONFIG_DEFAULT_EXT_DIR,
                   37457:             'doc' => 'directory where loadable extensions are installed',
                   37458:             'prompt' => 'PHP extension directory',
                   37459:             'group' => 'File Locations',
                   37460:             ),
                   37461:         'doc_dir' => array(
                   37462:             'type' => 'directory',
                   37463:             'default' => PEAR_CONFIG_DEFAULT_DOC_DIR,
                   37464:             'doc' => 'directory where documentation is installed',
                   37465:             'prompt' => 'PEAR documentation directory',
                   37466:             'group' => 'File Locations',
                   37467:             ),
                   37468:         'bin_dir' => array(
                   37469:             'type' => 'directory',
                   37470:             'default' => PEAR_CONFIG_DEFAULT_BIN_DIR,
                   37471:             'doc' => 'directory where executables are installed',
                   37472:             'prompt' => 'PEAR executables directory',
                   37473:             'group' => 'File Locations',
                   37474:             ),
                   37475:         'data_dir' => array(
                   37476:             'type' => 'directory',
                   37477:             'default' => PEAR_CONFIG_DEFAULT_DATA_DIR,
                   37478:             'doc' => 'directory where data files are installed',
                   37479:             'prompt' => 'PEAR data directory',
                   37480:             'group' => 'File Locations (Advanced)',
                   37481:             ),
                   37482:         'cfg_dir' => array(
                   37483:             'type' => 'directory',
                   37484:             'default' => PEAR_CONFIG_DEFAULT_CFG_DIR,
                   37485:             'doc' => 'directory where modifiable configuration files are installed',
                   37486:             'prompt' => 'PEAR configuration file directory',
                   37487:             'group' => 'File Locations (Advanced)',
                   37488:             ),
                   37489:         'www_dir' => array(
                   37490:             'type' => 'directory',
                   37491:             'default' => PEAR_CONFIG_DEFAULT_WWW_DIR,
                   37492:             'doc' => 'directory where www frontend files (html/js) are installed',
                   37493:             'prompt' => 'PEAR www files directory',
                   37494:             'group' => 'File Locations (Advanced)',
                   37495:             ),
                   37496:         'test_dir' => array(
                   37497:             'type' => 'directory',
                   37498:             'default' => PEAR_CONFIG_DEFAULT_TEST_DIR,
                   37499:             'doc' => 'directory where regression tests are installed',
                   37500:             'prompt' => 'PEAR test directory',
                   37501:             'group' => 'File Locations (Advanced)',
                   37502:             ),
                   37503:         'cache_dir' => array(
                   37504:             'type' => 'directory',
                   37505:             'default' => PEAR_CONFIG_DEFAULT_CACHE_DIR,
                   37506:             'doc' => 'directory which is used for web service cache',
                   37507:             'prompt' => 'PEAR Installer cache directory',
                   37508:             'group' => 'File Locations (Advanced)',
                   37509:             ),
                   37510:         'temp_dir' => array(
                   37511:             'type' => 'directory',
                   37512:             'default' => PEAR_CONFIG_DEFAULT_TEMP_DIR,
                   37513:             'doc' => 'directory which is used for all temp files',
                   37514:             'prompt' => 'PEAR Installer temp directory',
                   37515:             'group' => 'File Locations (Advanced)',
                   37516:             ),
                   37517:         'download_dir' => array(
                   37518:             'type' => 'directory',
                   37519:             'default' => PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR,
                   37520:             'doc' => 'directory which is used for all downloaded files',
                   37521:             'prompt' => 'PEAR Installer download directory',
                   37522:             'group' => 'File Locations (Advanced)',
                   37523:             ),
                   37524:         'php_bin' => array(
                   37525:             'type' => 'file',
                   37526:             'default' => PEAR_CONFIG_DEFAULT_PHP_BIN,
                   37527:             'doc' => 'PHP CLI/CGI binary for executing scripts',
                   37528:             'prompt' => 'PHP CLI/CGI binary',
                   37529:             'group' => 'File Locations (Advanced)',
                   37530:             ),
                   37531:         'php_prefix' => array(
                   37532:             'type' => 'string',
                   37533:             'default' => '',
                   37534:             'doc' => '--program-prefix for php_bin\'s ./configure, used for pecl installs',
                   37535:             'prompt' => '--program-prefix passed to PHP\'s ./configure',
                   37536:             'group' => 'File Locations (Advanced)',
                   37537:             ),
                   37538:         'php_suffix' => array(
                   37539:             'type' => 'string',
                   37540:             'default' => '',
                   37541:             'doc' => '--program-suffix for php_bin\'s ./configure, used for pecl installs',
                   37542:             'prompt' => '--program-suffix passed to PHP\'s ./configure',
                   37543:             'group' => 'File Locations (Advanced)',
                   37544:             ),
                   37545:         'php_ini' => array(
                   37546:             'type' => 'file',
                   37547:             'default' => '',
                   37548:             'doc' => 'location of php.ini in which to enable PECL extensions on install',
                   37549:             'prompt' => 'php.ini location',
                   37550:             'group' => 'File Locations (Advanced)',
                   37551:             ),
                   37552:         // Maintainers
                   37553:         'username' => array(
                   37554:             'type' => 'string',
                   37555:             'default' => '',
                   37556:             'doc' => '(maintainers) your PEAR account name',
                   37557:             'prompt' => 'PEAR username (for maintainers)',
                   37558:             'group' => 'Maintainers',
                   37559:             ),
                   37560:         'password' => array(
                   37561:             'type' => 'password',
                   37562:             'default' => '',
                   37563:             'doc' => '(maintainers) your PEAR account password',
                   37564:             'prompt' => 'PEAR password (for maintainers)',
                   37565:             'group' => 'Maintainers',
                   37566:             ),
                   37567:         // Advanced
                   37568:         'verbose' => array(
                   37569:             'type' => 'integer',
                   37570:             'default' => PEAR_CONFIG_DEFAULT_VERBOSE,
                   37571:             'doc' => 'verbosity level
                   37572: 0: really quiet
                   37573: 1: somewhat quiet
                   37574: 2: verbose
                   37575: 3: debug',
                   37576:             'prompt' => 'Debug Log Level',
                   37577:             'group' => 'Advanced',
                   37578:             ),
                   37579:         'preferred_state' => array(
                   37580:             'type' => 'set',
                   37581:             'default' => PEAR_CONFIG_DEFAULT_PREFERRED_STATE,
                   37582:             'doc' => 'the installer will prefer releases with this state when installing packages without a version or state specified',
                   37583:             'valid_set' => array(
                   37584:                 'stable', 'beta', 'alpha', 'devel', 'snapshot'),
                   37585:             'prompt' => 'Preferred Package State',
                   37586:             'group' => 'Advanced',
                   37587:             ),
                   37588:         'umask' => array(
                   37589:             'type' => 'mask',
                   37590:             'default' => PEAR_CONFIG_DEFAULT_UMASK,
                   37591:             'doc' => 'umask used when creating files (Unix-like systems only)',
                   37592:             'prompt' => 'Unix file mask',
                   37593:             'group' => 'Advanced',
                   37594:             ),
                   37595:         'cache_ttl' => array(
                   37596:             'type' => 'integer',
                   37597:             'default' => PEAR_CONFIG_DEFAULT_CACHE_TTL,
                   37598:             'doc' => 'amount of secs where the local cache is used and not updated',
                   37599:             'prompt' => 'Cache TimeToLive',
                   37600:             'group' => 'Advanced',
                   37601:             ),
                   37602:         'sig_type' => array(
                   37603:             'type' => 'set',
                   37604:             'default' => PEAR_CONFIG_DEFAULT_SIG_TYPE,
                   37605:             'doc' => 'which package signature mechanism to use',
                   37606:             'valid_set' => array('gpg'),
                   37607:             'prompt' => 'Package Signature Type',
                   37608:             'group' => 'Maintainers',
                   37609:             ),
                   37610:         'sig_bin' => array(
                   37611:             'type' => 'string',
                   37612:             'default' => PEAR_CONFIG_DEFAULT_SIG_BIN,
                   37613:             'doc' => 'which package signature mechanism to use',
                   37614:             'prompt' => 'Signature Handling Program',
                   37615:             'group' => 'Maintainers',
                   37616:             ),
                   37617:         'sig_keyid' => array(
                   37618:             'type' => 'string',
                   37619:             'default' => '',
                   37620:             'doc' => 'which key to use for signing with',
                   37621:             'prompt' => 'Signature Key Id',
                   37622:             'group' => 'Maintainers',
                   37623:             ),
                   37624:         'sig_keydir' => array(
                   37625:             'type' => 'directory',
                   37626:             'default' => PEAR_CONFIG_DEFAULT_SIG_KEYDIR,
                   37627:             'doc' => 'directory where signature keys are located',
                   37628:             'prompt' => 'Signature Key Directory',
                   37629:             'group' => 'Maintainers',
                   37630:             ),
                   37631:         // __channels is reserved - used for channel-specific configuration
                   37632:         );
                   37633: 
                   37634:     /**
                   37635:      * Constructor.
                   37636:      *
                   37637:      * @param string file to read user-defined options from
                   37638:      * @param string file to read system-wide defaults from
                   37639:      * @param bool   determines whether a registry object "follows"
                   37640:      *               the value of php_dir (is automatically created
                   37641:      *               and moved when php_dir is changed)
                   37642:      * @param bool   if true, fails if configuration files cannot be loaded
                   37643:      *
                   37644:      * @access public
                   37645:      *
                   37646:      * @see PEAR_Config::singleton
                   37647:      */
                   37648:     function PEAR_Config($user_file = '', $system_file = '', $ftp_file = false,
                   37649:                          $strict = true)
                   37650:     {
                   37651:         $this->PEAR();
                   37652:         PEAR_Installer_Role::initializeConfig($this);
                   37653:         $sl = DIRECTORY_SEPARATOR;
                   37654:         if (empty($user_file)) {
                   37655:             if (OS_WINDOWS) {
                   37656:                 $user_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini';
                   37657:             } else {
                   37658:                 $user_file = getenv('HOME') . $sl . '.pearrc';
                   37659:             }
                   37660:         }
                   37661: 
                   37662:         if (empty($system_file)) {
                   37663:             $system_file = PEAR_CONFIG_SYSCONFDIR . $sl;
                   37664:             if (OS_WINDOWS) {
                   37665:                 $system_file .= 'pearsys.ini';
                   37666:             } else {
                   37667:                 $system_file .= 'pear.conf';
                   37668:             }
                   37669:         }
                   37670: 
                   37671:         $this->layers = array_keys($this->configuration);
                   37672:         $this->files['user']   = $user_file;
                   37673:         $this->files['system'] = $system_file;
                   37674:         if ($user_file && file_exists($user_file)) {
                   37675:             $this->pushErrorHandling(PEAR_ERROR_RETURN);
                   37676:             $this->readConfigFile($user_file, 'user', $strict);
                   37677:             $this->popErrorHandling();
                   37678:             if ($this->_errorsFound > 0) {
                   37679:                 return;
                   37680:             }
                   37681:         }
                   37682: 
                   37683:         if ($system_file && @file_exists($system_file)) {
                   37684:             $this->mergeConfigFile($system_file, false, 'system', $strict);
                   37685:             if ($this->_errorsFound > 0) {
                   37686:                 return;
                   37687:             }
                   37688: 
                   37689:         }
                   37690: 
                   37691:         if (!$ftp_file) {
                   37692:             $ftp_file = $this->get('remote_config');
                   37693:         }
                   37694: 
                   37695:         if ($ftp_file && defined('PEAR_REMOTEINSTALL_OK')) {
                   37696:             $this->readFTPConfigFile($ftp_file);
                   37697:         }
                   37698: 
                   37699:         foreach ($this->configuration_info as $key => $info) {
                   37700:             $this->configuration['default'][$key] = $info['default'];
                   37701:         }
                   37702: 
                   37703:         $this->_registry['default'] = &new PEAR_Registry($this->configuration['default']['php_dir']);
                   37704:         $this->_registry['default']->setConfig($this, false);
                   37705:         $this->_regInitialized['default'] = false;
                   37706:         //$GLOBALS['_PEAR_Config_instance'] = &$this;
                   37707:     }
                   37708: 
                   37709:     /**
                   37710:      * Return the default locations of user and system configuration files
                   37711:      * @static
                   37712:      */
                   37713:     function getDefaultConfigFiles()
                   37714:     {
                   37715:         $sl = DIRECTORY_SEPARATOR;
                   37716:         if (OS_WINDOWS) {
                   37717:             return array(
                   37718:                 'user'   => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini',
                   37719:                 'system' =>  PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini'
                   37720:             );
                   37721:         }
                   37722: 
                   37723:         return array(
                   37724:             'user'   => getenv('HOME') . $sl . '.pearrc',
                   37725:             'system' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf'
                   37726:         );
                   37727:     }
                   37728: 
                   37729:     /**
                   37730:      * Static singleton method.  If you want to keep only one instance
                   37731:      * of this class in use, this method will give you a reference to
                   37732:      * the last created PEAR_Config object if one exists, or create a
                   37733:      * new object.
                   37734:      *
                   37735:      * @param string (optional) file to read user-defined options from
                   37736:      * @param string (optional) file to read system-wide defaults from
                   37737:      *
                   37738:      * @return object an existing or new PEAR_Config instance
                   37739:      *
                   37740:      * @access public
                   37741:      *
                   37742:      * @see PEAR_Config::PEAR_Config
                   37743:      */
                   37744:     function &singleton($user_file = '', $system_file = '', $strict = true)
                   37745:     {
                   37746:         if (is_object($GLOBALS['_PEAR_Config_instance'])) {
                   37747:             return $GLOBALS['_PEAR_Config_instance'];
                   37748:         }
                   37749: 
                   37750:         $t_conf = &new PEAR_Config($user_file, $system_file, false, $strict);
                   37751:         if ($t_conf->_errorsFound > 0) {
                   37752:              return $t_conf->lastError;
                   37753:         }
                   37754: 
                   37755:         $GLOBALS['_PEAR_Config_instance'] = &$t_conf;
                   37756:         return $GLOBALS['_PEAR_Config_instance'];
                   37757:     }
                   37758: 
                   37759:     /**
                   37760:      * Determine whether any configuration files have been detected, and whether a
                   37761:      * registry object can be retrieved from this configuration.
                   37762:      * @return bool
                   37763:      * @since PEAR 1.4.0a1
                   37764:      */
                   37765:     function validConfiguration()
                   37766:     {
                   37767:         if ($this->isDefinedLayer('user') || $this->isDefinedLayer('system')) {
                   37768:             return true;
                   37769:         }
                   37770: 
                   37771:         return false;
                   37772:     }
                   37773: 
                   37774:     /**
                   37775:      * Reads configuration data from a file.  All existing values in
                   37776:      * the config layer are discarded and replaced with data from the
                   37777:      * file.
                   37778:      * @param string file to read from, if NULL or not specified, the
                   37779:      *               last-used file for the same layer (second param) is used
                   37780:      * @param string config layer to insert data into ('user' or 'system')
                   37781:      * @return bool TRUE on success or a PEAR error on failure
                   37782:      */
                   37783:     function readConfigFile($file = null, $layer = 'user', $strict = true)
                   37784:     {
                   37785:         if (empty($this->files[$layer])) {
                   37786:             return $this->raiseError("unknown config layer `$layer'");
                   37787:         }
                   37788: 
                   37789:         if ($file === null) {
                   37790:             $file = $this->files[$layer];
                   37791:         }
                   37792: 
                   37793:         $data = $this->_readConfigDataFrom($file);
                   37794:         if (PEAR::isError($data)) {
                   37795:             if (!$strict) {
                   37796:                 return true;
                   37797:             }
                   37798: 
                   37799:             $this->_errorsFound++;
                   37800:             $this->lastError = $data;
                   37801: 
                   37802:             return $data;
                   37803:         }
                   37804: 
                   37805:         $this->files[$layer] = $file;
                   37806:         $this->_decodeInput($data);
                   37807:         $this->configuration[$layer] = $data;
                   37808:         $this->_setupChannels();
                   37809:         if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {
                   37810:             $this->_registry[$layer] = &new PEAR_Registry($phpdir);
                   37811:             $this->_registry[$layer]->setConfig($this, false);
                   37812:             $this->_regInitialized[$layer] = false;
                   37813:         } else {
                   37814:             unset($this->_registry[$layer]);
                   37815:         }
                   37816:         return true;
                   37817:     }
                   37818: 
                   37819:     /**
                   37820:      * @param string url to the remote config file, like ftp://www.example.com/pear/config.ini
                   37821:      * @return true|PEAR_Error
                   37822:      */
                   37823:     function readFTPConfigFile($path)
                   37824:     {
                   37825:         do { // poor man's try
                   37826:             if (!class_exists('PEAR_FTP')) {
                   37827:                 if (!class_exists('PEAR_Common')) {
                   37828:                     require_once 'PEAR/Common.php';
                   37829:                 }
                   37830:                 if (PEAR_Common::isIncludeable('PEAR/FTP.php')) {
                   37831:                     require_once 'PEAR/FTP.php';
                   37832:                 }
                   37833:             }
                   37834: 
                   37835:             if (!class_exists('PEAR_FTP')) {
                   37836:                 return PEAR::raiseError('PEAR_RemoteInstaller must be installed to use remote config');
                   37837:             }
                   37838: 
                   37839:             $this->_ftp = &new PEAR_FTP;
                   37840:             $this->_ftp->pushErrorHandling(PEAR_ERROR_RETURN);
                   37841:             $e = $this->_ftp->init($path);
                   37842:             if (PEAR::isError($e)) {
                   37843:                 $this->_ftp->popErrorHandling();
                   37844:                 return $e;
                   37845:             }
                   37846: 
                   37847:             $tmp = System::mktemp('-d');
                   37848:             PEAR_Common::addTempFile($tmp);
                   37849:             $e = $this->_ftp->get(basename($path), $tmp . DIRECTORY_SEPARATOR .
                   37850:                 'pear.ini', false, FTP_BINARY);
                   37851:             if (PEAR::isError($e)) {
                   37852:                 $this->_ftp->popErrorHandling();
                   37853:                 return $e;
                   37854:             }
                   37855: 
                   37856:             PEAR_Common::addTempFile($tmp . DIRECTORY_SEPARATOR . 'pear.ini');
                   37857:             $this->_ftp->disconnect();
                   37858:             $this->_ftp->popErrorHandling();
                   37859:             $this->files['ftp'] = $tmp . DIRECTORY_SEPARATOR . 'pear.ini';
                   37860:             $e = $this->readConfigFile(null, 'ftp');
                   37861:             if (PEAR::isError($e)) {
                   37862:                 return $e;
                   37863:             }
                   37864: 
                   37865:             $fail = array();
                   37866:             foreach ($this->configuration_info as $key => $val) {
                   37867:                 if (in_array($this->getGroup($key),
                   37868:                       array('File Locations', 'File Locations (Advanced)')) &&
                   37869:                       $this->getType($key) == 'directory') {
                   37870:                     // any directory configs must be set for this to work
                   37871:                     if (!isset($this->configuration['ftp'][$key])) {
                   37872:                         $fail[] = $key;
                   37873:                     }
                   37874:                 }
                   37875:             }
                   37876: 
                   37877:             if (!count($fail)) {
                   37878:                 return true;
                   37879:             }
                   37880: 
                   37881:             $fail = '"' . implode('", "', $fail) . '"';
                   37882:             unset($this->files['ftp']);
                   37883:             unset($this->configuration['ftp']);
                   37884:             return PEAR::raiseError('ERROR: Ftp configuration file must set all ' .
                   37885:                 'directory configuration variables.  These variables were not set: ' .
                   37886:                 $fail);
                   37887:         } while (false); // poor man's catch
                   37888:         unset($this->files['ftp']);
                   37889:         return PEAR::raiseError('no remote host specified');
                   37890:     }
                   37891: 
                   37892:     /**
                   37893:      * Reads the existing configurations and creates the _channels array from it
                   37894:      */
                   37895:     function _setupChannels()
                   37896:     {
                   37897:         $set = array_flip(array_values($this->_channels));
                   37898:         foreach ($this->configuration as $layer => $data) {
                   37899:             $i = 1000;
                   37900:             if (isset($data['__channels']) && is_array($data['__channels'])) {
                   37901:                 foreach ($data['__channels'] as $channel => $info) {
                   37902:                     $set[$channel] = $i++;
                   37903:                 }
                   37904:             }
                   37905:         }
                   37906:         $this->_channels = array_values(array_flip($set));
                   37907:         $this->setChannels($this->_channels);
                   37908:     }
                   37909: 
                   37910:     function deleteChannel($channel)
                   37911:     {
                   37912:         $ch = strtolower($channel);
                   37913:         foreach ($this->configuration as $layer => $data) {
                   37914:             if (isset($data['__channels']) && isset($data['__channels'][$ch])) {
                   37915:                 unset($this->configuration[$layer]['__channels'][$ch]);
                   37916:             }
                   37917:         }
                   37918: 
                   37919:         $this->_channels = array_flip($this->_channels);
                   37920:         unset($this->_channels[$ch]);
                   37921:         $this->_channels = array_flip($this->_channels);
                   37922:     }
                   37923: 
                   37924:     /**
                   37925:      * Merges data into a config layer from a file.  Does the same
                   37926:      * thing as readConfigFile, except it does not replace all
                   37927:      * existing values in the config layer.
                   37928:      * @param string file to read from
                   37929:      * @param bool whether to overwrite existing data (default TRUE)
                   37930:      * @param string config layer to insert data into ('user' or 'system')
                   37931:      * @param string if true, errors are returned if file opening fails
                   37932:      * @return bool TRUE on success or a PEAR error on failure
                   37933:      */
                   37934:     function mergeConfigFile($file, $override = true, $layer = 'user', $strict = true)
                   37935:     {
                   37936:         if (empty($this->files[$layer])) {
                   37937:             return $this->raiseError("unknown config layer `$layer'");
                   37938:         }
                   37939: 
                   37940:         if ($file === null) {
                   37941:             $file = $this->files[$layer];
                   37942:         }
                   37943: 
                   37944:         $data = $this->_readConfigDataFrom($file);
                   37945:         if (PEAR::isError($data)) {
                   37946:             if (!$strict) {
                   37947:                 return true;
                   37948:             }
                   37949: 
                   37950:             $this->_errorsFound++;
                   37951:             $this->lastError = $data;
                   37952: 
                   37953:             return $data;
                   37954:         }
                   37955: 
                   37956:         $this->_decodeInput($data);
                   37957:         if ($override) {
                   37958:             $this->configuration[$layer] =
                   37959:                 PEAR_Config::arrayMergeRecursive($this->configuration[$layer], $data);
                   37960:         } else {
                   37961:             $this->configuration[$layer] =
                   37962:                 PEAR_Config::arrayMergeRecursive($data, $this->configuration[$layer]);
                   37963:         }
                   37964: 
                   37965:         $this->_setupChannels();
                   37966:         if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {
                   37967:             $this->_registry[$layer] = &new PEAR_Registry($phpdir);
                   37968:             $this->_registry[$layer]->setConfig($this, false);
                   37969:             $this->_regInitialized[$layer] = false;
                   37970:         } else {
                   37971:             unset($this->_registry[$layer]);
                   37972:         }
                   37973:         return true;
                   37974:     }
                   37975: 
                   37976:     /**
                   37977:      * @param array
                   37978:      * @param array
                   37979:      * @return array
                   37980:      * @static
                   37981:      */
                   37982:     function arrayMergeRecursive($arr2, $arr1)
                   37983:     {
                   37984:         $ret = array();
                   37985:         foreach ($arr2 as $key => $data) {
                   37986:             if (!isset($arr1[$key])) {
                   37987:                 $ret[$key] = $data;
                   37988:                 unset($arr1[$key]);
                   37989:                 continue;
                   37990:             }
                   37991:             if (is_array($data)) {
                   37992:                 if (!is_array($arr1[$key])) {
                   37993:                     $ret[$key] = $arr1[$key];
                   37994:                     unset($arr1[$key]);
                   37995:                     continue;
                   37996:                 }
                   37997:                 $ret[$key] = PEAR_Config::arrayMergeRecursive($arr1[$key], $arr2[$key]);
                   37998:                 unset($arr1[$key]);
                   37999:             }
                   38000:         }
                   38001: 
                   38002:         return array_merge($ret, $arr1);
                   38003:     }
                   38004: 
                   38005:     /**
                   38006:      * Writes data into a config layer from a file.
                   38007:      *
                   38008:      * @param string|null file to read from, or null for default
                   38009:      * @param string config layer to insert data into ('user' or
                   38010:      *               'system')
                   38011:      * @param string|null data to write to config file or null for internal data [DEPRECATED]
                   38012:      * @return bool TRUE on success or a PEAR error on failure
                   38013:      */
                   38014:     function writeConfigFile($file = null, $layer = 'user', $data = null)
                   38015:     {
                   38016:         $this->_lazyChannelSetup($layer);
                   38017:         if ($layer == 'both' || $layer == 'all') {
                   38018:             foreach ($this->files as $type => $file) {
                   38019:                 $err = $this->writeConfigFile($file, $type, $data);
                   38020:                 if (PEAR::isError($err)) {
                   38021:                     return $err;
                   38022:                 }
                   38023:             }
                   38024:             return true;
                   38025:         }
                   38026: 
                   38027:         if (empty($this->files[$layer])) {
                   38028:             return $this->raiseError("unknown config file type `$layer'");
                   38029:         }
                   38030: 
                   38031:         if ($file === null) {
                   38032:             $file = $this->files[$layer];
                   38033:         }
                   38034: 
                   38035:         $data = ($data === null) ? $this->configuration[$layer] : $data;
                   38036:         $this->_encodeOutput($data);
                   38037:         $opt = array('-p', dirname($file));
                   38038:         if (!@System::mkDir($opt)) {
                   38039:             return $this->raiseError("could not create directory: " . dirname($file));
                   38040:         }
                   38041: 
                   38042:         if (file_exists($file) && is_file($file) && !is_writeable($file)) {
                   38043:             return $this->raiseError("no write access to $file!");
                   38044:         }
                   38045: 
                   38046:         $fp = @fopen($file, "w");
                   38047:         if (!$fp) {
                   38048:             return $this->raiseError("PEAR_Config::writeConfigFile fopen('$file','w') failed ($php_errormsg)");
                   38049:         }
                   38050: 
                   38051:         $contents = "#PEAR_Config 0.9\n" . serialize($data);
                   38052:         if (!@fwrite($fp, $contents)) {
                   38053:             return $this->raiseError("PEAR_Config::writeConfigFile: fwrite failed ($php_errormsg)");
                   38054:         }
                   38055:         return true;
                   38056:     }
                   38057: 
                   38058:     /**
                   38059:      * Reads configuration data from a file and returns the parsed data
                   38060:      * in an array.
                   38061:      *
                   38062:      * @param string file to read from
                   38063:      * @return array configuration data or a PEAR error on failure
                   38064:      * @access private
                   38065:      */
                   38066:     function _readConfigDataFrom($file)
                   38067:     {
                   38068:         $fp = false;
                   38069:         if (file_exists($file)) {
                   38070:             $fp = @fopen($file, "r");
                   38071:         }
                   38072: 
                   38073:         if (!$fp) {
                   38074:             return $this->raiseError("PEAR_Config::readConfigFile fopen('$file','r') failed");
                   38075:         }
                   38076: 
                   38077:         $size = filesize($file);
                   38078:         $rt = get_magic_quotes_runtime();
                   38079:         set_magic_quotes_runtime(0);
                   38080:         fclose($fp);
                   38081:         $contents = file_get_contents($file);
                   38082:         if (empty($contents)) {
                   38083:             return $this->raiseError('Configuration file "' . $file . '" is empty');
                   38084:         }
                   38085: 
                   38086:         set_magic_quotes_runtime($rt);
                   38087: 
                   38088:         $version = false;
                   38089:         if (preg_match('/^#PEAR_Config\s+(\S+)\s+/si', $contents, $matches)) {
                   38090:             $version = $matches[1];
                   38091:             $contents = substr($contents, strlen($matches[0]));
                   38092:         } else {
                   38093:             // Museum config file
                   38094:             if (substr($contents,0,2) == 'a:') {
                   38095:                 $version = '0.1';
                   38096:             }
                   38097:         }
                   38098: 
                   38099:         if ($version && version_compare("$version", '1', '<')) {
                   38100:             // no '@', it is possible that unserialize
                   38101:             // raises a notice but it seems to block IO to
                   38102:             // STDOUT if a '@' is used and a notice is raise
                   38103:             $data = unserialize($contents);
                   38104: 
                   38105:             if (!is_array($data) && !$data) {
                   38106:                 if ($contents == serialize(false)) {
                   38107:                     $data = array();
                   38108:                 } else {
                   38109:                     $err = $this->raiseError("PEAR_Config: bad data in $file");
                   38110:                     return $err;
                   38111:                 }
                   38112:             }
                   38113:             if (!is_array($data)) {
                   38114:                 if (strlen(trim($contents)) > 0) {
                   38115:                     $error = "PEAR_Config: bad data in $file";
                   38116:                     $err = $this->raiseError($error);
                   38117:                     return $err;
                   38118:                 }
                   38119: 
                   38120:                 $data = array();
                   38121:             }
                   38122:         // add parsing of newer formats here...
                   38123:         } else {
                   38124:             $err = $this->raiseError("$file: unknown version `$version'");
                   38125:             return $err;
                   38126:         }
                   38127: 
                   38128:         return $data;
                   38129:     }
                   38130: 
                   38131:     /**
                   38132:     * Gets the file used for storing the config for a layer
                   38133:     *
                   38134:     * @param string $layer 'user' or 'system'
                   38135:     */
                   38136:     function getConfFile($layer)
                   38137:     {
                   38138:         return $this->files[$layer];
                   38139:     }
                   38140: 
                   38141:     /**
                   38142:      * @param string Configuration class name, used for detecting duplicate calls
                   38143:      * @param array information on a role as parsed from its xml file
                   38144:      * @return true|PEAR_Error
                   38145:      * @access private
                   38146:      */
                   38147:     function _addConfigVars($class, $vars)
                   38148:     {
                   38149:         static $called = array();
                   38150:         if (isset($called[$class])) {
                   38151:             return;
                   38152:         }
                   38153: 
                   38154:         $called[$class] = 1;
                   38155:         if (count($vars) > 3) {
                   38156:             return $this->raiseError('Roles can only define 3 new config variables or less');
                   38157:         }
                   38158: 
                   38159:         foreach ($vars as $name => $var) {
                   38160:             if (!is_array($var)) {
                   38161:                 return $this->raiseError('Configuration information must be an array');
                   38162:             }
                   38163: 
                   38164:             if (!isset($var['type'])) {
                   38165:                 return $this->raiseError('Configuration information must contain a type');
                   38166:             } elseif (!in_array($var['type'],
                   38167:                     array('string', 'mask', 'password', 'directory', 'file', 'set'))) {
                   38168:                   return $this->raiseError(
                   38169:                       'Configuration type must be one of directory, file, string, ' .
                   38170:                       'mask, set, or password');
                   38171:             }
                   38172:             if (!isset($var['default'])) {
                   38173:                 return $this->raiseError(
                   38174:                     'Configuration information must contain a default value ("default" index)');
                   38175:             }
                   38176: 
                   38177:             if (is_array($var['default'])) {
                   38178:                 $real_default = '';
                   38179:                 foreach ($var['default'] as $config_var => $val) {
                   38180:                     if (strpos($config_var, 'text') === 0) {
                   38181:                         $real_default .= $val;
                   38182:                     } elseif (strpos($config_var, 'constant') === 0) {
                   38183:                         if (!defined($val)) {
                   38184:                             return $this->raiseError(
                   38185:                                 'Unknown constant "' . $val . '" requested in ' .
                   38186:                                 'default value for configuration variable "' .
                   38187:                                 $name . '"');
                   38188:                         }
                   38189: 
                   38190:                         $real_default .= constant($val);
                   38191:                     } elseif (isset($this->configuration_info[$config_var])) {
                   38192:                         $real_default .=
                   38193:                             $this->configuration_info[$config_var]['default'];
                   38194:                     } else {
                   38195:                         return $this->raiseError(
                   38196:                             'Unknown request for "' . $config_var . '" value in ' .
                   38197:                             'default value for configuration variable "' .
                   38198:                             $name . '"');
                   38199:                     }
                   38200:                 }
                   38201:                 $var['default'] = $real_default;
                   38202:             }
                   38203: 
                   38204:             if ($var['type'] == 'integer') {
                   38205:                 $var['default'] = (integer) $var['default'];
                   38206:             }
                   38207: 
                   38208:             if (!isset($var['doc'])) {
                   38209:                 return $this->raiseError(
                   38210:                     'Configuration information must contain a summary ("doc" index)');
                   38211:             }
                   38212: 
                   38213:             if (!isset($var['prompt'])) {
                   38214:                 return $this->raiseError(
                   38215:                     'Configuration information must contain a simple prompt ("prompt" index)');
                   38216:             }
                   38217: 
                   38218:             if (!isset($var['group'])) {
                   38219:                 return $this->raiseError(
                   38220:                     'Configuration information must contain a simple group ("group" index)');
                   38221:             }
                   38222: 
                   38223:             if (isset($this->configuration_info[$name])) {
                   38224:                 return $this->raiseError('Configuration variable "' . $name .
                   38225:                     '" already exists');
                   38226:             }
                   38227: 
                   38228:             $this->configuration_info[$name] = $var;
                   38229:             // fix bug #7351: setting custom config variable in a channel fails
                   38230:             $this->_channelConfigInfo[] = $name;
                   38231:         }
                   38232: 
                   38233:         return true;
                   38234:     }
                   38235: 
                   38236:     /**
                   38237:      * Encodes/scrambles configuration data before writing to files.
                   38238:      * Currently, 'password' values will be base64-encoded as to avoid
                   38239:      * that people spot cleartext passwords by accident.
                   38240:      *
                   38241:      * @param array (reference) array to encode values in
                   38242:      * @return bool TRUE on success
                   38243:      * @access private
                   38244:      */
                   38245:     function _encodeOutput(&$data)
                   38246:     {
                   38247:         foreach ($data as $key => $value) {
                   38248:             if ($key == '__channels') {
                   38249:                 foreach ($data['__channels'] as $channel => $blah) {
                   38250:                     $this->_encodeOutput($data['__channels'][$channel]);
                   38251:                 }
                   38252:             }
                   38253: 
                   38254:             if (!isset($this->configuration_info[$key])) {
                   38255:                 continue;
                   38256:             }
                   38257: 
                   38258:             $type = $this->configuration_info[$key]['type'];
                   38259:             switch ($type) {
                   38260:                 // we base64-encode passwords so they are at least
                   38261:                 // not shown in plain by accident
                   38262:                 case 'password': {
                   38263:                     $data[$key] = base64_encode($data[$key]);
                   38264:                     break;
                   38265:                 }
                   38266:                 case 'mask': {
                   38267:                     $data[$key] = octdec($data[$key]);
                   38268:                     break;
                   38269:                 }
                   38270:             }
                   38271:         }
                   38272: 
                   38273:         return true;
                   38274:     }
                   38275: 
                   38276:     /**
                   38277:      * Decodes/unscrambles configuration data after reading from files.
                   38278:      *
                   38279:      * @param array (reference) array to encode values in
                   38280:      * @return bool TRUE on success
                   38281:      * @access private
                   38282:      *
                   38283:      * @see PEAR_Config::_encodeOutput
                   38284:      */
                   38285:     function _decodeInput(&$data)
                   38286:     {
                   38287:         if (!is_array($data)) {
                   38288:             return true;
                   38289:         }
                   38290: 
                   38291:         foreach ($data as $key => $value) {
                   38292:             if ($key == '__channels') {
                   38293:                 foreach ($data['__channels'] as $channel => $blah) {
                   38294:                     $this->_decodeInput($data['__channels'][$channel]);
                   38295:                 }
                   38296:             }
                   38297: 
                   38298:             if (!isset($this->configuration_info[$key])) {
                   38299:                 continue;
                   38300:             }
                   38301: 
                   38302:             $type = $this->configuration_info[$key]['type'];
                   38303:             switch ($type) {
                   38304:                 case 'password': {
                   38305:                     $data[$key] = base64_decode($data[$key]);
                   38306:                     break;
                   38307:                 }
                   38308:                 case 'mask': {
                   38309:                     $data[$key] = decoct($data[$key]);
                   38310:                     break;
                   38311:                 }
                   38312:             }
                   38313:         }
                   38314: 
                   38315:         return true;
                   38316:     }
                   38317: 
                   38318:     /**
                   38319:      * Retrieve the default channel.
                   38320:      *
                   38321:      * On startup, channels are not initialized, so if the default channel is not
                   38322:      * pear.php.net, then initialize the config.
                   38323:      * @param string registry layer
                   38324:      * @return string|false
                   38325:      */
                   38326:     function getDefaultChannel($layer = null)
                   38327:     {
                   38328:         $ret = false;
                   38329:         if ($layer === null) {
                   38330:             foreach ($this->layers as $layer) {
                   38331:                 if (isset($this->configuration[$layer]['default_channel'])) {
                   38332:                     $ret = $this->configuration[$layer]['default_channel'];
                   38333:                     break;
                   38334:                 }
                   38335:             }
                   38336:         } elseif (isset($this->configuration[$layer]['default_channel'])) {
                   38337:             $ret = $this->configuration[$layer]['default_channel'];
                   38338:         }
                   38339: 
                   38340:         if ($ret == 'pear.php.net' && defined('PEAR_RUNTYPE') && PEAR_RUNTYPE == 'pecl') {
                   38341:             $ret = 'pecl.php.net';
                   38342:         }
                   38343: 
                   38344:         if ($ret) {
                   38345:             if ($ret != 'pear.php.net') {
                   38346:                 $this->_lazyChannelSetup();
                   38347:             }
                   38348: 
                   38349:             return $ret;
                   38350:         }
                   38351: 
                   38352:         return PEAR_CONFIG_DEFAULT_CHANNEL;
                   38353:     }
                   38354: 
                   38355:     /**
                   38356:      * Returns a configuration value, prioritizing layers as per the
                   38357:      * layers property.
                   38358:      *
                   38359:      * @param string config key
                   38360:      * @return mixed the config value, or NULL if not found
                   38361:      * @access public
                   38362:      */
                   38363:     function get($key, $layer = null, $channel = false)
                   38364:     {
                   38365:         if (!isset($this->configuration_info[$key])) {
                   38366:             return null;
                   38367:         }
                   38368: 
                   38369:         if ($key == '__channels') {
                   38370:             return null;
                   38371:         }
                   38372: 
                   38373:         if ($key == 'default_channel') {
                   38374:             return $this->getDefaultChannel($layer);
                   38375:         }
                   38376: 
                   38377:         if (!$channel) {
                   38378:             $channel = $this->getDefaultChannel();
                   38379:         } elseif ($channel != 'pear.php.net') {
                   38380:             $this->_lazyChannelSetup();
                   38381:         }
                   38382:         $channel = strtolower($channel);
                   38383: 
                   38384:         $test = (in_array($key, $this->_channelConfigInfo)) ?
                   38385:             $this->_getChannelValue($key, $layer, $channel) :
                   38386:             null;
                   38387:         if ($test !== null) {
                   38388:             if ($this->_installRoot) {
                   38389:                 if (in_array($this->getGroup($key),
                   38390:                       array('File Locations', 'File Locations (Advanced)')) &&
                   38391:                       $this->getType($key) == 'directory') {
                   38392:                     return $this->_prependPath($test, $this->_installRoot);
                   38393:                 }
                   38394:             }
                   38395:             return $test;
                   38396:         }
                   38397: 
                   38398:         if ($layer === null) {
                   38399:             foreach ($this->layers as $layer) {
                   38400:                 if (isset($this->configuration[$layer][$key])) {
                   38401:                     $test = $this->configuration[$layer][$key];
                   38402:                     if ($this->_installRoot) {
                   38403:                         if (in_array($this->getGroup($key),
                   38404:                               array('File Locations', 'File Locations (Advanced)')) &&
                   38405:                               $this->getType($key) == 'directory') {
                   38406:                             return $this->_prependPath($test, $this->_installRoot);
                   38407:                         }
                   38408:                     }
                   38409: 
                   38410:                     if ($key == 'preferred_mirror') {
                   38411:                         $reg = &$this->getRegistry();
                   38412:                         if (is_object($reg)) {
                   38413:                             $chan = &$reg->getChannel($channel);
                   38414:                             if (PEAR::isError($chan)) {
                   38415:                                 return $channel;
                   38416:                             }
                   38417: 
                   38418:                             if (!$chan->getMirror($test) && $chan->getName() != $test) {
                   38419:                                 return $channel; // mirror does not exist
                   38420:                             }
                   38421:                         }
                   38422:                     }
                   38423:                     return $test;
                   38424:                 }
                   38425:             }
                   38426:         } elseif (isset($this->configuration[$layer][$key])) {
                   38427:             $test = $this->configuration[$layer][$key];
                   38428:             if ($this->_installRoot) {
                   38429:                 if (in_array($this->getGroup($key),
                   38430:                       array('File Locations', 'File Locations (Advanced)')) &&
                   38431:                       $this->getType($key) == 'directory') {
                   38432:                     return $this->_prependPath($test, $this->_installRoot);
                   38433:                 }
                   38434:             }
                   38435: 
                   38436:             if ($key == 'preferred_mirror') {
                   38437:                 $reg = &$this->getRegistry();
                   38438:                 if (is_object($reg)) {
                   38439:                     $chan = &$reg->getChannel($channel);
                   38440:                     if (PEAR::isError($chan)) {
                   38441:                         return $channel;
                   38442:                     }
                   38443: 
                   38444:                     if (!$chan->getMirror($test) && $chan->getName() != $test) {
                   38445:                         return $channel; // mirror does not exist
                   38446:                     }
                   38447:                 }
                   38448:             }
                   38449: 
                   38450:             return $test;
                   38451:         }
                   38452: 
                   38453:         return null;
                   38454:     }
                   38455: 
                   38456:     /**
                   38457:      * Returns a channel-specific configuration value, prioritizing layers as per the
                   38458:      * layers property.
                   38459:      *
                   38460:      * @param string config key
                   38461:      * @return mixed the config value, or NULL if not found
                   38462:      * @access private
                   38463:      */
                   38464:     function _getChannelValue($key, $layer, $channel)
                   38465:     {
                   38466:         if ($key == '__channels' || $channel == 'pear.php.net') {
                   38467:             return null;
                   38468:         }
                   38469: 
                   38470:         $ret = null;
                   38471:         if ($layer === null) {
                   38472:             foreach ($this->layers as $ilayer) {
                   38473:                 if (isset($this->configuration[$ilayer]['__channels'][$channel][$key])) {
                   38474:                     $ret = $this->configuration[$ilayer]['__channels'][$channel][$key];
                   38475:                     break;
                   38476:                 }
                   38477:             }
                   38478:         } elseif (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
                   38479:             $ret = $this->configuration[$layer]['__channels'][$channel][$key];
                   38480:         }
                   38481: 
                   38482:         if ($key != 'preferred_mirror') {
                   38483:             return $ret;
                   38484:         }
                   38485: 
                   38486: 
                   38487:         if ($ret !== null) {
                   38488:             $reg = &$this->getRegistry($layer);
                   38489:             if (is_object($reg)) {
                   38490:                 $chan = &$reg->getChannel($channel);
                   38491:                 if (PEAR::isError($chan)) {
                   38492:                     return $channel;
                   38493:                 }
                   38494: 
                   38495:                 if (!$chan->getMirror($ret) && $chan->getName() != $ret) {
                   38496:                     return $channel; // mirror does not exist
                   38497:                 }
                   38498:             }
                   38499: 
                   38500:             return $ret;
                   38501:         }
                   38502: 
                   38503:         if ($channel != $this->getDefaultChannel($layer)) {
                   38504:             return $channel; // we must use the channel name as the preferred mirror
                   38505:                              // if the user has not chosen an alternate
                   38506:         }
                   38507: 
                   38508:         return $this->getDefaultChannel($layer);
                   38509:     }
                   38510: 
                   38511:     /**
                   38512:      * Set a config value in a specific layer (defaults to 'user').
                   38513:      * Enforces the types defined in the configuration_info array.  An
                   38514:      * integer config variable will be cast to int, and a set config
                   38515:      * variable will be validated against its legal values.
                   38516:      *
                   38517:      * @param string config key
                   38518:      * @param string config value
                   38519:      * @param string (optional) config layer
                   38520:      * @param string channel to set this value for, or null for global value
                   38521:      * @return bool TRUE on success, FALSE on failure
                   38522:      */
                   38523:     function set($key, $value, $layer = 'user', $channel = false)
                   38524:     {
                   38525:         if ($key == '__channels') {
                   38526:             return false;
                   38527:         }
                   38528: 
                   38529:         if (!isset($this->configuration[$layer])) {
                   38530:             return false;
                   38531:         }
                   38532: 
                   38533:         if ($key == 'default_channel') {
                   38534:             // can only set this value globally
                   38535:             $channel = 'pear.php.net';
                   38536:             if ($value != 'pear.php.net') {
                   38537:                 $this->_lazyChannelSetup($layer);
                   38538:             }
                   38539:         }
                   38540: 
                   38541:         if ($key == 'preferred_mirror') {
                   38542:             if ($channel == '__uri') {
                   38543:                 return false; // can't set the __uri pseudo-channel's mirror
                   38544:             }
                   38545: 
                   38546:             $reg = &$this->getRegistry($layer);
                   38547:             if (is_object($reg)) {
                   38548:                 $chan = &$reg->getChannel($channel ? $channel : 'pear.php.net');
                   38549:                 if (PEAR::isError($chan)) {
                   38550:                     return false;
                   38551:                 }
                   38552: 
                   38553:                 if (!$chan->getMirror($value) && $chan->getName() != $value) {
                   38554:                     return false; // mirror does not exist
                   38555:                 }
                   38556:             }
                   38557:         }
                   38558: 
                   38559:         if (!isset($this->configuration_info[$key])) {
                   38560:             return false;
                   38561:         }
                   38562: 
                   38563:         extract($this->configuration_info[$key]);
                   38564:         switch ($type) {
                   38565:             case 'integer':
                   38566:                 $value = (int)$value;
                   38567:                 break;
                   38568:             case 'set': {
                   38569:                 // If a valid_set is specified, require the value to
                   38570:                 // be in the set.  If there is no valid_set, accept
                   38571:                 // any value.
                   38572:                 if ($valid_set) {
                   38573:                     reset($valid_set);
                   38574:                     if ((key($valid_set) === 0 && !in_array($value, $valid_set)) ||
                   38575:                         (key($valid_set) !== 0 && empty($valid_set[$value])))
                   38576:                     {
                   38577:                         return false;
                   38578:                     }
                   38579:                 }
                   38580:                 break;
                   38581:             }
                   38582:         }
                   38583: 
                   38584:         if (!$channel) {
                   38585:             $channel = $this->get('default_channel', null, 'pear.php.net');
                   38586:         }
                   38587: 
                   38588:         if (!in_array($channel, $this->_channels)) {
                   38589:             $this->_lazyChannelSetup($layer);
                   38590:             $reg = &$this->getRegistry($layer);
                   38591:             if ($reg) {
                   38592:                 $channel = $reg->channelName($channel);
                   38593:             }
                   38594: 
                   38595:             if (!in_array($channel, $this->_channels)) {
                   38596:                 return false;
                   38597:             }
                   38598:         }
                   38599: 
                   38600:         if ($channel != 'pear.php.net') {
                   38601:             if (in_array($key, $this->_channelConfigInfo)) {
                   38602:                 $this->configuration[$layer]['__channels'][$channel][$key] = $value;
                   38603:                 return true;
                   38604:             }
                   38605: 
                   38606:             return false;
                   38607:         }
                   38608: 
                   38609:         if ($key == 'default_channel') {
                   38610:             if (!isset($reg)) {
                   38611:                 $reg = &$this->getRegistry($layer);
                   38612:                 if (!$reg) {
                   38613:                     $reg = &$this->getRegistry();
                   38614:                 }
                   38615:             }
                   38616: 
                   38617:             if ($reg) {
                   38618:                 $value = $reg->channelName($value);
                   38619:             }
                   38620: 
                   38621:             if (!$value) {
                   38622:                 return false;
                   38623:             }
                   38624:         }
                   38625: 
                   38626:         $this->configuration[$layer][$key] = $value;
                   38627:         if ($key == 'php_dir' && !$this->_noRegistry) {
                   38628:             if (!isset($this->_registry[$layer]) ||
                   38629:                   $value != $this->_registry[$layer]->install_dir) {
                   38630:                 $this->_registry[$layer] = &new PEAR_Registry($value);
                   38631:                 $this->_regInitialized[$layer] = false;
                   38632:                 $this->_registry[$layer]->setConfig($this, false);
                   38633:             }
                   38634:         }
                   38635: 
                   38636:         return true;
                   38637:     }
                   38638: 
                   38639:     function _lazyChannelSetup($uselayer = false)
                   38640:     {
                   38641:         if ($this->_noRegistry) {
                   38642:             return;
                   38643:         }
                   38644: 
                   38645:         $merge = false;
                   38646:         foreach ($this->_registry as $layer => $p) {
                   38647:             if ($uselayer && $uselayer != $layer) {
                   38648:                 continue;
                   38649:             }
                   38650: 
                   38651:             if (!$this->_regInitialized[$layer]) {
                   38652:                 if ($layer == 'default' && isset($this->_registry['user']) ||
                   38653:                       isset($this->_registry['system'])) {
                   38654:                     // only use the default registry if there are no alternatives
                   38655:                     continue;
                   38656:                 }
                   38657: 
                   38658:                 if (!is_object($this->_registry[$layer])) {
                   38659:                     if ($phpdir = $this->get('php_dir', $layer, 'pear.php.net')) {
                   38660:                         $this->_registry[$layer] = &new PEAR_Registry($phpdir);
                   38661:                         $this->_registry[$layer]->setConfig($this, false);
                   38662:                         $this->_regInitialized[$layer] = false;
                   38663:                     } else {
                   38664:                         unset($this->_registry[$layer]);
                   38665:                         return;
                   38666:                     }
                   38667:                 }
                   38668: 
                   38669:                 $this->setChannels($this->_registry[$layer]->listChannels(), $merge);
                   38670:                 $this->_regInitialized[$layer] = true;
                   38671:                 $merge = true;
                   38672:             }
                   38673:         }
                   38674:     }
                   38675: 
                   38676:     /**
                   38677:      * Set the list of channels.
                   38678:      *
                   38679:      * This should be set via a call to {@link PEAR_Registry::listChannels()}
                   38680:      * @param array
                   38681:      * @param bool
                   38682:      * @return bool success of operation
                   38683:      */
                   38684:     function setChannels($channels, $merge = false)
                   38685:     {
                   38686:         if (!is_array($channels)) {
                   38687:             return false;
                   38688:         }
                   38689: 
                   38690:         if ($merge) {
                   38691:             $this->_channels = array_merge($this->_channels, $channels);
                   38692:         } else {
                   38693:             $this->_channels = $channels;
                   38694:         }
                   38695: 
                   38696:         foreach ($channels as $channel) {
                   38697:             $channel = strtolower($channel);
                   38698:             if ($channel == 'pear.php.net') {
                   38699:                 continue;
                   38700:             }
                   38701: 
                   38702:             foreach ($this->layers as $layer) {
                   38703:                 if (!isset($this->configuration[$layer]['__channels'])) {
                   38704:                     $this->configuration[$layer]['__channels'] = array();
                   38705:                 }
                   38706:                 if (!isset($this->configuration[$layer]['__channels'][$channel])
                   38707:                       || !is_array($this->configuration[$layer]['__channels'][$channel])) {
                   38708:                     $this->configuration[$layer]['__channels'][$channel] = array();
                   38709:                 }
                   38710:             }
                   38711:         }
                   38712: 
                   38713:         return true;
                   38714:     }
                   38715: 
                   38716:     /**
                   38717:      * Get the type of a config value.
                   38718:      *
                   38719:      * @param string  config key
                   38720:      *
                   38721:      * @return string type, one of "string", "integer", "file",
                   38722:      * "directory", "set" or "password".
                   38723:      *
                   38724:      * @access public
                   38725:      *
                   38726:      */
                   38727:     function getType($key)
                   38728:     {
                   38729:         if (isset($this->configuration_info[$key])) {
                   38730:             return $this->configuration_info[$key]['type'];
                   38731:         }
                   38732:         return false;
                   38733:     }
                   38734: 
                   38735:     /**
                   38736:      * Get the documentation for a config value.
                   38737:      *
                   38738:      * @param string  config key
                   38739:      * @return string documentation string
                   38740:      *
                   38741:      * @access public
                   38742:      *
                   38743:      */
                   38744:     function getDocs($key)
                   38745:     {
                   38746:         if (isset($this->configuration_info[$key])) {
                   38747:             return $this->configuration_info[$key]['doc'];
                   38748:         }
                   38749: 
                   38750:         return false;
                   38751:     }
                   38752: 
                   38753:     /**
                   38754:      * Get the short documentation for a config value.
                   38755:      *
                   38756:      * @param string  config key
                   38757:      * @return string short documentation string
                   38758:      *
                   38759:      * @access public
                   38760:      *
                   38761:      */
                   38762:     function getPrompt($key)
                   38763:     {
                   38764:         if (isset($this->configuration_info[$key])) {
                   38765:             return $this->configuration_info[$key]['prompt'];
                   38766:         }
                   38767: 
                   38768:         return false;
                   38769:     }
                   38770: 
                   38771:     /**
                   38772:      * Get the parameter group for a config key.
                   38773:      *
                   38774:      * @param string  config key
                   38775:      * @return string parameter group
                   38776:      *
                   38777:      * @access public
                   38778:      *
                   38779:      */
                   38780:     function getGroup($key)
                   38781:     {
                   38782:         if (isset($this->configuration_info[$key])) {
                   38783:             return $this->configuration_info[$key]['group'];
                   38784:         }
                   38785: 
                   38786:         return false;
                   38787:     }
                   38788: 
                   38789:     /**
                   38790:      * Get the list of parameter groups.
                   38791:      *
                   38792:      * @return array list of parameter groups
                   38793:      *
                   38794:      * @access public
                   38795:      *
                   38796:      */
                   38797:     function getGroups()
                   38798:     {
                   38799:         $tmp = array();
                   38800:         foreach ($this->configuration_info as $key => $info) {
                   38801:             $tmp[$info['group']] = 1;
                   38802:         }
                   38803: 
                   38804:         return array_keys($tmp);
                   38805:     }
                   38806: 
                   38807:     /**
                   38808:      * Get the list of the parameters in a group.
                   38809:      *
                   38810:      * @param string $group parameter group
                   38811:      * @return array list of parameters in $group
                   38812:      *
                   38813:      * @access public
                   38814:      *
                   38815:      */
                   38816:     function getGroupKeys($group)
                   38817:     {
                   38818:         $keys = array();
                   38819:         foreach ($this->configuration_info as $key => $info) {
                   38820:             if ($info['group'] == $group) {
                   38821:                 $keys[] = $key;
                   38822:             }
                   38823:         }
                   38824: 
                   38825:         return $keys;
                   38826:     }
                   38827: 
                   38828:     /**
                   38829:      * Get the list of allowed set values for a config value.  Returns
                   38830:      * NULL for config values that are not sets.
                   38831:      *
                   38832:      * @param string  config key
                   38833:      * @return array enumerated array of set values, or NULL if the
                   38834:      *               config key is unknown or not a set
                   38835:      *
                   38836:      * @access public
                   38837:      *
                   38838:      */
                   38839:     function getSetValues($key)
                   38840:     {
                   38841:         if (isset($this->configuration_info[$key]) &&
                   38842:             isset($this->configuration_info[$key]['type']) &&
                   38843:             $this->configuration_info[$key]['type'] == 'set')
                   38844:         {
                   38845:             $valid_set = $this->configuration_info[$key]['valid_set'];
                   38846:             reset($valid_set);
                   38847:             if (key($valid_set) === 0) {
                   38848:                 return $valid_set;
                   38849:             }
                   38850: 
                   38851:             return array_keys($valid_set);
                   38852:         }
                   38853: 
                   38854:         return null;
                   38855:     }
                   38856: 
                   38857:     /**
                   38858:      * Get all the current config keys.
                   38859:      *
                   38860:      * @return array simple array of config keys
                   38861:      *
                   38862:      * @access public
                   38863:      */
                   38864:     function getKeys()
                   38865:     {
                   38866:         $keys = array();
                   38867:         foreach ($this->layers as $layer) {
                   38868:             $test = $this->configuration[$layer];
                   38869:             if (isset($test['__channels'])) {
                   38870:                 foreach ($test['__channels'] as $channel => $configs) {
                   38871:                     $keys = array_merge($keys, $configs);
                   38872:                 }
                   38873:             }
                   38874: 
                   38875:             unset($test['__channels']);
                   38876:             $keys = array_merge($keys, $test);
                   38877: 
                   38878:         }
                   38879:         return array_keys($keys);
                   38880:     }
                   38881: 
                   38882:     /**
                   38883:      * Remove the a config key from a specific config layer.
                   38884:      *
                   38885:      * @param string config key
                   38886:      * @param string (optional) config layer
                   38887:      * @param string (optional) channel (defaults to default channel)
                   38888:      * @return bool TRUE on success, FALSE on failure
                   38889:      *
                   38890:      * @access public
                   38891:      */
                   38892:     function remove($key, $layer = 'user', $channel = null)
                   38893:     {
                   38894:         if ($channel === null) {
                   38895:             $channel = $this->getDefaultChannel();
                   38896:         }
                   38897: 
                   38898:         if ($channel !== 'pear.php.net') {
                   38899:             if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
                   38900:                 unset($this->configuration[$layer]['__channels'][$channel][$key]);
                   38901:                 return true;
                   38902:             }
                   38903:         }
                   38904: 
                   38905:         if (isset($this->configuration[$layer][$key])) {
                   38906:             unset($this->configuration[$layer][$key]);
                   38907:             return true;
                   38908:         }
                   38909: 
                   38910:         return false;
                   38911:     }
                   38912: 
                   38913:     /**
                   38914:      * Temporarily remove an entire config layer.  USE WITH CARE!
                   38915:      *
                   38916:      * @param string config key
                   38917:      * @param string (optional) config layer
                   38918:      * @return bool TRUE on success, FALSE on failure
                   38919:      *
                   38920:      * @access public
                   38921:      */
                   38922:     function removeLayer($layer)
                   38923:     {
                   38924:         if (isset($this->configuration[$layer])) {
                   38925:             $this->configuration[$layer] = array();
                   38926:             return true;
                   38927:         }
                   38928: 
                   38929:         return false;
                   38930:     }
                   38931: 
                   38932:     /**
                   38933:      * Stores configuration data in a layer.
                   38934:      *
                   38935:      * @param string config layer to store
                   38936:      * @return bool TRUE on success, or PEAR error on failure
                   38937:      *
                   38938:      * @access public
                   38939:      */
                   38940:     function store($layer = 'user', $data = null)
                   38941:     {
                   38942:         return $this->writeConfigFile(null, $layer, $data);
                   38943:     }
                   38944: 
                   38945:     /**
                   38946:      * Tells what config layer that gets to define a key.
                   38947:      *
                   38948:      * @param string config key
                   38949:      * @param boolean return the defining channel
                   38950:      *
                   38951:      * @return string|array the config layer, or an empty string if not found.
                   38952:      *
                   38953:      *         if $returnchannel, the return is an array array('layer' => layername,
                   38954:      *         'channel' => channelname), or an empty string if not found
                   38955:      *
                   38956:      * @access public
                   38957:      */
                   38958:     function definedBy($key, $returnchannel = false)
                   38959:     {
                   38960:         foreach ($this->layers as $layer) {
                   38961:             $channel = $this->getDefaultChannel();
                   38962:             if ($channel !== 'pear.php.net') {
                   38963:                 if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
                   38964:                     if ($returnchannel) {
                   38965:                         return array('layer' => $layer, 'channel' => $channel);
                   38966:                     }
                   38967:                     return $layer;
                   38968:                 }
                   38969:             }
                   38970: 
                   38971:             if (isset($this->configuration[$layer][$key])) {
                   38972:                 if ($returnchannel) {
                   38973:                     return array('layer' => $layer, 'channel' => 'pear.php.net');
                   38974:                 }
                   38975:                 return $layer;
                   38976:             }
                   38977:         }
                   38978: 
                   38979:         return '';
                   38980:     }
                   38981: 
                   38982:     /**
                   38983:      * Tells whether a given key exists as a config value.
                   38984:      *
                   38985:      * @param string config key
                   38986:      * @return bool whether <config key> exists in this object
                   38987:      *
                   38988:      * @access public
                   38989:      */
                   38990:     function isDefined($key)
                   38991:     {
                   38992:         foreach ($this->layers as $layer) {
                   38993:             if (isset($this->configuration[$layer][$key])) {
                   38994:                 return true;
                   38995:             }
                   38996:         }
                   38997: 
                   38998:         return false;
                   38999:     }
                   39000: 
                   39001:     /**
                   39002:      * Tells whether a given config layer exists.
                   39003:      *
                   39004:      * @param string config layer
                   39005:      * @return bool whether <config layer> exists in this object
                   39006:      *
                   39007:      * @access public
                   39008:      */
                   39009:     function isDefinedLayer($layer)
                   39010:     {
                   39011:         return isset($this->configuration[$layer]);
                   39012:     }
                   39013: 
                   39014:     /**
                   39015:      * Returns the layers defined (except the 'default' one)
                   39016:      *
                   39017:      * @return array of the defined layers
                   39018:      */
                   39019:     function getLayers()
                   39020:     {
                   39021:         $cf = $this->configuration;
                   39022:         unset($cf['default']);
                   39023:         return array_keys($cf);
                   39024:     }
                   39025: 
                   39026:     function apiVersion()
                   39027:     {
                   39028:         return '1.1';
                   39029:     }
                   39030: 
                   39031:     /**
                   39032:      * @return PEAR_Registry
                   39033:      */
                   39034:     function &getRegistry($use = null)
                   39035:     {
                   39036:         $layer = $use === null ? 'user' : $use;
                   39037:         if (isset($this->_registry[$layer])) {
                   39038:             return $this->_registry[$layer];
                   39039:         } elseif ($use === null && isset($this->_registry['system'])) {
                   39040:             return $this->_registry['system'];
                   39041:         } elseif ($use === null && isset($this->_registry['default'])) {
                   39042:             return $this->_registry['default'];
                   39043:         } elseif ($use) {
                   39044:             $a = false;
                   39045:             return $a;
                   39046:         }
                   39047: 
                   39048:         // only go here if null was passed in
                   39049:         echo "CRITICAL ERROR: Registry could not be initialized from any value";
                   39050:         exit(1);
                   39051:     }
                   39052: 
                   39053:     /**
                   39054:      * This is to allow customization like the use of installroot
                   39055:      * @param PEAR_Registry
                   39056:      * @return bool
                   39057:      */
                   39058:     function setRegistry(&$reg, $layer = 'user')
                   39059:     {
                   39060:         if ($this->_noRegistry) {
                   39061:             return false;
                   39062:         }
                   39063: 
                   39064:         if (!in_array($layer, array('user', 'system'))) {
                   39065:             return false;
                   39066:         }
                   39067: 
                   39068:         $this->_registry[$layer] = &$reg;
                   39069:         if (is_object($reg)) {
                   39070:             $this->_registry[$layer]->setConfig($this, false);
                   39071:         }
                   39072: 
                   39073:         return true;
                   39074:     }
                   39075: 
                   39076:     function noRegistry()
                   39077:     {
                   39078:         $this->_noRegistry = true;
                   39079:     }
                   39080: 
                   39081:     /**
                   39082:      * @return PEAR_REST
                   39083:      */
                   39084:     function &getREST($version, $options = array())
                   39085:     {
                   39086:         $version = str_replace('.', '', $version);
                   39087:         if (!class_exists($class = 'PEAR_REST_' . $version)) {
                   39088:             require_once 'PEAR/REST/' . $version . '.php';
                   39089:         }
                   39090: 
                   39091:         $remote = &new $class($this, $options);
                   39092:         return $remote;
                   39093:     }
                   39094: 
                   39095:     /**
                   39096:      * The ftp server is set in {@link readFTPConfigFile()}.  It exists only if a
                   39097:      * remote configuration file has been specified
                   39098:      * @return PEAR_FTP|false
                   39099:      */
                   39100:     function &getFTP()
                   39101:     {
                   39102:         if (isset($this->_ftp)) {
                   39103:             return $this->_ftp;
                   39104:         }
                   39105: 
                   39106:         $a = false;
                   39107:         return $a;
                   39108:     }
                   39109: 
                   39110:     function _prependPath($path, $prepend)
                   39111:     {
                   39112:         if (strlen($prepend) > 0) {
                   39113:             if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) {
                   39114:                 if (preg_match('/^[a-z]:/i', $prepend)) {
                   39115:                     $prepend = substr($prepend, 2);
                   39116:                 } elseif ($prepend{0} != '\\') {
                   39117:                     $prepend = "\\$prepend";
                   39118:                 }
                   39119:                 $path = substr($path, 0, 2) . $prepend . substr($path, 2);
                   39120:             } else {
                   39121:                 $path = $prepend . $path;
                   39122:             }
                   39123:         }
                   39124:         return $path;
                   39125:     }
                   39126: 
                   39127:     /**
                   39128:      * @param string|false installation directory to prepend to all _dir variables, or false to
                   39129:      *                     disable
                   39130:      */
                   39131:     function setInstallRoot($root)
                   39132:     {
                   39133:         if (substr($root, -1) == DIRECTORY_SEPARATOR) {
                   39134:             $root = substr($root, 0, -1);
                   39135:         }
                   39136:         $old = $this->_installRoot;
                   39137:         $this->_installRoot = $root;
                   39138:         if (($old != $root) && !$this->_noRegistry) {
                   39139:             foreach (array_keys($this->_registry) as $layer) {
                   39140:                 if ($layer == 'ftp' || !isset($this->_registry[$layer])) {
                   39141:                     continue;
                   39142:                 }
                   39143:                 $this->_registry[$layer] =
                   39144:                     &new PEAR_Registry($this->get('php_dir', $layer, 'pear.php.net'));
                   39145:                 $this->_registry[$layer]->setConfig($this, false);
                   39146:                 $this->_regInitialized[$layer] = false;
                   39147:             }
                   39148:         }
                   39149:     }
                   39150: }
1.1.1.2 ! misho    39151: PEAR-1.9.4/PEAR/DependencyDB.php0000644000076500000240000005725611605156614014777 0ustar  helgistaff<?php
1.1       misho    39152: /**
                   39153:  * PEAR_DependencyDB, advanced installed packages dependency database
                   39154:  *
                   39155:  * PHP versions 4 and 5
                   39156:  *
                   39157:  * @category   pear
                   39158:  * @package    PEAR
                   39159:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   39160:  * @author     Greg Beaver <cellog@php.net>
                   39161:  * @copyright  1997-2009 The Authors
                   39162:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   39163:  * @version    CVS: $Id: DependencyDB.php 313023 2011-07-06 19:17:11Z dufuz $
                   39164:  * @link       http://pear.php.net/package/PEAR
                   39165:  * @since      File available since Release 1.4.0a1
                   39166:  */
                   39167: 
                   39168: /**
                   39169:  * Needed for error handling
                   39170:  */
                   39171: require_once 'PEAR.php';
                   39172: require_once 'PEAR/Config.php';
                   39173: 
                   39174: $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'] = array();
                   39175: /**
                   39176:  * Track dependency relationships between installed packages
                   39177:  * @category   pear
                   39178:  * @package    PEAR
                   39179:  * @author     Greg Beaver <cellog@php.net>
                   39180:  * @author     Tomas V.V.Cox <cox@idec.net.com>
                   39181:  * @copyright  1997-2009 The Authors
                   39182:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   39183:  * @version    Release: 1.9.4
                   39184:  * @link       http://pear.php.net/package/PEAR
                   39185:  * @since      Class available since Release 1.4.0a1
                   39186:  */
                   39187: class PEAR_DependencyDB
                   39188: {
                   39189:     // {{{ properties
                   39190: 
                   39191:     /**
                   39192:      * This is initialized by {@link setConfig()}
                   39193:      * @var PEAR_Config
                   39194:      * @access private
                   39195:      */
                   39196:     var $_config;
                   39197:     /**
                   39198:      * This is initialized by {@link setConfig()}
                   39199:      * @var PEAR_Registry
                   39200:      * @access private
                   39201:      */
                   39202:     var $_registry;
                   39203:     /**
                   39204:      * Filename of the dependency DB (usually .depdb)
                   39205:      * @var string
                   39206:      * @access private
                   39207:      */
                   39208:     var $_depdb = false;
                   39209:     /**
                   39210:      * File name of the lockfile (usually .depdblock)
                   39211:      * @var string
                   39212:      * @access private
                   39213:      */
                   39214:     var $_lockfile = false;
                   39215:     /**
                   39216:      * Open file resource for locking the lockfile
                   39217:      * @var resource|false
                   39218:      * @access private
                   39219:      */
                   39220:     var $_lockFp = false;
                   39221:     /**
                   39222:      * API version of this class, used to validate a file on-disk
                   39223:      * @var string
                   39224:      * @access private
                   39225:      */
                   39226:     var $_version = '1.0';
                   39227:     /**
                   39228:      * Cached dependency database file
                   39229:      * @var array|null
                   39230:      * @access private
                   39231:      */
                   39232:     var $_cache;
                   39233: 
                   39234:     // }}}
                   39235:     // {{{ & singleton()
                   39236: 
                   39237:     /**
                   39238:      * Get a raw dependency database.  Calls setConfig() and assertDepsDB()
                   39239:      * @param PEAR_Config
                   39240:      * @param string|false full path to the dependency database, or false to use default
                   39241:      * @return PEAR_DependencyDB|PEAR_Error
                   39242:      * @static
                   39243:      */
                   39244:     function &singleton(&$config, $depdb = false)
                   39245:     {
                   39246:         $phpdir = $config->get('php_dir', null, 'pear.php.net');
                   39247:         if (!isset($GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir])) {
                   39248:             $a = new PEAR_DependencyDB;
                   39249:             $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir] = &$a;
                   39250:             $a->setConfig($config, $depdb);
                   39251:             $e = $a->assertDepsDB();
                   39252:             if (PEAR::isError($e)) {
                   39253:                 return $e;
                   39254:             }
                   39255:         }
                   39256: 
                   39257:         return $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir];
                   39258:     }
                   39259: 
                   39260:     /**
                   39261:      * Set up the registry/location of dependency DB
                   39262:      * @param PEAR_Config|false
                   39263:      * @param string|false full path to the dependency database, or false to use default
                   39264:      */
                   39265:     function setConfig(&$config, $depdb = false)
                   39266:     {
                   39267:         if (!$config) {
                   39268:             $this->_config = &PEAR_Config::singleton();
                   39269:         } else {
                   39270:             $this->_config = &$config;
                   39271:         }
                   39272: 
                   39273:         $this->_registry = &$this->_config->getRegistry();
                   39274:         if (!$depdb) {
                   39275:             $this->_depdb = $this->_config->get('php_dir', null, 'pear.php.net') .
                   39276:                 DIRECTORY_SEPARATOR . '.depdb';
                   39277:         } else {
                   39278:             $this->_depdb = $depdb;
                   39279:         }
                   39280: 
                   39281:         $this->_lockfile = dirname($this->_depdb) . DIRECTORY_SEPARATOR . '.depdblock';
                   39282:     }
                   39283:     // }}}
                   39284: 
                   39285:     function hasWriteAccess()
                   39286:     {
                   39287:         if (!file_exists($this->_depdb)) {
                   39288:             $dir = $this->_depdb;
                   39289:             while ($dir && $dir != '.') {
                   39290:                 $dir = dirname($dir); // cd ..
                   39291:                 if ($dir != '.' && file_exists($dir)) {
                   39292:                     if (is_writeable($dir)) {
                   39293:                         return true;
                   39294:                     }
                   39295: 
                   39296:                     return false;
                   39297:                 }
                   39298:             }
                   39299: 
                   39300:             return false;
                   39301:         }
                   39302: 
                   39303:         return is_writeable($this->_depdb);
                   39304:     }
                   39305: 
                   39306:     // {{{ assertDepsDB()
                   39307: 
                   39308:     /**
                   39309:      * Create the dependency database, if it doesn't exist.  Error if the database is
                   39310:      * newer than the code reading it.
                   39311:      * @return void|PEAR_Error
                   39312:      */
                   39313:     function assertDepsDB()
                   39314:     {
                   39315:         if (!is_file($this->_depdb)) {
                   39316:             $this->rebuildDB();
                   39317:             return;
                   39318:         }
                   39319: 
                   39320:         $depdb = $this->_getDepDB();
                   39321:         // Datatype format has been changed, rebuild the Deps DB
                   39322:         if ($depdb['_version'] < $this->_version) {
                   39323:             $this->rebuildDB();
                   39324:         }
                   39325: 
                   39326:         if ($depdb['_version']{0} > $this->_version{0}) {
                   39327:             return PEAR::raiseError('Dependency database is version ' .
                   39328:                 $depdb['_version'] . ', and we are version ' .
                   39329:                 $this->_version . ', cannot continue');
                   39330:         }
                   39331:     }
                   39332: 
                   39333:     /**
                   39334:      * Get a list of installed packages that depend on this package
                   39335:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
                   39336:      * @return array|false
                   39337:      */
                   39338:     function getDependentPackages(&$pkg)
                   39339:     {
                   39340:         $data = $this->_getDepDB();
                   39341:         if (is_object($pkg)) {
                   39342:             $channel = strtolower($pkg->getChannel());
                   39343:             $package = strtolower($pkg->getPackage());
                   39344:         } else {
                   39345:             $channel = strtolower($pkg['channel']);
                   39346:             $package = strtolower($pkg['package']);
                   39347:         }
                   39348: 
                   39349:         if (isset($data['packages'][$channel][$package])) {
                   39350:             return $data['packages'][$channel][$package];
                   39351:         }
                   39352: 
                   39353:         return false;
                   39354:     }
                   39355: 
                   39356:     /**
                   39357:      * Get a list of the actual dependencies of installed packages that depend on
                   39358:      * a package.
                   39359:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
                   39360:      * @return array|false
                   39361:      */
                   39362:     function getDependentPackageDependencies(&$pkg)
                   39363:     {
                   39364:         $data = $this->_getDepDB();
                   39365:         if (is_object($pkg)) {
                   39366:             $channel = strtolower($pkg->getChannel());
                   39367:             $package = strtolower($pkg->getPackage());
                   39368:         } else {
                   39369:             $channel = strtolower($pkg['channel']);
                   39370:             $package = strtolower($pkg['package']);
                   39371:         }
                   39372: 
                   39373:         $depend = $this->getDependentPackages($pkg);
                   39374:         if (!$depend) {
                   39375:             return false;
                   39376:         }
                   39377: 
                   39378:         $dependencies = array();
                   39379:         foreach ($depend as $info) {
                   39380:             $temp = $this->getDependencies($info);
                   39381:             foreach ($temp as $dep) {
                   39382:                 if (
                   39383:                     isset($dep['dep'], $dep['dep']['channel'], $dep['dep']['name']) &&
                   39384:                     strtolower($dep['dep']['channel']) == $channel &&
                   39385:                     strtolower($dep['dep']['name']) == $package
                   39386:                 ) {
                   39387:                     if (!isset($dependencies[$info['channel']])) {
                   39388:                         $dependencies[$info['channel']] = array();
                   39389:                     }
                   39390: 
                   39391:                     if (!isset($dependencies[$info['channel']][$info['package']])) {
                   39392:                         $dependencies[$info['channel']][$info['package']] = array();
                   39393:                     }
                   39394:                     $dependencies[$info['channel']][$info['package']][] = $dep;
                   39395:                 }
                   39396:             }
                   39397:         }
                   39398: 
                   39399:         return $dependencies;
                   39400:     }
                   39401: 
                   39402:     /**
                   39403:      * Get a list of dependencies of this installed package
                   39404:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
                   39405:      * @return array|false
                   39406:      */
                   39407:     function getDependencies(&$pkg)
                   39408:     {
                   39409:         if (is_object($pkg)) {
                   39410:             $channel = strtolower($pkg->getChannel());
                   39411:             $package = strtolower($pkg->getPackage());
                   39412:         } else {
                   39413:             $channel = strtolower($pkg['channel']);
                   39414:             $package = strtolower($pkg['package']);
                   39415:         }
                   39416: 
                   39417:         $data = $this->_getDepDB();
                   39418:         if (isset($data['dependencies'][$channel][$package])) {
                   39419:             return $data['dependencies'][$channel][$package];
                   39420:         }
                   39421: 
                   39422:         return false;
                   39423:     }
                   39424: 
                   39425:     /**
                   39426:      * Determine whether $parent depends on $child, near or deep
                   39427:      * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
                   39428:      * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
                   39429:      */
                   39430:     function dependsOn($parent, $child)
                   39431:     {
                   39432:         $c = array();
                   39433:         $this->_getDepDB();
                   39434:         return $this->_dependsOn($parent, $child, $c);
                   39435:     }
                   39436: 
                   39437:     function _dependsOn($parent, $child, &$checked)
                   39438:     {
                   39439:         if (is_object($parent)) {
                   39440:             $channel = strtolower($parent->getChannel());
                   39441:             $package = strtolower($parent->getPackage());
                   39442:         } else {
                   39443:             $channel = strtolower($parent['channel']);
                   39444:             $package = strtolower($parent['package']);
                   39445:         }
                   39446: 
                   39447:         if (is_object($child)) {
                   39448:             $depchannel = strtolower($child->getChannel());
                   39449:             $deppackage = strtolower($child->getPackage());
                   39450:         } else {
                   39451:             $depchannel = strtolower($child['channel']);
                   39452:             $deppackage = strtolower($child['package']);
                   39453:         }
                   39454: 
                   39455:         if (isset($checked[$channel][$package][$depchannel][$deppackage])) {
                   39456:             return false; // avoid endless recursion
                   39457:         }
                   39458: 
                   39459:         $checked[$channel][$package][$depchannel][$deppackage] = true;
                   39460:         if (!isset($this->_cache['dependencies'][$channel][$package])) {
                   39461:             return false;
                   39462:         }
                   39463: 
                   39464:         foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
                   39465:             if (isset($info['dep']['uri'])) {
                   39466:                 if (is_object($child)) {
                   39467:                     if ($info['dep']['uri'] == $child->getURI()) {
                   39468:                         return true;
                   39469:                     }
                   39470:                 } elseif (isset($child['uri'])) {
                   39471:                     if ($info['dep']['uri'] == $child['uri']) {
                   39472:                         return true;
                   39473:                     }
                   39474:                 }
                   39475:                 return false;
                   39476:             }
                   39477: 
                   39478:             if (strtolower($info['dep']['channel']) == $depchannel &&
                   39479:                   strtolower($info['dep']['name']) == $deppackage) {
                   39480:                 return true;
                   39481:             }
                   39482:         }
                   39483: 
                   39484:         foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
                   39485:             if (isset($info['dep']['uri'])) {
                   39486:                 if ($this->_dependsOn(array(
                   39487:                         'uri' => $info['dep']['uri'],
                   39488:                         'package' => $info['dep']['name']), $child, $checked)) {
                   39489:                     return true;
                   39490:                 }
                   39491:             } else {
                   39492:                 if ($this->_dependsOn(array(
                   39493:                         'channel' => $info['dep']['channel'],
                   39494:                         'package' => $info['dep']['name']), $child, $checked)) {
                   39495:                     return true;
                   39496:                 }
                   39497:             }
                   39498:         }
                   39499: 
                   39500:         return false;
                   39501:     }
                   39502: 
                   39503:     /**
                   39504:      * Register dependencies of a package that is being installed or upgraded
                   39505:      * @param PEAR_PackageFile_v2|PEAR_PackageFile_v2
                   39506:      */
                   39507:     function installPackage(&$package)
                   39508:     {
                   39509:         $data = $this->_getDepDB();
                   39510:         unset($this->_cache);
                   39511:         $this->_setPackageDeps($data, $package);
                   39512:         $this->_writeDepDB($data);
                   39513:     }
                   39514: 
                   39515:     /**
                   39516:      * Remove dependencies of a package that is being uninstalled, or upgraded.
                   39517:      *
                   39518:      * Upgraded packages first uninstall, then install
                   39519:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array If an array, then it must have
                   39520:      *        indices 'channel' and 'package'
                   39521:      */
                   39522:     function uninstallPackage(&$pkg)
                   39523:     {
                   39524:         $data = $this->_getDepDB();
                   39525:         unset($this->_cache);
                   39526:         if (is_object($pkg)) {
                   39527:             $channel = strtolower($pkg->getChannel());
                   39528:             $package = strtolower($pkg->getPackage());
                   39529:         } else {
                   39530:             $channel = strtolower($pkg['channel']);
                   39531:             $package = strtolower($pkg['package']);
                   39532:         }
                   39533: 
                   39534:         if (!isset($data['dependencies'][$channel][$package])) {
                   39535:             return true;
                   39536:         }
                   39537: 
                   39538:         foreach ($data['dependencies'][$channel][$package] as $dep) {
                   39539:             $found      = false;
                   39540:             $depchannel = isset($dep['dep']['uri']) ? '__uri' : strtolower($dep['dep']['channel']);
                   39541:             $depname    = strtolower($dep['dep']['name']);
                   39542:             if (isset($data['packages'][$depchannel][$depname])) {
                   39543:                 foreach ($data['packages'][$depchannel][$depname] as $i => $info) {
                   39544:                     if ($info['channel'] == $channel && $info['package'] == $package) {
                   39545:                         $found = true;
                   39546:                         break;
                   39547:                     }
                   39548:                 }
                   39549:             }
                   39550: 
                   39551:             if ($found) {
                   39552:                 unset($data['packages'][$depchannel][$depname][$i]);
                   39553:                 if (!count($data['packages'][$depchannel][$depname])) {
                   39554:                     unset($data['packages'][$depchannel][$depname]);
                   39555:                     if (!count($data['packages'][$depchannel])) {
                   39556:                         unset($data['packages'][$depchannel]);
                   39557:                     }
                   39558:                 } else {
                   39559:                     $data['packages'][$depchannel][$depname] =
                   39560:                         array_values($data['packages'][$depchannel][$depname]);
                   39561:                 }
                   39562:             }
                   39563:         }
                   39564: 
                   39565:         unset($data['dependencies'][$channel][$package]);
                   39566:         if (!count($data['dependencies'][$channel])) {
                   39567:             unset($data['dependencies'][$channel]);
                   39568:         }
                   39569: 
                   39570:         if (!count($data['dependencies'])) {
                   39571:             unset($data['dependencies']);
                   39572:         }
                   39573: 
                   39574:         if (!count($data['packages'])) {
                   39575:             unset($data['packages']);
                   39576:         }
                   39577: 
                   39578:         $this->_writeDepDB($data);
                   39579:     }
                   39580: 
                   39581:     /**
                   39582:      * Rebuild the dependency DB by reading registry entries.
                   39583:      * @return true|PEAR_Error
                   39584:      */
                   39585:     function rebuildDB()
                   39586:     {
                   39587:         $depdb = array('_version' => $this->_version);
                   39588:         if (!$this->hasWriteAccess()) {
                   39589:             // allow startup for read-only with older Registry
                   39590:             return $depdb;
                   39591:         }
                   39592: 
                   39593:         $packages = $this->_registry->listAllPackages();
                   39594:         if (PEAR::isError($packages)) {
                   39595:             return $packages;
                   39596:         }
                   39597: 
                   39598:         foreach ($packages as $channel => $ps) {
                   39599:             foreach ($ps as $package) {
                   39600:                 $package = $this->_registry->getPackage($package, $channel);
                   39601:                 if (PEAR::isError($package)) {
                   39602:                     return $package;
                   39603:                 }
                   39604:                 $this->_setPackageDeps($depdb, $package);
                   39605:             }
                   39606:         }
                   39607: 
                   39608:         $error = $this->_writeDepDB($depdb);
                   39609:         if (PEAR::isError($error)) {
                   39610:             return $error;
                   39611:         }
                   39612: 
                   39613:         $this->_cache = $depdb;
                   39614:         return true;
                   39615:     }
                   39616: 
                   39617:     /**
                   39618:      * Register usage of the dependency DB to prevent race conditions
                   39619:      * @param int one of the LOCK_* constants
                   39620:      * @return true|PEAR_Error
                   39621:      * @access private
                   39622:      */
                   39623:     function _lock($mode = LOCK_EX)
                   39624:     {
                   39625:         if (stristr(php_uname(), 'Windows 9')) {
                   39626:             return true;
                   39627:         }
                   39628: 
                   39629:         if ($mode != LOCK_UN && is_resource($this->_lockFp)) {
                   39630:             // XXX does not check type of lock (LOCK_SH/LOCK_EX)
                   39631:             return true;
                   39632:         }
                   39633: 
                   39634:         $open_mode = 'w';
                   39635:         // XXX People reported problems with LOCK_SH and 'w'
                   39636:         if ($mode === LOCK_SH) {
                   39637:             if (!file_exists($this->_lockfile)) {
                   39638:                 touch($this->_lockfile);
                   39639:             } elseif (!is_file($this->_lockfile)) {
                   39640:                 return PEAR::raiseError('could not create Dependency lock file, ' .
                   39641:                     'it exists and is not a regular file');
                   39642:             }
                   39643:             $open_mode = 'r';
                   39644:         }
                   39645: 
                   39646:         if (!is_resource($this->_lockFp)) {
                   39647:             $this->_lockFp = @fopen($this->_lockfile, $open_mode);
                   39648:         }
                   39649: 
                   39650:         if (!is_resource($this->_lockFp)) {
                   39651:             return PEAR::raiseError("could not create Dependency lock file" .
                   39652:                                      (isset($php_errormsg) ? ": " . $php_errormsg : ""));
                   39653:         }
                   39654: 
                   39655:         if (!(int)flock($this->_lockFp, $mode)) {
                   39656:             switch ($mode) {
                   39657:                 case LOCK_SH: $str = 'shared';    break;
                   39658:                 case LOCK_EX: $str = 'exclusive'; break;
                   39659:                 case LOCK_UN: $str = 'unlock';    break;
                   39660:                 default:      $str = 'unknown';   break;
                   39661:             }
                   39662: 
                   39663:             return PEAR::raiseError("could not acquire $str lock ($this->_lockfile)");
                   39664:         }
                   39665: 
                   39666:         return true;
                   39667:     }
                   39668: 
                   39669:     /**
                   39670:      * Release usage of dependency DB
                   39671:      * @return true|PEAR_Error
                   39672:      * @access private
                   39673:      */
                   39674:     function _unlock()
                   39675:     {
                   39676:         $ret = $this->_lock(LOCK_UN);
                   39677:         if (is_resource($this->_lockFp)) {
                   39678:             fclose($this->_lockFp);
                   39679:         }
                   39680:         $this->_lockFp = null;
                   39681:         return $ret;
                   39682:     }
                   39683: 
                   39684:     /**
                   39685:      * Load the dependency database from disk, or return the cache
                   39686:      * @return array|PEAR_Error
                   39687:      */
                   39688:     function _getDepDB()
                   39689:     {
                   39690:         if (!$this->hasWriteAccess()) {
                   39691:             return array('_version' => $this->_version);
                   39692:         }
                   39693: 
                   39694:         if (isset($this->_cache)) {
                   39695:             return $this->_cache;
                   39696:         }
                   39697: 
                   39698:         if (!$fp = fopen($this->_depdb, 'r')) {
                   39699:             $err = PEAR::raiseError("Could not open dependencies file `".$this->_depdb."'");
                   39700:             return $err;
                   39701:         }
                   39702: 
                   39703:         $rt = get_magic_quotes_runtime();
                   39704:         set_magic_quotes_runtime(0);
                   39705:         clearstatcache();
                   39706:         fclose($fp);
                   39707:         $data = unserialize(file_get_contents($this->_depdb));
                   39708:         set_magic_quotes_runtime($rt);
                   39709:         $this->_cache = $data;
                   39710:         return $data;
                   39711:     }
                   39712: 
                   39713:     /**
                   39714:      * Write out the dependency database to disk
                   39715:      * @param array the database
                   39716:      * @return true|PEAR_Error
                   39717:      * @access private
                   39718:      */
                   39719:     function _writeDepDB(&$deps)
                   39720:     {
                   39721:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   39722:             return $e;
                   39723:         }
                   39724: 
                   39725:         if (!$fp = fopen($this->_depdb, 'wb')) {
                   39726:             $this->_unlock();
                   39727:             return PEAR::raiseError("Could not open dependencies file `".$this->_depdb."' for writing");
                   39728:         }
                   39729: 
                   39730:         $rt = get_magic_quotes_runtime();
                   39731:         set_magic_quotes_runtime(0);
                   39732:         fwrite($fp, serialize($deps));
                   39733:         set_magic_quotes_runtime($rt);
                   39734:         fclose($fp);
                   39735:         $this->_unlock();
                   39736:         $this->_cache = $deps;
                   39737:         return true;
                   39738:     }
                   39739: 
                   39740:     /**
                   39741:      * Register all dependencies from a package in the dependencies database, in essence
                   39742:      * "installing" the package's dependency information
                   39743:      * @param array the database
                   39744:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   39745:      * @access private
                   39746:      */
                   39747:     function _setPackageDeps(&$data, &$pkg)
                   39748:     {
                   39749:         $pkg->setConfig($this->_config);
                   39750:         if ($pkg->getPackagexmlVersion() == '1.0') {
                   39751:             $gen = &$pkg->getDefaultGenerator();
                   39752:             $deps = $gen->dependenciesToV2();
                   39753:         } else {
                   39754:             $deps = $pkg->getDeps(true);
                   39755:         }
                   39756: 
                   39757:         if (!$deps) {
                   39758:             return;
                   39759:         }
                   39760: 
                   39761:         if (!is_array($data)) {
                   39762:             $data = array();
                   39763:         }
                   39764: 
                   39765:         if (!isset($data['dependencies'])) {
                   39766:             $data['dependencies'] = array();
                   39767:         }
                   39768: 
                   39769:         $channel = strtolower($pkg->getChannel());
                   39770:         $package = strtolower($pkg->getPackage());
                   39771: 
                   39772:         if (!isset($data['dependencies'][$channel])) {
                   39773:             $data['dependencies'][$channel] = array();
                   39774:         }
                   39775: 
                   39776:         $data['dependencies'][$channel][$package] = array();
                   39777:         if (isset($deps['required']['package'])) {
                   39778:             if (!isset($deps['required']['package'][0])) {
                   39779:                 $deps['required']['package'] = array($deps['required']['package']);
                   39780:             }
                   39781: 
                   39782:             foreach ($deps['required']['package'] as $dep) {
                   39783:                 $this->_registerDep($data, $pkg, $dep, 'required');
                   39784:             }
                   39785:         }
                   39786: 
                   39787:         if (isset($deps['optional']['package'])) {
                   39788:             if (!isset($deps['optional']['package'][0])) {
                   39789:                 $deps['optional']['package'] = array($deps['optional']['package']);
                   39790:             }
                   39791: 
                   39792:             foreach ($deps['optional']['package'] as $dep) {
                   39793:                 $this->_registerDep($data, $pkg, $dep, 'optional');
                   39794:             }
                   39795:         }
                   39796: 
                   39797:         if (isset($deps['required']['subpackage'])) {
                   39798:             if (!isset($deps['required']['subpackage'][0])) {
                   39799:                 $deps['required']['subpackage'] = array($deps['required']['subpackage']);
                   39800:             }
                   39801: 
                   39802:             foreach ($deps['required']['subpackage'] as $dep) {
                   39803:                 $this->_registerDep($data, $pkg, $dep, 'required');
                   39804:             }
                   39805:         }
                   39806: 
                   39807:         if (isset($deps['optional']['subpackage'])) {
                   39808:             if (!isset($deps['optional']['subpackage'][0])) {
                   39809:                 $deps['optional']['subpackage'] = array($deps['optional']['subpackage']);
                   39810:             }
                   39811: 
                   39812:             foreach ($deps['optional']['subpackage'] as $dep) {
                   39813:                 $this->_registerDep($data, $pkg, $dep, 'optional');
                   39814:             }
                   39815:         }
                   39816: 
                   39817:         if (isset($deps['group'])) {
                   39818:             if (!isset($deps['group'][0])) {
                   39819:                 $deps['group'] = array($deps['group']);
                   39820:             }
                   39821: 
                   39822:             foreach ($deps['group'] as $group) {
                   39823:                 if (isset($group['package'])) {
                   39824:                     if (!isset($group['package'][0])) {
                   39825:                         $group['package'] = array($group['package']);
                   39826:                     }
                   39827: 
                   39828:                     foreach ($group['package'] as $dep) {
                   39829:                         $this->_registerDep($data, $pkg, $dep, 'optional',
                   39830:                             $group['attribs']['name']);
                   39831:                     }
                   39832:                 }
                   39833: 
                   39834:                 if (isset($group['subpackage'])) {
                   39835:                     if (!isset($group['subpackage'][0])) {
                   39836:                         $group['subpackage'] = array($group['subpackage']);
                   39837:                     }
                   39838: 
                   39839:                     foreach ($group['subpackage'] as $dep) {
                   39840:                         $this->_registerDep($data, $pkg, $dep, 'optional',
                   39841:                             $group['attribs']['name']);
                   39842:                     }
                   39843:                 }
                   39844:             }
                   39845:         }
                   39846: 
                   39847:         if ($data['dependencies'][$channel][$package] == array()) {
                   39848:             unset($data['dependencies'][$channel][$package]);
                   39849:             if (!count($data['dependencies'][$channel])) {
                   39850:                 unset($data['dependencies'][$channel]);
                   39851:             }
                   39852:         }
                   39853:     }
                   39854: 
                   39855:     /**
                   39856:      * @param array the database
                   39857:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   39858:      * @param array the specific dependency
                   39859:      * @param required|optional whether this is a required or an optional dep
                   39860:      * @param string|false dependency group this dependency is from, or false for ordinary dep
                   39861:      */
                   39862:     function _registerDep(&$data, &$pkg, $dep, $type, $group = false)
                   39863:     {
                   39864:         $info = array(
                   39865:             'dep'   => $dep,
                   39866:             'type'  => $type,
                   39867:             'group' => $group
                   39868:         );
                   39869: 
                   39870:         $dep  = array_map('strtolower', $dep);
                   39871:         $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
                   39872:         if (!isset($data['dependencies'])) {
                   39873:             $data['dependencies'] = array();
                   39874:         }
                   39875: 
                   39876:         $channel = strtolower($pkg->getChannel());
                   39877:         $package = strtolower($pkg->getPackage());
                   39878: 
                   39879:         if (!isset($data['dependencies'][$channel])) {
                   39880:             $data['dependencies'][$channel] = array();
                   39881:         }
                   39882: 
                   39883:         if (!isset($data['dependencies'][$channel][$package])) {
                   39884:             $data['dependencies'][$channel][$package] = array();
                   39885:         }
                   39886: 
                   39887:         $data['dependencies'][$channel][$package][] = $info;
                   39888:         if (isset($data['packages'][$depchannel][$dep['name']])) {
                   39889:             $found = false;
                   39890:             foreach ($data['packages'][$depchannel][$dep['name']] as $i => $p) {
                   39891:                 if ($p['channel'] == $channel && $p['package'] == $package) {
                   39892:                     $found = true;
                   39893:                     break;
                   39894:                 }
                   39895:             }
                   39896:         } else {
                   39897:             if (!isset($data['packages'])) {
                   39898:                 $data['packages'] = array();
                   39899:             }
                   39900: 
                   39901:             if (!isset($data['packages'][$depchannel])) {
                   39902:                 $data['packages'][$depchannel] = array();
                   39903:             }
                   39904: 
                   39905:             if (!isset($data['packages'][$depchannel][$dep['name']])) {
                   39906:                 $data['packages'][$depchannel][$dep['name']] = array();
                   39907:             }
                   39908: 
                   39909:             $found = false;
                   39910:         }
                   39911: 
                   39912:         if (!$found) {
                   39913:             $data['packages'][$depchannel][$dep['name']][] = array(
                   39914:                 'channel' => $channel,
                   39915:                 'package' => $package
                   39916:             );
                   39917:         }
                   39918:     }
1.1.1.2 ! misho    39919: }PEAR-1.9.4/PEAR/Dependency2.php0000644000076500000240000014251711605156614014646 0ustar  helgistaff<?php
1.1       misho    39920: /**
                   39921:  * PEAR_Dependency2, advanced dependency validation
                   39922:  *
                   39923:  * PHP versions 4 and 5
                   39924:  *
                   39925:  * @category   pear
                   39926:  * @package    PEAR
                   39927:  * @author     Greg Beaver <cellog@php.net>
                   39928:  * @copyright  1997-2009 The Authors
                   39929:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   39930:  * @version    CVS: $Id: Dependency2.php 313023 2011-07-06 19:17:11Z dufuz $
                   39931:  * @link       http://pear.php.net/package/PEAR
                   39932:  * @since      File available since Release 1.4.0a1
                   39933:  */
                   39934: 
                   39935: /**
                   39936:  * Required for the PEAR_VALIDATE_* constants
                   39937:  */
                   39938: require_once 'PEAR/Validate.php';
                   39939: 
                   39940: /**
                   39941:  * Dependency check for PEAR packages
                   39942:  *
                   39943:  * This class handles both version 1.0 and 2.0 dependencies
                   39944:  * WARNING: *any* changes to this class must be duplicated in the
                   39945:  * test_PEAR_Dependency2 class found in tests/PEAR_Dependency2/setup.php.inc,
                   39946:  * or unit tests will not actually validate the changes
                   39947:  * @category   pear
                   39948:  * @package    PEAR
                   39949:  * @author     Greg Beaver <cellog@php.net>
                   39950:  * @copyright  1997-2009 The Authors
                   39951:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   39952:  * @version    Release: 1.9.4
                   39953:  * @link       http://pear.php.net/package/PEAR
                   39954:  * @since      Class available since Release 1.4.0a1
                   39955:  */
                   39956: class PEAR_Dependency2
                   39957: {
                   39958:     /**
                   39959:      * One of the PEAR_VALIDATE_* states
                   39960:      * @see PEAR_VALIDATE_NORMAL
                   39961:      * @var integer
                   39962:      */
                   39963:     var $_state;
                   39964: 
                   39965:     /**
                   39966:      * Command-line options to install/upgrade/uninstall commands
                   39967:      * @param array
                   39968:      */
                   39969:     var $_options;
                   39970: 
                   39971:     /**
                   39972:      * @var OS_Guess
                   39973:      */
                   39974:     var $_os;
                   39975: 
                   39976:     /**
                   39977:      * @var PEAR_Registry
                   39978:      */
                   39979:     var $_registry;
                   39980: 
                   39981:     /**
                   39982:      * @var PEAR_Config
                   39983:      */
                   39984:     var $_config;
                   39985: 
                   39986:     /**
                   39987:      * @var PEAR_DependencyDB
                   39988:      */
                   39989:     var $_dependencydb;
                   39990: 
                   39991:     /**
                   39992:      * Output of PEAR_Registry::parsedPackageName()
                   39993:      * @var array
                   39994:      */
                   39995:     var $_currentPackage;
                   39996: 
                   39997:     /**
                   39998:      * @param PEAR_Config
                   39999:      * @param array installation options
                   40000:      * @param array format of PEAR_Registry::parsedPackageName()
                   40001:      * @param int installation state (one of PEAR_VALIDATE_*)
                   40002:      */
                   40003:     function PEAR_Dependency2(&$config, $installoptions, $package,
                   40004:                               $state = PEAR_VALIDATE_INSTALLING)
                   40005:     {
                   40006:         $this->_config = &$config;
                   40007:         if (!class_exists('PEAR_DependencyDB')) {
                   40008:             require_once 'PEAR/DependencyDB.php';
                   40009:         }
                   40010: 
                   40011:         if (isset($installoptions['packagingroot'])) {
                   40012:             // make sure depdb is in the right location
                   40013:             $config->setInstallRoot($installoptions['packagingroot']);
                   40014:         }
                   40015: 
                   40016:         $this->_registry = &$config->getRegistry();
                   40017:         $this->_dependencydb = &PEAR_DependencyDB::singleton($config);
                   40018:         if (isset($installoptions['packagingroot'])) {
                   40019:             $config->setInstallRoot(false);
                   40020:         }
                   40021: 
                   40022:         $this->_options = $installoptions;
                   40023:         $this->_state = $state;
                   40024:         if (!class_exists('OS_Guess')) {
                   40025:             require_once 'OS/Guess.php';
                   40026:         }
                   40027: 
                   40028:         $this->_os = new OS_Guess;
                   40029:         $this->_currentPackage = $package;
                   40030:     }
                   40031: 
                   40032:     function _getExtraString($dep)
                   40033:     {
                   40034:         $extra = ' (';
                   40035:         if (isset($dep['uri'])) {
                   40036:             return '';
                   40037:         }
                   40038: 
                   40039:         if (isset($dep['recommended'])) {
                   40040:             $extra .= 'recommended version ' . $dep['recommended'];
                   40041:         } else {
                   40042:             if (isset($dep['min'])) {
                   40043:                 $extra .= 'version >= ' . $dep['min'];
                   40044:             }
                   40045: 
                   40046:             if (isset($dep['max'])) {
                   40047:                 if ($extra != ' (') {
                   40048:                     $extra .= ', ';
                   40049:                 }
                   40050:                 $extra .= 'version <= ' . $dep['max'];
                   40051:             }
                   40052: 
                   40053:             if (isset($dep['exclude'])) {
                   40054:                 if (!is_array($dep['exclude'])) {
                   40055:                     $dep['exclude'] = array($dep['exclude']);
                   40056:                 }
                   40057: 
                   40058:                 if ($extra != ' (') {
                   40059:                     $extra .= ', ';
                   40060:                 }
                   40061: 
                   40062:                 $extra .= 'excluded versions: ';
                   40063:                 foreach ($dep['exclude'] as $i => $exclude) {
                   40064:                     if ($i) {
                   40065:                         $extra .= ', ';
                   40066:                     }
                   40067:                     $extra .= $exclude;
                   40068:                 }
                   40069:             }
                   40070:         }
                   40071: 
                   40072:         $extra .= ')';
                   40073:         if ($extra == ' ()') {
                   40074:             $extra = '';
                   40075:         }
                   40076: 
                   40077:         return $extra;
                   40078:     }
                   40079: 
                   40080:     /**
                   40081:      * This makes unit-testing a heck of a lot easier
                   40082:      */
                   40083:     function getPHP_OS()
                   40084:     {
                   40085:         return PHP_OS;
                   40086:     }
                   40087: 
                   40088:     /**
                   40089:      * This makes unit-testing a heck of a lot easier
                   40090:      */
                   40091:     function getsysname()
                   40092:     {
                   40093:         return $this->_os->getSysname();
                   40094:     }
                   40095: 
                   40096:     /**
                   40097:      * Specify a dependency on an OS.  Use arch for detailed os/processor information
                   40098:      *
                   40099:      * There are two generic OS dependencies that will be the most common, unix and windows.
                   40100:      * Other options are linux, freebsd, darwin (OS X), sunos, irix, hpux, aix
                   40101:      */
                   40102:     function validateOsDependency($dep)
                   40103:     {
                   40104:         if ($this->_state != PEAR_VALIDATE_INSTALLING && $this->_state != PEAR_VALIDATE_DOWNLOADING) {
                   40105:             return true;
                   40106:         }
                   40107: 
                   40108:         if ($dep['name'] == '*') {
                   40109:             return true;
                   40110:         }
                   40111: 
                   40112:         $not = isset($dep['conflicts']) ? true : false;
                   40113:         switch (strtolower($dep['name'])) {
                   40114:             case 'windows' :
                   40115:                 if ($not) {
                   40116:                     if (strtolower(substr($this->getPHP_OS(), 0, 3)) == 'win') {
                   40117:                         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40118:                             return $this->raiseError("Cannot install %s on Windows");
                   40119:                         }
                   40120: 
                   40121:                         return $this->warning("warning: Cannot install %s on Windows");
                   40122:                     }
                   40123:                 } else {
                   40124:                     if (strtolower(substr($this->getPHP_OS(), 0, 3)) != 'win') {
                   40125:                         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40126:                             return $this->raiseError("Can only install %s on Windows");
                   40127:                         }
                   40128: 
                   40129:                         return $this->warning("warning: Can only install %s on Windows");
                   40130:                     }
                   40131:                 }
                   40132:             break;
                   40133:             case 'unix' :
                   40134:                 $unices = array('linux', 'freebsd', 'darwin', 'sunos', 'irix', 'hpux', 'aix');
                   40135:                 if ($not) {
                   40136:                     if (in_array($this->getSysname(), $unices)) {
                   40137:                         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40138:                             return $this->raiseError("Cannot install %s on any Unix system");
                   40139:                         }
                   40140: 
                   40141:                         return $this->warning( "warning: Cannot install %s on any Unix system");
                   40142:                     }
                   40143:                 } else {
                   40144:                     if (!in_array($this->getSysname(), $unices)) {
                   40145:                         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40146:                             return $this->raiseError("Can only install %s on a Unix system");
                   40147:                         }
                   40148: 
                   40149:                         return $this->warning("warning: Can only install %s on a Unix system");
                   40150:                     }
                   40151:                 }
                   40152:             break;
                   40153:             default :
                   40154:                 if ($not) {
                   40155:                     if (strtolower($dep['name']) == strtolower($this->getSysname())) {
                   40156:                         if (!isset($this->_options['nodeps']) &&
                   40157:                               !isset($this->_options['force'])) {
                   40158:                             return $this->raiseError('Cannot install %s on ' . $dep['name'] .
                   40159:                                 ' operating system');
                   40160:                         }
                   40161: 
                   40162:                         return $this->warning('warning: Cannot install %s on ' .
                   40163:                             $dep['name'] . ' operating system');
                   40164:                     }
                   40165:                 } else {
                   40166:                     if (strtolower($dep['name']) != strtolower($this->getSysname())) {
                   40167:                         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40168:                             return $this->raiseError('Cannot install %s on ' .
                   40169:                                 $this->getSysname() .
                   40170:                                 ' operating system, can only install on ' . $dep['name']);
                   40171:                         }
                   40172: 
                   40173:                         return $this->warning('warning: Cannot install %s on ' .
                   40174:                             $this->getSysname() .
                   40175:                             ' operating system, can only install on ' . $dep['name']);
                   40176:                     }
                   40177:                 }
                   40178:         }
                   40179:         return true;
                   40180:     }
                   40181: 
                   40182:     /**
                   40183:      * This makes unit-testing a heck of a lot easier
                   40184:      */
                   40185:     function matchSignature($pattern)
                   40186:     {
                   40187:         return $this->_os->matchSignature($pattern);
                   40188:     }
                   40189: 
                   40190:     /**
                   40191:      * Specify a complex dependency on an OS/processor/kernel version,
                   40192:      * Use OS for simple operating system dependency.
                   40193:      *
                   40194:      * This is the only dependency that accepts an eregable pattern.  The pattern
                   40195:      * will be matched against the php_uname() output parsed by OS_Guess
                   40196:      */
                   40197:     function validateArchDependency($dep)
                   40198:     {
                   40199:         if ($this->_state != PEAR_VALIDATE_INSTALLING) {
                   40200:             return true;
                   40201:         }
                   40202: 
                   40203:         $not = isset($dep['conflicts']) ? true : false;
                   40204:         if (!$this->matchSignature($dep['pattern'])) {
                   40205:             if (!$not) {
                   40206:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40207:                     return $this->raiseError('%s Architecture dependency failed, does not ' .
                   40208:                         'match "' . $dep['pattern'] . '"');
                   40209:                 }
                   40210: 
                   40211:                 return $this->warning('warning: %s Architecture dependency failed, does ' .
                   40212:                     'not match "' . $dep['pattern'] . '"');
                   40213:             }
                   40214: 
                   40215:             return true;
                   40216:         }
                   40217: 
                   40218:         if ($not) {
                   40219:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40220:                 return $this->raiseError('%s Architecture dependency failed, required "' .
                   40221:                     $dep['pattern'] . '"');
                   40222:             }
                   40223: 
                   40224:             return $this->warning('warning: %s Architecture dependency failed, ' .
                   40225:                 'required "' . $dep['pattern'] . '"');
                   40226:         }
                   40227: 
                   40228:         return true;
                   40229:     }
                   40230: 
                   40231:     /**
                   40232:      * This makes unit-testing a heck of a lot easier
                   40233:      */
                   40234:     function extension_loaded($name)
                   40235:     {
                   40236:         return extension_loaded($name);
                   40237:     }
                   40238: 
                   40239:     /**
                   40240:      * This makes unit-testing a heck of a lot easier
                   40241:      */
                   40242:     function phpversion($name = null)
                   40243:     {
                   40244:         if ($name !== null) {
                   40245:             return phpversion($name);
                   40246:         }
                   40247: 
                   40248:         return phpversion();
                   40249:     }
                   40250: 
                   40251:     function validateExtensionDependency($dep, $required = true)
                   40252:     {
                   40253:         if ($this->_state != PEAR_VALIDATE_INSTALLING &&
                   40254:               $this->_state != PEAR_VALIDATE_DOWNLOADING) {
                   40255:             return true;
                   40256:         }
                   40257: 
                   40258:         $loaded = $this->extension_loaded($dep['name']);
                   40259:         $extra  = $this->_getExtraString($dep);
                   40260:         if (isset($dep['exclude'])) {
                   40261:             if (!is_array($dep['exclude'])) {
                   40262:                 $dep['exclude'] = array($dep['exclude']);
                   40263:             }
                   40264:         }
                   40265: 
                   40266:         if (!isset($dep['min']) && !isset($dep['max']) &&
                   40267:             !isset($dep['recommended']) && !isset($dep['exclude'])
                   40268:         ) {
                   40269:             if ($loaded) {
                   40270:                 if (isset($dep['conflicts'])) {
                   40271:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40272:                         return $this->raiseError('%s conflicts with PHP extension "' .
                   40273:                             $dep['name'] . '"' . $extra);
                   40274:                     }
                   40275: 
                   40276:                     return $this->warning('warning: %s conflicts with PHP extension "' .
                   40277:                         $dep['name'] . '"' . $extra);
                   40278:                 }
                   40279: 
                   40280:                 return true;
                   40281:             }
                   40282: 
                   40283:             if (isset($dep['conflicts'])) {
                   40284:                 return true;
                   40285:             }
                   40286: 
                   40287:             if ($required) {
                   40288:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40289:                     return $this->raiseError('%s requires PHP extension "' .
                   40290:                         $dep['name'] . '"' . $extra);
                   40291:                 }
                   40292: 
                   40293:                 return $this->warning('warning: %s requires PHP extension "' .
                   40294:                     $dep['name'] . '"' . $extra);
                   40295:             }
                   40296: 
                   40297:             return $this->warning('%s can optionally use PHP extension "' .
                   40298:                 $dep['name'] . '"' . $extra);
                   40299:         }
                   40300: 
                   40301:         if (!$loaded) {
                   40302:             if (isset($dep['conflicts'])) {
                   40303:                 return true;
                   40304:             }
                   40305: 
                   40306:             if (!$required) {
                   40307:                 return $this->warning('%s can optionally use PHP extension "' .
                   40308:                     $dep['name'] . '"' . $extra);
                   40309:             }
                   40310: 
                   40311:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40312:                 return $this->raiseError('%s requires PHP extension "' . $dep['name'] .
                   40313:                     '"' . $extra);
                   40314:             }
                   40315: 
                   40316:             return $this->warning('warning: %s requires PHP extension "' . $dep['name'] .
                   40317:                     '"' . $extra);
                   40318:         }
                   40319: 
                   40320:         $version = (string) $this->phpversion($dep['name']);
                   40321:         if (empty($version)) {
                   40322:             $version = '0';
                   40323:         }
                   40324: 
                   40325:         $fail = false;
                   40326:         if (isset($dep['min']) && !version_compare($version, $dep['min'], '>=')) {
                   40327:             $fail = true;
                   40328:         }
                   40329: 
                   40330:         if (isset($dep['max']) && !version_compare($version, $dep['max'], '<=')) {
                   40331:             $fail = true;
                   40332:         }
                   40333: 
                   40334:         if ($fail && !isset($dep['conflicts'])) {
                   40335:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40336:                 return $this->raiseError('%s requires PHP extension "' . $dep['name'] .
                   40337:                     '"' . $extra . ', installed version is ' . $version);
                   40338:             }
                   40339: 
                   40340:             return $this->warning('warning: %s requires PHP extension "' . $dep['name'] .
                   40341:                 '"' . $extra . ', installed version is ' . $version);
                   40342:         } elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail && isset($dep['conflicts'])) {
                   40343:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40344:                 return $this->raiseError('%s conflicts with PHP extension "' .
                   40345:                     $dep['name'] . '"' . $extra . ', installed version is ' . $version);
                   40346:             }
                   40347: 
                   40348:             return $this->warning('warning: %s conflicts with PHP extension "' .
                   40349:                 $dep['name'] . '"' . $extra . ', installed version is ' . $version);
                   40350:         }
                   40351: 
                   40352:         if (isset($dep['exclude'])) {
                   40353:             foreach ($dep['exclude'] as $exclude) {
                   40354:                 if (version_compare($version, $exclude, '==')) {
                   40355:                     if (isset($dep['conflicts'])) {
                   40356:                         continue;
                   40357:                     }
                   40358: 
                   40359:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40360:                         return $this->raiseError('%s is not compatible with PHP extension "' .
                   40361:                             $dep['name'] . '" version ' .
                   40362:                             $exclude);
                   40363:                     }
                   40364: 
                   40365:                     return $this->warning('warning: %s is not compatible with PHP extension "' .
                   40366:                         $dep['name'] . '" version ' .
                   40367:                         $exclude);
                   40368:                 } elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) {
                   40369:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40370:                         return $this->raiseError('%s conflicts with PHP extension "' .
                   40371:                             $dep['name'] . '"' . $extra . ', installed version is ' . $version);
                   40372:                     }
                   40373: 
                   40374:                     return $this->warning('warning: %s conflicts with PHP extension "' .
                   40375:                         $dep['name'] . '"' . $extra . ', installed version is ' . $version);
                   40376:                 }
                   40377:             }
                   40378:         }
                   40379: 
                   40380:         if (isset($dep['recommended'])) {
                   40381:             if (version_compare($version, $dep['recommended'], '==')) {
                   40382:                 return true;
                   40383:             }
                   40384: 
                   40385:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40386:                 return $this->raiseError('%s dependency: PHP extension ' . $dep['name'] .
                   40387:                     ' version "' . $version . '"' .
                   40388:                     ' is not the recommended version "' . $dep['recommended'] .
                   40389:                     '", but may be compatible, use --force to install');
                   40390:             }
                   40391: 
                   40392:             return $this->warning('warning: %s dependency: PHP extension ' .
                   40393:                 $dep['name'] . ' version "' . $version . '"' .
                   40394:                 ' is not the recommended version "' . $dep['recommended'].'"');
                   40395:         }
                   40396: 
                   40397:         return true;
                   40398:     }
                   40399: 
                   40400:     function validatePhpDependency($dep)
                   40401:     {
                   40402:         if ($this->_state != PEAR_VALIDATE_INSTALLING &&
                   40403:               $this->_state != PEAR_VALIDATE_DOWNLOADING) {
                   40404:             return true;
                   40405:         }
                   40406: 
                   40407:         $version = $this->phpversion();
                   40408:         $extra   = $this->_getExtraString($dep);
                   40409:         if (isset($dep['exclude'])) {
                   40410:             if (!is_array($dep['exclude'])) {
                   40411:                 $dep['exclude'] = array($dep['exclude']);
                   40412:             }
                   40413:         }
                   40414: 
                   40415:         if (isset($dep['min'])) {
                   40416:             if (!version_compare($version, $dep['min'], '>=')) {
                   40417:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40418:                     return $this->raiseError('%s requires PHP' .
                   40419:                         $extra . ', installed version is ' . $version);
                   40420:                 }
                   40421: 
                   40422:                 return $this->warning('warning: %s requires PHP' .
                   40423:                     $extra . ', installed version is ' . $version);
                   40424:             }
                   40425:         }
                   40426: 
                   40427:         if (isset($dep['max'])) {
                   40428:             if (!version_compare($version, $dep['max'], '<=')) {
                   40429:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40430:                     return $this->raiseError('%s requires PHP' .
                   40431:                         $extra . ', installed version is ' . $version);
                   40432:                 }
                   40433: 
                   40434:                 return $this->warning('warning: %s requires PHP' .
                   40435:                     $extra . ', installed version is ' . $version);
                   40436:             }
                   40437:         }
                   40438: 
                   40439:         if (isset($dep['exclude'])) {
                   40440:             foreach ($dep['exclude'] as $exclude) {
                   40441:                 if (version_compare($version, $exclude, '==')) {
                   40442:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40443:                         return $this->raiseError('%s is not compatible with PHP version ' .
                   40444:                             $exclude);
                   40445:                     }
                   40446: 
                   40447:                     return $this->warning(
                   40448:                         'warning: %s is not compatible with PHP version ' .
                   40449:                         $exclude);
                   40450:                 }
                   40451:             }
                   40452:         }
                   40453: 
                   40454:         return true;
                   40455:     }
                   40456: 
                   40457:     /**
                   40458:      * This makes unit-testing a heck of a lot easier
                   40459:      */
                   40460:     function getPEARVersion()
                   40461:     {
                   40462:         return '1.9.4';
                   40463:     }
                   40464: 
                   40465:     function validatePearinstallerDependency($dep)
                   40466:     {
                   40467:         $pearversion = $this->getPEARVersion();
                   40468:         $extra = $this->_getExtraString($dep);
                   40469:         if (isset($dep['exclude'])) {
                   40470:             if (!is_array($dep['exclude'])) {
                   40471:                 $dep['exclude'] = array($dep['exclude']);
                   40472:             }
                   40473:         }
                   40474: 
                   40475:         if (version_compare($pearversion, $dep['min'], '<')) {
                   40476:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40477:                 return $this->raiseError('%s requires PEAR Installer' . $extra .
                   40478:                     ', installed version is ' . $pearversion);
                   40479:             }
                   40480: 
                   40481:             return $this->warning('warning: %s requires PEAR Installer' . $extra .
                   40482:                 ', installed version is ' . $pearversion);
                   40483:         }
                   40484: 
                   40485:         if (isset($dep['max'])) {
                   40486:             if (version_compare($pearversion, $dep['max'], '>')) {
                   40487:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40488:                     return $this->raiseError('%s requires PEAR Installer' . $extra .
                   40489:                         ', installed version is ' . $pearversion);
                   40490:                 }
                   40491: 
                   40492:                 return $this->warning('warning: %s requires PEAR Installer' . $extra .
                   40493:                     ', installed version is ' . $pearversion);
                   40494:             }
                   40495:         }
                   40496: 
                   40497:         if (isset($dep['exclude'])) {
                   40498:             if (!isset($dep['exclude'][0])) {
                   40499:                 $dep['exclude'] = array($dep['exclude']);
                   40500:             }
                   40501: 
                   40502:             foreach ($dep['exclude'] as $exclude) {
                   40503:                 if (version_compare($exclude, $pearversion, '==')) {
                   40504:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40505:                         return $this->raiseError('%s is not compatible with PEAR Installer ' .
                   40506:                             'version ' . $exclude);
                   40507:                     }
                   40508: 
                   40509:                     return $this->warning('warning: %s is not compatible with PEAR ' .
                   40510:                         'Installer version ' . $exclude);
                   40511:                 }
                   40512:             }
                   40513:         }
                   40514: 
                   40515:         return true;
                   40516:     }
                   40517: 
                   40518:     function validateSubpackageDependency($dep, $required, $params)
                   40519:     {
                   40520:         return $this->validatePackageDependency($dep, $required, $params);
                   40521:     }
                   40522: 
                   40523:     /**
                   40524:      * @param array dependency information (2.0 format)
                   40525:      * @param boolean whether this is a required dependency
                   40526:      * @param array a list of downloaded packages to be installed, if any
                   40527:      * @param boolean if true, then deps on pear.php.net that fail will also check
                   40528:      *                against pecl.php.net packages to accomodate extensions that have
                   40529:      *                moved to pecl.php.net from pear.php.net
                   40530:      */
                   40531:     function validatePackageDependency($dep, $required, $params, $depv1 = false)
                   40532:     {
                   40533:         if ($this->_state != PEAR_VALIDATE_INSTALLING &&
                   40534:               $this->_state != PEAR_VALIDATE_DOWNLOADING) {
                   40535:             return true;
                   40536:         }
                   40537: 
                   40538:         if (isset($dep['providesextension'])) {
                   40539:             if ($this->extension_loaded($dep['providesextension'])) {
                   40540:                 $save = $dep;
                   40541:                 $subdep = $dep;
                   40542:                 $subdep['name'] = $subdep['providesextension'];
                   40543:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   40544:                 $ret = $this->validateExtensionDependency($subdep, $required);
                   40545:                 PEAR::popErrorHandling();
                   40546:                 if (!PEAR::isError($ret)) {
                   40547:                     return true;
                   40548:                 }
                   40549:             }
                   40550:         }
                   40551: 
                   40552:         if ($this->_state == PEAR_VALIDATE_INSTALLING) {
                   40553:             return $this->_validatePackageInstall($dep, $required, $depv1);
                   40554:         }
                   40555: 
                   40556:         if ($this->_state == PEAR_VALIDATE_DOWNLOADING) {
                   40557:             return $this->_validatePackageDownload($dep, $required, $params, $depv1);
                   40558:         }
                   40559:     }
                   40560: 
                   40561:     function _validatePackageDownload($dep, $required, $params, $depv1 = false)
                   40562:     {
                   40563:         $dep['package'] = $dep['name'];
                   40564:         if (isset($dep['uri'])) {
                   40565:             $dep['channel'] = '__uri';
                   40566:         }
                   40567: 
                   40568:         $depname = $this->_registry->parsedPackageNameToString($dep, true);
                   40569:         $found = false;
                   40570:         foreach ($params as $param) {
                   40571:             if ($param->isEqual(
                   40572:                   array('package' => $dep['name'],
                   40573:                         'channel' => $dep['channel']))) {
                   40574:                 $found = true;
                   40575:                 break;
                   40576:             }
                   40577: 
                   40578:             if ($depv1 && $dep['channel'] == 'pear.php.net') {
                   40579:                 if ($param->isEqual(
                   40580:                   array('package' => $dep['name'],
                   40581:                         'channel' => 'pecl.php.net'))) {
                   40582:                     $found = true;
                   40583:                     break;
                   40584:                 }
                   40585:             }
                   40586:         }
                   40587: 
                   40588:         if (!$found && isset($dep['providesextension'])) {
                   40589:             foreach ($params as $param) {
                   40590:                 if ($param->isExtension($dep['providesextension'])) {
                   40591:                     $found = true;
                   40592:                     break;
                   40593:                 }
                   40594:             }
                   40595:         }
                   40596: 
                   40597:         if ($found) {
                   40598:             $version = $param->getVersion();
                   40599:             $installed = false;
                   40600:             $downloaded = true;
                   40601:         } else {
                   40602:             if ($this->_registry->packageExists($dep['name'], $dep['channel'])) {
                   40603:                 $installed = true;
                   40604:                 $downloaded = false;
                   40605:                 $version = $this->_registry->packageinfo($dep['name'], 'version',
                   40606:                     $dep['channel']);
                   40607:             } else {
                   40608:                 if ($dep['channel'] == 'pecl.php.net' && $this->_registry->packageExists($dep['name'],
                   40609:                       'pear.php.net')) {
                   40610:                     $installed = true;
                   40611:                     $downloaded = false;
                   40612:                     $version = $this->_registry->packageinfo($dep['name'], 'version',
                   40613:                         'pear.php.net');
                   40614:                 } else {
                   40615:                     $version = 'not installed or downloaded';
                   40616:                     $installed = false;
                   40617:                     $downloaded = false;
                   40618:                 }
                   40619:             }
                   40620:         }
                   40621: 
                   40622:         $extra = $this->_getExtraString($dep);
                   40623:         if (isset($dep['exclude']) && !is_array($dep['exclude'])) {
                   40624:             $dep['exclude'] = array($dep['exclude']);
                   40625:         }
                   40626: 
                   40627:         if (!isset($dep['min']) && !isset($dep['max']) &&
                   40628:               !isset($dep['recommended']) && !isset($dep['exclude'])
                   40629:         ) {
                   40630:             if ($installed || $downloaded) {
                   40631:                 $installed = $installed ? 'installed' : 'downloaded';
                   40632:                 if (isset($dep['conflicts'])) {
                   40633:                     $rest = '';
                   40634:                     if ($version) {
                   40635:                         $rest = ", $installed version is " . $version;
                   40636:                     }
                   40637: 
                   40638:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40639:                         return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra . $rest);
                   40640:                     }
                   40641: 
                   40642:                     return $this->warning('warning: %s conflicts with package "' . $depname . '"' . $extra . $rest);
                   40643:                 }
                   40644: 
                   40645:                 return true;
                   40646:             }
                   40647: 
                   40648:             if (isset($dep['conflicts'])) {
                   40649:                 return true;
                   40650:             }
                   40651: 
                   40652:             if ($required) {
                   40653:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40654:                     return $this->raiseError('%s requires package "' . $depname . '"' . $extra);
                   40655:                 }
                   40656: 
                   40657:                 return $this->warning('warning: %s requires package "' . $depname . '"' . $extra);
                   40658:             }
                   40659: 
                   40660:             return $this->warning('%s can optionally use package "' . $depname . '"' . $extra);
                   40661:         }
                   40662: 
                   40663:         if (!$installed && !$downloaded) {
                   40664:             if (isset($dep['conflicts'])) {
                   40665:                 return true;
                   40666:             }
                   40667: 
                   40668:             if ($required) {
                   40669:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40670:                     return $this->raiseError('%s requires package "' . $depname . '"' . $extra);
                   40671:                 }
                   40672: 
                   40673:                 return $this->warning('warning: %s requires package "' . $depname . '"' . $extra);
                   40674:             }
                   40675: 
                   40676:             return $this->warning('%s can optionally use package "' . $depname . '"' . $extra);
                   40677:         }
                   40678: 
                   40679:         $fail = false;
                   40680:         if (isset($dep['min']) && version_compare($version, $dep['min'], '<')) {
                   40681:             $fail = true;
                   40682:         }
                   40683: 
                   40684:         if (isset($dep['max']) && version_compare($version, $dep['max'], '>')) {
                   40685:             $fail = true;
                   40686:         }
                   40687: 
                   40688:         if ($fail && !isset($dep['conflicts'])) {
                   40689:             $installed = $installed ? 'installed' : 'downloaded';
                   40690:             $dep['package'] = $dep['name'];
                   40691:             $dep = $this->_registry->parsedPackageNameToString($dep, true);
                   40692:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40693:                 return $this->raiseError('%s requires package "' . $depname . '"' .
                   40694:                     $extra . ", $installed version is " . $version);
                   40695:             }
                   40696: 
                   40697:             return $this->warning('warning: %s requires package "' . $depname . '"' .
                   40698:                 $extra . ", $installed version is " . $version);
                   40699:         } elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail &&
                   40700:               isset($dep['conflicts']) && !isset($dep['exclude'])) {
                   40701:             $installed = $installed ? 'installed' : 'downloaded';
                   40702:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40703:                 return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra .
                   40704:                     ", $installed version is " . $version);
                   40705:             }
                   40706: 
                   40707:             return $this->warning('warning: %s conflicts with package "' . $depname . '"' .
                   40708:                 $extra . ", $installed version is " . $version);
                   40709:         }
                   40710: 
                   40711:         if (isset($dep['exclude'])) {
                   40712:             $installed = $installed ? 'installed' : 'downloaded';
                   40713:             foreach ($dep['exclude'] as $exclude) {
                   40714:                 if (version_compare($version, $exclude, '==') && !isset($dep['conflicts'])) {
                   40715:                     if (!isset($this->_options['nodeps']) &&
                   40716:                           !isset($this->_options['force'])
                   40717:                     ) {
                   40718:                         return $this->raiseError('%s is not compatible with ' .
                   40719:                             $installed . ' package "' .
                   40720:                             $depname . '" version ' .
                   40721:                             $exclude);
                   40722:                     }
                   40723: 
                   40724:                     return $this->warning('warning: %s is not compatible with ' .
                   40725:                         $installed . ' package "' .
                   40726:                         $depname . '" version ' .
                   40727:                         $exclude);
                   40728:                 } elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) {
                   40729:                     $installed = $installed ? 'installed' : 'downloaded';
                   40730:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   40731:                         return $this->raiseError('%s conflicts with package "' . $depname . '"' .
                   40732:                             $extra . ", $installed version is " . $version);
                   40733:                     }
                   40734: 
                   40735:                     return $this->warning('warning: %s conflicts with package "' . $depname . '"' .
                   40736:                         $extra . ", $installed version is " . $version);
                   40737:                 }
                   40738:             }
                   40739:         }
                   40740: 
                   40741:         if (isset($dep['recommended'])) {
                   40742:             $installed = $installed ? 'installed' : 'downloaded';
                   40743:             if (version_compare($version, $dep['recommended'], '==')) {
                   40744:                 return true;
                   40745:             }
                   40746: 
                   40747:             if (!$found && $installed) {
                   40748:                 $param = $this->_registry->getPackage($dep['name'], $dep['channel']);
                   40749:             }
                   40750: 
                   40751:             if ($param) {
                   40752:                 $found = false;
                   40753:                 foreach ($params as $parent) {
                   40754:                     if ($parent->isEqual($this->_currentPackage)) {
                   40755:                         $found = true;
                   40756:                         break;
                   40757:                     }
                   40758:                 }
                   40759: 
                   40760:                 if ($found) {
                   40761:                     if ($param->isCompatible($parent)) {
                   40762:                         return true;
                   40763:                     }
                   40764:                 } else { // this is for validPackage() calls
                   40765:                     $parent = $this->_registry->getPackage($this->_currentPackage['package'],
                   40766:                         $this->_currentPackage['channel']);
                   40767:                     if ($parent !== null && $param->isCompatible($parent)) {
                   40768:                         return true;
                   40769:                     }
                   40770:                 }
                   40771:             }
                   40772: 
                   40773:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force']) &&
                   40774:                   !isset($this->_options['loose'])
                   40775:             ) {
                   40776:                 return $this->raiseError('%s dependency package "' . $depname .
                   40777:                     '" ' . $installed . ' version ' . $version .
                   40778:                     ' is not the recommended version ' . $dep['recommended'] .
                   40779:                     ', but may be compatible, use --force to install');
                   40780:             }
                   40781: 
                   40782:             return $this->warning('warning: %s dependency package "' . $depname .
                   40783:                 '" ' . $installed . ' version ' . $version .
                   40784:                 ' is not the recommended version ' . $dep['recommended']);
                   40785:         }
                   40786: 
                   40787:         return true;
                   40788:     }
                   40789: 
                   40790:     function _validatePackageInstall($dep, $required, $depv1 = false)
                   40791:     {
                   40792:         return $this->_validatePackageDownload($dep, $required, array(), $depv1);
                   40793:     }
                   40794: 
                   40795:     /**
                   40796:      * Verify that uninstalling packages passed in to command line is OK.
                   40797:      *
                   40798:      * @param PEAR_Installer $dl
                   40799:      * @return PEAR_Error|true
                   40800:      */
                   40801:     function validatePackageUninstall(&$dl)
                   40802:     {
                   40803:         if (PEAR::isError($this->_dependencydb)) {
                   40804:             return $this->_dependencydb;
                   40805:         }
                   40806: 
                   40807:         $params = array();
                   40808:         // construct an array of "downloaded" packages to fool the package dependency checker
                   40809:         // into using these to validate uninstalls of circular dependencies
                   40810:         $downloaded = &$dl->getUninstallPackages();
                   40811:         foreach ($downloaded as $i => $pf) {
                   40812:             if (!class_exists('PEAR_Downloader_Package')) {
                   40813:                 require_once 'PEAR/Downloader/Package.php';
                   40814:             }
                   40815:             $dp = &new PEAR_Downloader_Package($dl);
                   40816:             $dp->setPackageFile($downloaded[$i]);
                   40817:             $params[$i] = &$dp;
                   40818:         }
                   40819: 
                   40820:         // check cache
                   40821:         $memyselfandI = strtolower($this->_currentPackage['channel']) . '/' .
                   40822:             strtolower($this->_currentPackage['package']);
                   40823:         if (isset($dl->___uninstall_package_cache)) {
                   40824:             $badpackages = $dl->___uninstall_package_cache;
                   40825:             if (isset($badpackages[$memyselfandI]['warnings'])) {
                   40826:                 foreach ($badpackages[$memyselfandI]['warnings'] as $warning) {
                   40827:                     $dl->log(0, $warning[0]);
                   40828:                 }
                   40829:             }
                   40830: 
                   40831:             if (isset($badpackages[$memyselfandI]['errors'])) {
                   40832:                 foreach ($badpackages[$memyselfandI]['errors'] as $error) {
                   40833:                     if (is_array($error)) {
                   40834:                         $dl->log(0, $error[0]);
                   40835:                     } else {
                   40836:                         $dl->log(0, $error->getMessage());
                   40837:                     }
                   40838:                 }
                   40839: 
                   40840:                 if (isset($this->_options['nodeps']) || isset($this->_options['force'])) {
                   40841:                     return $this->warning(
                   40842:                         'warning: %s should not be uninstalled, other installed packages depend ' .
                   40843:                         'on this package');
                   40844:                 }
                   40845: 
                   40846:                 return $this->raiseError(
                   40847:                     '%s cannot be uninstalled, other installed packages depend on this package');
                   40848:             }
                   40849: 
                   40850:             return true;
                   40851:         }
                   40852: 
                   40853:         // first, list the immediate parents of each package to be uninstalled
                   40854:         $perpackagelist = array();
                   40855:         $allparents = array();
                   40856:         foreach ($params as $i => $param) {
                   40857:             $a = array(
                   40858:                 'channel' => strtolower($param->getChannel()),
                   40859:                 'package' => strtolower($param->getPackage())
                   40860:             );
                   40861: 
                   40862:             $deps = $this->_dependencydb->getDependentPackages($a);
                   40863:             if ($deps) {
                   40864:                 foreach ($deps as $d) {
                   40865:                     $pardeps = $this->_dependencydb->getDependencies($d);
                   40866:                     foreach ($pardeps as $dep) {
                   40867:                         if (strtolower($dep['dep']['channel']) == $a['channel'] &&
                   40868:                               strtolower($dep['dep']['name']) == $a['package']) {
                   40869:                             if (!isset($perpackagelist[$a['channel'] . '/' . $a['package']])) {
                   40870:                                 $perpackagelist[$a['channel'] . '/' . $a['package']] = array();
                   40871:                             }
                   40872:                             $perpackagelist[$a['channel'] . '/' . $a['package']][]
                   40873:                                 = array($d['channel'] . '/' . $d['package'], $dep);
                   40874:                             if (!isset($allparents[$d['channel'] . '/' . $d['package']])) {
                   40875:                                 $allparents[$d['channel'] . '/' . $d['package']] = array();
                   40876:                             }
                   40877:                             if (!isset($allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']])) {
                   40878:                                 $allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']] = array();
                   40879:                             }
                   40880:                             $allparents[$d['channel'] . '/' . $d['package']]
                   40881:                                        [$a['channel'] . '/' . $a['package']][]
                   40882:                                 = array($d, $dep);
                   40883:                         }
                   40884:                     }
                   40885:                 }
                   40886:             }
                   40887:         }
                   40888: 
                   40889:         // next, remove any packages from the parents list that are not installed
                   40890:         $remove = array();
                   40891:         foreach ($allparents as $parent => $d1) {
                   40892:             foreach ($d1 as $d) {
                   40893:                 if ($this->_registry->packageExists($d[0][0]['package'], $d[0][0]['channel'])) {
                   40894:                     continue;
                   40895:                 }
                   40896:                 $remove[$parent] = true;
                   40897:             }
                   40898:         }
                   40899: 
                   40900:         // next remove any packages from the parents list that are not passed in for
                   40901:         // uninstallation
                   40902:         foreach ($allparents as $parent => $d1) {
                   40903:             foreach ($d1 as $d) {
                   40904:                 foreach ($params as $param) {
                   40905:                     if (strtolower($param->getChannel()) == $d[0][0]['channel'] &&
                   40906:                           strtolower($param->getPackage()) == $d[0][0]['package']) {
                   40907:                         // found it
                   40908:                         continue 3;
                   40909:                     }
                   40910:                 }
                   40911:                 $remove[$parent] = true;
                   40912:             }
                   40913:         }
                   40914: 
                   40915:         // remove all packages whose dependencies fail
                   40916:         // save which ones failed for error reporting
                   40917:         $badchildren = array();
                   40918:         do {
                   40919:             $fail = false;
                   40920:             foreach ($remove as $package => $unused) {
                   40921:                 if (!isset($allparents[$package])) {
                   40922:                     continue;
                   40923:                 }
                   40924: 
                   40925:                 foreach ($allparents[$package] as $kid => $d1) {
                   40926:                     foreach ($d1 as $depinfo) {
                   40927:                         if ($depinfo[1]['type'] != 'optional') {
                   40928:                             if (isset($badchildren[$kid])) {
                   40929:                                 continue;
                   40930:                             }
                   40931:                             $badchildren[$kid] = true;
                   40932:                             $remove[$kid] = true;
                   40933:                             $fail = true;
                   40934:                             continue 2;
                   40935:                         }
                   40936:                     }
                   40937:                 }
                   40938:                 if ($fail) {
                   40939:                     // start over, we removed some children
                   40940:                     continue 2;
                   40941:                 }
                   40942:             }
                   40943:         } while ($fail);
                   40944: 
                   40945:         // next, construct the list of packages that can't be uninstalled
                   40946:         $badpackages = array();
                   40947:         $save = $this->_currentPackage;
                   40948:         foreach ($perpackagelist as $package => $packagedeps) {
                   40949:             foreach ($packagedeps as $parent) {
                   40950:                 if (!isset($remove[$parent[0]])) {
                   40951:                     continue;
                   40952:                 }
                   40953: 
                   40954:                 $packagename = $this->_registry->parsePackageName($parent[0]);
                   40955:                 $packagename['channel'] = $this->_registry->channelAlias($packagename['channel']);
                   40956:                 $pa = $this->_registry->getPackage($packagename['package'], $packagename['channel']);
                   40957:                 $packagename['package'] = $pa->getPackage();
                   40958:                 $this->_currentPackage = $packagename;
                   40959:                 // parent is not present in uninstall list, make sure we can actually
                   40960:                 // uninstall it (parent dep is optional)
                   40961:                 $parentname['channel'] = $this->_registry->channelAlias($parent[1]['dep']['channel']);
                   40962:                 $pa = $this->_registry->getPackage($parent[1]['dep']['name'], $parent[1]['dep']['channel']);
                   40963:                 $parentname['package'] = $pa->getPackage();
                   40964:                 $parent[1]['dep']['package'] = $parentname['package'];
                   40965:                 $parent[1]['dep']['channel'] = $parentname['channel'];
                   40966:                 if ($parent[1]['type'] == 'optional') {
                   40967:                     $test = $this->_validatePackageUninstall($parent[1]['dep'], false, $dl);
                   40968:                     if ($test !== true) {
                   40969:                         $badpackages[$package]['warnings'][] = $test;
                   40970:                     }
                   40971:                 } else {
                   40972:                     $test = $this->_validatePackageUninstall($parent[1]['dep'], true, $dl);
                   40973:                     if ($test !== true) {
                   40974:                         $badpackages[$package]['errors'][] = $test;
                   40975:                     }
                   40976:                 }
                   40977:             }
                   40978:         }
                   40979: 
                   40980:         $this->_currentPackage          = $save;
                   40981:         $dl->___uninstall_package_cache = $badpackages;
                   40982:         if (isset($badpackages[$memyselfandI])) {
                   40983:             if (isset($badpackages[$memyselfandI]['warnings'])) {
                   40984:                 foreach ($badpackages[$memyselfandI]['warnings'] as $warning) {
                   40985:                     $dl->log(0, $warning[0]);
                   40986:                 }
                   40987:             }
                   40988: 
                   40989:             if (isset($badpackages[$memyselfandI]['errors'])) {
                   40990:                 foreach ($badpackages[$memyselfandI]['errors'] as $error) {
                   40991:                     if (is_array($error)) {
                   40992:                         $dl->log(0, $error[0]);
                   40993:                     } else {
                   40994:                         $dl->log(0, $error->getMessage());
                   40995:                     }
                   40996:                 }
                   40997: 
                   40998:                 if (isset($this->_options['nodeps']) || isset($this->_options['force'])) {
                   40999:                     return $this->warning(
                   41000:                         'warning: %s should not be uninstalled, other installed packages depend ' .
                   41001:                         'on this package');
                   41002:                 }
                   41003: 
                   41004:                 return $this->raiseError(
                   41005:                     '%s cannot be uninstalled, other installed packages depend on this package');
                   41006:             }
                   41007:         }
                   41008: 
                   41009:         return true;
                   41010:     }
                   41011: 
                   41012:     function _validatePackageUninstall($dep, $required, $dl)
                   41013:     {
                   41014:         $depname = $this->_registry->parsedPackageNameToString($dep, true);
                   41015:         $version = $this->_registry->packageinfo($dep['package'], 'version', $dep['channel']);
                   41016:         if (!$version) {
                   41017:             return true;
                   41018:         }
                   41019: 
                   41020:         $extra = $this->_getExtraString($dep);
                   41021:         if (isset($dep['exclude']) && !is_array($dep['exclude'])) {
                   41022:             $dep['exclude'] = array($dep['exclude']);
                   41023:         }
                   41024: 
                   41025:         if (isset($dep['conflicts'])) {
                   41026:             return true; // uninstall OK - these packages conflict (probably installed with --force)
                   41027:         }
                   41028: 
                   41029:         if (!isset($dep['min']) && !isset($dep['max'])) {
                   41030:             if (!$required) {
                   41031:                 return $this->warning('"' . $depname . '" can be optionally used by ' .
                   41032:                         'installed package %s' . $extra);
                   41033:             }
                   41034: 
                   41035:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   41036:                 return $this->raiseError('"' . $depname . '" is required by ' .
                   41037:                     'installed package %s' . $extra);
                   41038:             }
                   41039: 
                   41040:             return $this->warning('warning: "' . $depname . '" is required by ' .
                   41041:                 'installed package %s' . $extra);
                   41042:         }
                   41043: 
                   41044:         $fail = false;
                   41045:         if (isset($dep['min']) && version_compare($version, $dep['min'], '>=')) {
                   41046:             $fail = true;
                   41047:         }
                   41048: 
                   41049:         if (isset($dep['max']) && version_compare($version, $dep['max'], '<=')) {
                   41050:             $fail = true;
                   41051:         }
                   41052: 
                   41053:         // we re-use this variable, preserve the original value
                   41054:         $saverequired = $required;
                   41055:         if (!$required) {
                   41056:             return $this->warning($depname . $extra . ' can be optionally used by installed package' .
                   41057:                     ' "%s"');
                   41058:         }
                   41059: 
                   41060:         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
                   41061:             return $this->raiseError($depname . $extra . ' is required by installed package' .
                   41062:                 ' "%s"');
                   41063:         }
                   41064: 
                   41065:         return $this->raiseError('warning: ' . $depname . $extra .
                   41066:             ' is required by installed package "%s"');
                   41067:     }
                   41068: 
                   41069:     /**
                   41070:      * validate a downloaded package against installed packages
                   41071:      *
                   41072:      * As of PEAR 1.4.3, this will only validate
                   41073:      *
                   41074:      * @param array|PEAR_Downloader_Package|PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   41075:      *              $pkg package identifier (either
                   41076:      *                   array('package' => blah, 'channel' => blah) or an array with
                   41077:      *                   index 'info' referencing an object)
                   41078:      * @param PEAR_Downloader $dl
                   41079:      * @param array $params full list of packages to install
                   41080:      * @return true|PEAR_Error
                   41081:      */
                   41082:     function validatePackage($pkg, &$dl, $params = array())
                   41083:     {
                   41084:         if (is_array($pkg) && isset($pkg['info'])) {
                   41085:             $deps = $this->_dependencydb->getDependentPackageDependencies($pkg['info']);
                   41086:         } else {
                   41087:             $deps = $this->_dependencydb->getDependentPackageDependencies($pkg);
                   41088:         }
                   41089: 
                   41090:         $fail = false;
                   41091:         if ($deps) {
                   41092:             if (!class_exists('PEAR_Downloader_Package')) {
                   41093:                 require_once 'PEAR/Downloader/Package.php';
                   41094:             }
                   41095: 
                   41096:             $dp = &new PEAR_Downloader_Package($dl);
                   41097:             if (is_object($pkg)) {
                   41098:                 $dp->setPackageFile($pkg);
                   41099:             } else {
                   41100:                 $dp->setDownloadURL($pkg);
                   41101:             }
                   41102: 
                   41103:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   41104:             foreach ($deps as $channel => $info) {
                   41105:                 foreach ($info as $package => $ds) {
                   41106:                     foreach ($params as $packd) {
                   41107:                         if (strtolower($packd->getPackage()) == strtolower($package) &&
                   41108:                               $packd->getChannel() == $channel) {
                   41109:                             $dl->log(3, 'skipping installed package check of "' .
                   41110:                                         $this->_registry->parsedPackageNameToString(
                   41111:                                             array('channel' => $channel, 'package' => $package),
                   41112:                                             true) .
                   41113:                                         '", version "' . $packd->getVersion() . '" will be ' .
                   41114:                                         'downloaded and installed');
                   41115:                             continue 2; // jump to next package
                   41116:                         }
                   41117:                     }
                   41118: 
                   41119:                     foreach ($ds as $d) {
                   41120:                         $checker = &new PEAR_Dependency2($this->_config, $this->_options,
                   41121:                             array('channel' => $channel, 'package' => $package), $this->_state);
                   41122:                         $dep = $d['dep'];
                   41123:                         $required = $d['type'] == 'required';
                   41124:                         $ret = $checker->_validatePackageDownload($dep, $required, array(&$dp));
                   41125:                         if (is_array($ret)) {
                   41126:                             $dl->log(0, $ret[0]);
                   41127:                         } elseif (PEAR::isError($ret)) {
                   41128:                             $dl->log(0, $ret->getMessage());
                   41129:                             $fail = true;
                   41130:                         }
                   41131:                     }
                   41132:                 }
                   41133:             }
                   41134:             PEAR::popErrorHandling();
                   41135:         }
                   41136: 
                   41137:         if ($fail) {
                   41138:             return $this->raiseError(
                   41139:                 '%s cannot be installed, conflicts with installed packages');
                   41140:         }
                   41141: 
                   41142:         return true;
                   41143:     }
                   41144: 
                   41145:     /**
                   41146:      * validate a package.xml 1.0 dependency
                   41147:      */
                   41148:     function validateDependency1($dep, $params = array())
                   41149:     {
                   41150:         if (!isset($dep['optional'])) {
                   41151:             $dep['optional'] = 'no';
                   41152:         }
                   41153: 
                   41154:         list($newdep, $type) = $this->normalizeDep($dep);
                   41155:         if (!$newdep) {
                   41156:             return $this->raiseError("Invalid Dependency");
                   41157:         }
                   41158: 
                   41159:         if (method_exists($this, "validate{$type}Dependency")) {
                   41160:             return $this->{"validate{$type}Dependency"}($newdep, $dep['optional'] == 'no',
                   41161:                 $params, true);
                   41162:         }
                   41163:     }
                   41164: 
                   41165:     /**
                   41166:      * Convert a 1.0 dep into a 2.0 dep
                   41167:      */
                   41168:     function normalizeDep($dep)
                   41169:     {
                   41170:         $types = array(
                   41171:             'pkg' => 'Package',
                   41172:             'ext' => 'Extension',
                   41173:             'os' => 'Os',
                   41174:             'php' => 'Php'
                   41175:         );
                   41176: 
                   41177:         if (!isset($types[$dep['type']])) {
                   41178:             return array(false, false);
                   41179:         }
                   41180: 
                   41181:         $type = $types[$dep['type']];
                   41182: 
                   41183:         $newdep = array();
                   41184:         switch ($type) {
                   41185:             case 'Package' :
                   41186:                 $newdep['channel'] = 'pear.php.net';
                   41187:             case 'Extension' :
                   41188:             case 'Os' :
                   41189:                 $newdep['name'] = $dep['name'];
                   41190:             break;
                   41191:         }
                   41192: 
                   41193:         $dep['rel'] = PEAR_Dependency2::signOperator($dep['rel']);
                   41194:         switch ($dep['rel']) {
                   41195:             case 'has' :
                   41196:                 return array($newdep, $type);
                   41197:             break;
                   41198:             case 'not' :
                   41199:                 $newdep['conflicts'] = true;
                   41200:             break;
                   41201:             case '>=' :
                   41202:             case '>' :
                   41203:                 $newdep['min'] = $dep['version'];
                   41204:                 if ($dep['rel'] == '>') {
                   41205:                     $newdep['exclude'] = $dep['version'];
                   41206:                 }
                   41207:             break;
                   41208:             case '<=' :
                   41209:             case '<' :
                   41210:                 $newdep['max'] = $dep['version'];
                   41211:                 if ($dep['rel'] == '<') {
                   41212:                     $newdep['exclude'] = $dep['version'];
                   41213:                 }
                   41214:             break;
                   41215:             case 'ne' :
                   41216:             case '!=' :
                   41217:                 $newdep['min'] = '0';
                   41218:                 $newdep['max'] = '100000';
                   41219:                 $newdep['exclude'] = $dep['version'];
                   41220:             break;
                   41221:             case '==' :
                   41222:                 $newdep['min'] = $dep['version'];
                   41223:                 $newdep['max'] = $dep['version'];
                   41224:             break;
                   41225:         }
                   41226:         if ($type == 'Php') {
                   41227:             if (!isset($newdep['min'])) {
                   41228:                 $newdep['min'] = '4.4.0';
                   41229:             }
                   41230: 
                   41231:             if (!isset($newdep['max'])) {
                   41232:                 $newdep['max'] = '6.0.0';
                   41233:             }
                   41234:         }
                   41235:         return array($newdep, $type);
                   41236:     }
                   41237: 
                   41238:     /**
                   41239:      * Converts text comparing operators to them sign equivalents
                   41240:      *
                   41241:      * Example: 'ge' to '>='
                   41242:      *
                   41243:      * @access public
                   41244:      * @param  string Operator
                   41245:      * @return string Sign equivalent
                   41246:      */
                   41247:     function signOperator($operator)
                   41248:     {
                   41249:         switch($operator) {
                   41250:             case 'lt': return '<';
                   41251:             case 'le': return '<=';
                   41252:             case 'gt': return '>';
                   41253:             case 'ge': return '>=';
                   41254:             case 'eq': return '==';
                   41255:             case 'ne': return '!=';
                   41256:             default:
                   41257:                 return $operator;
                   41258:         }
                   41259:     }
                   41260: 
                   41261:     function raiseError($msg)
                   41262:     {
                   41263:         if (isset($this->_options['ignore-errors'])) {
                   41264:             return $this->warning($msg);
                   41265:         }
                   41266: 
                   41267:         return PEAR::raiseError(sprintf($msg, $this->_registry->parsedPackageNameToString(
                   41268:             $this->_currentPackage, true)));
                   41269:     }
                   41270: 
                   41271:     function warning($msg)
                   41272:     {
                   41273:         return array(sprintf($msg, $this->_registry->parsedPackageNameToString(
                   41274:             $this->_currentPackage, true)));
                   41275:     }
1.1.1.2 ! misho    41276: }PEAR-1.9.4/PEAR/Downloader.php0000644000076500000240000020203111605156614014570 0ustar  helgistaff<?php
1.1       misho    41277: /**
                   41278:  * PEAR_Downloader, the PEAR Installer's download utility class
                   41279:  *
                   41280:  * PHP versions 4 and 5
                   41281:  *
                   41282:  * @category   pear
                   41283:  * @package    PEAR
                   41284:  * @author     Greg Beaver <cellog@php.net>
                   41285:  * @author     Stig Bakken <ssb@php.net>
                   41286:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   41287:  * @author     Martin Jansen <mj@php.net>
                   41288:  * @copyright  1997-2009 The Authors
                   41289:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   41290:  * @version    CVS: $Id: Downloader.php 313024 2011-07-06 19:51:24Z dufuz $
                   41291:  * @link       http://pear.php.net/package/PEAR
                   41292:  * @since      File available since Release 1.3.0
                   41293:  */
                   41294: 
                   41295: /**
                   41296:  * Needed for constants, extending
                   41297:  */
                   41298: require_once 'PEAR/Common.php';
                   41299: 
                   41300: define('PEAR_INSTALLER_OK',       1);
                   41301: define('PEAR_INSTALLER_FAILED',   0);
                   41302: define('PEAR_INSTALLER_SKIPPED', -1);
                   41303: define('PEAR_INSTALLER_ERROR_NO_PREF_STATE', 2);
                   41304: 
                   41305: /**
                   41306:  * Administration class used to download anything from the internet (PEAR Packages,
                   41307:  * static URLs, xml files)
                   41308:  *
                   41309:  * @category   pear
                   41310:  * @package    PEAR
                   41311:  * @author     Greg Beaver <cellog@php.net>
                   41312:  * @author     Stig Bakken <ssb@php.net>
                   41313:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   41314:  * @author     Martin Jansen <mj@php.net>
                   41315:  * @copyright  1997-2009 The Authors
                   41316:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   41317:  * @version    Release: 1.9.4
                   41318:  * @link       http://pear.php.net/package/PEAR
                   41319:  * @since      Class available since Release 1.3.0
                   41320:  */
                   41321: class PEAR_Downloader extends PEAR_Common
                   41322: {
                   41323:     /**
                   41324:      * @var PEAR_Registry
                   41325:      * @access private
                   41326:      */
                   41327:     var $_registry;
                   41328: 
                   41329:     /**
                   41330:      * Preferred Installation State (snapshot, devel, alpha, beta, stable)
                   41331:      * @var string|null
                   41332:      * @access private
                   41333:      */
                   41334:     var $_preferredState;
                   41335: 
                   41336:     /**
                   41337:      * Options from command-line passed to Install.
                   41338:      *
                   41339:      * Recognized options:<br />
                   41340:      *  - onlyreqdeps   : install all required dependencies as well
                   41341:      *  - alldeps       : install all dependencies, including optional
                   41342:      *  - installroot   : base relative path to install files in
                   41343:      *  - force         : force a download even if warnings would prevent it
                   41344:      *  - nocompress    : download uncompressed tarballs
                   41345:      * @see PEAR_Command_Install
                   41346:      * @access private
                   41347:      * @var array
                   41348:      */
                   41349:     var $_options;
                   41350: 
                   41351:     /**
                   41352:      * Downloaded Packages after a call to download().
                   41353:      *
                   41354:      * Format of each entry:
                   41355:      *
                   41356:      * <code>
                   41357:      * array('pkg' => 'package_name', 'file' => '/path/to/local/file',
                   41358:      *    'info' => array() // parsed package.xml
                   41359:      * );
                   41360:      * </code>
                   41361:      * @access private
                   41362:      * @var array
                   41363:      */
                   41364:     var $_downloadedPackages = array();
                   41365: 
                   41366:     /**
                   41367:      * Packages slated for download.
                   41368:      *
                   41369:      * This is used to prevent downloading a package more than once should it be a dependency
                   41370:      * for two packages to be installed.
                   41371:      * Format of each entry:
                   41372:      *
                   41373:      * <pre>
                   41374:      * array('package_name1' => parsed package.xml, 'package_name2' => parsed package.xml,
                   41375:      * );
                   41376:      * </pre>
                   41377:      * @access private
                   41378:      * @var array
                   41379:      */
                   41380:     var $_toDownload = array();
                   41381: 
                   41382:     /**
                   41383:      * Array of every package installed, with names lower-cased.
                   41384:      *
                   41385:      * Format:
                   41386:      * <code>
                   41387:      * array('package1' => 0, 'package2' => 1, );
                   41388:      * </code>
                   41389:      * @var array
                   41390:      */
                   41391:     var $_installed = array();
                   41392: 
                   41393:     /**
                   41394:      * @var array
                   41395:      * @access private
                   41396:      */
                   41397:     var $_errorStack = array();
                   41398: 
                   41399:     /**
                   41400:      * @var boolean
                   41401:      * @access private
                   41402:      */
                   41403:     var $_internalDownload = false;
                   41404: 
                   41405:     /**
                   41406:      * Temporary variable used in sorting packages by dependency in {@link sortPkgDeps()}
                   41407:      * @var array
                   41408:      * @access private
                   41409:      */
                   41410:     var $_packageSortTree;
                   41411: 
                   41412:     /**
                   41413:      * Temporary directory, or configuration value where downloads will occur
                   41414:      * @var string
                   41415:      */
                   41416:     var $_downloadDir;
                   41417: 
                   41418:     /**
                   41419:      * @param PEAR_Frontend_*
                   41420:      * @param array
                   41421:      * @param PEAR_Config
                   41422:      */
                   41423:     function PEAR_Downloader(&$ui, $options, &$config)
                   41424:     {
                   41425:         parent::PEAR_Common();
                   41426:         $this->_options = $options;
                   41427:         $this->config = &$config;
                   41428:         $this->_preferredState = $this->config->get('preferred_state');
                   41429:         $this->ui = &$ui;
                   41430:         if (!$this->_preferredState) {
                   41431:             // don't inadvertantly use a non-set preferred_state
                   41432:             $this->_preferredState = null;
                   41433:         }
                   41434: 
                   41435:         if (isset($this->_options['installroot'])) {
                   41436:             $this->config->setInstallRoot($this->_options['installroot']);
                   41437:         }
                   41438:         $this->_registry = &$config->getRegistry();
                   41439: 
                   41440:         if (isset($this->_options['alldeps']) || isset($this->_options['onlyreqdeps'])) {
                   41441:             $this->_installed = $this->_registry->listAllPackages();
                   41442:             foreach ($this->_installed as $key => $unused) {
                   41443:                 if (!count($unused)) {
                   41444:                     continue;
                   41445:                 }
                   41446:                 $strtolower = create_function('$a','return strtolower($a);');
                   41447:                 array_walk($this->_installed[$key], $strtolower);
                   41448:             }
                   41449:         }
                   41450:     }
                   41451: 
                   41452:     /**
                   41453:      * Attempt to discover a channel's remote capabilities from
                   41454:      * its server name
                   41455:      * @param string
                   41456:      * @return boolean
                   41457:      */
                   41458:     function discover($channel)
                   41459:     {
                   41460:         $this->log(1, 'Attempting to discover channel "' . $channel . '"...');
                   41461:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   41462:         $callback = $this->ui ? array(&$this, '_downloadCallback') : null;
                   41463:         if (!class_exists('System')) {
                   41464:             require_once 'System.php';
                   41465:         }
                   41466: 
                   41467:         $tmpdir = $this->config->get('temp_dir');
                   41468:         $tmp = System::mktemp('-d -t "' . $tmpdir . '"');
                   41469:         $a   = $this->downloadHttp('http://' . $channel . '/channel.xml', $this->ui, $tmp, $callback, false);
                   41470:         PEAR::popErrorHandling();
                   41471:         if (PEAR::isError($a)) {
                   41472:             // Attempt to fallback to https automatically.
                   41473:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   41474:             $this->log(1, 'Attempting fallback to https instead of http on channel "' . $channel . '"...');
                   41475:             $a = $this->downloadHttp('https://' . $channel . '/channel.xml', $this->ui, $tmp, $callback, false);
                   41476:             PEAR::popErrorHandling();
                   41477:             if (PEAR::isError($a)) {
                   41478:                 return false;
                   41479:             }
                   41480:         }
                   41481: 
                   41482:         list($a, $lastmodified) = $a;
                   41483:         if (!class_exists('PEAR_ChannelFile')) {
                   41484:             require_once 'PEAR/ChannelFile.php';
                   41485:         }
                   41486: 
                   41487:         $b = new PEAR_ChannelFile;
                   41488:         if ($b->fromXmlFile($a)) {
                   41489:             unlink($a);
                   41490:             if ($this->config->get('auto_discover')) {
                   41491:                 $this->_registry->addChannel($b, $lastmodified);
                   41492:                 $alias = $b->getName();
                   41493:                 if ($b->getName() == $this->_registry->channelName($b->getAlias())) {
                   41494:                     $alias = $b->getAlias();
                   41495:                 }
                   41496: 
                   41497:                 $this->log(1, 'Auto-discovered channel "' . $channel .
                   41498:                     '", alias "' . $alias . '", adding to registry');
                   41499:             }
                   41500: 
                   41501:             return true;
                   41502:         }
                   41503: 
                   41504:         unlink($a);
                   41505:         return false;
                   41506:     }
                   41507: 
                   41508:     /**
                   41509:      * For simpler unit-testing
                   41510:      * @param PEAR_Downloader
                   41511:      * @return PEAR_Downloader_Package
                   41512:      */
                   41513:     function &newDownloaderPackage(&$t)
                   41514:     {
                   41515:         if (!class_exists('PEAR_Downloader_Package')) {
                   41516:             require_once 'PEAR/Downloader/Package.php';
                   41517:         }
                   41518:         $a = &new PEAR_Downloader_Package($t);
                   41519:         return $a;
                   41520:     }
                   41521: 
                   41522:     /**
                   41523:      * For simpler unit-testing
                   41524:      * @param PEAR_Config
                   41525:      * @param array
                   41526:      * @param array
                   41527:      * @param int
                   41528:      */
                   41529:     function &getDependency2Object(&$c, $i, $p, $s)
                   41530:     {
                   41531:         if (!class_exists('PEAR_Dependency2')) {
                   41532:             require_once 'PEAR/Dependency2.php';
                   41533:         }
                   41534:         $z = &new PEAR_Dependency2($c, $i, $p, $s);
                   41535:         return $z;
                   41536:     }
                   41537: 
                   41538:     function &download($params)
                   41539:     {
                   41540:         if (!count($params)) {
                   41541:             $a = array();
                   41542:             return $a;
                   41543:         }
                   41544: 
                   41545:         if (!isset($this->_registry)) {
                   41546:             $this->_registry = &$this->config->getRegistry();
                   41547:         }
                   41548: 
                   41549:         $channelschecked = array();
                   41550:         // convert all parameters into PEAR_Downloader_Package objects
                   41551:         foreach ($params as $i => $param) {
                   41552:             $params[$i] = &$this->newDownloaderPackage($this);
                   41553:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   41554:             $err = $params[$i]->initialize($param);
                   41555:             PEAR::staticPopErrorHandling();
                   41556:             if (!$err) {
                   41557:                 // skip parameters that were missed by preferred_state
                   41558:                 continue;
                   41559:             }
                   41560: 
                   41561:             if (PEAR::isError($err)) {
                   41562:                 if (!isset($this->_options['soft']) && $err->getMessage() !== '') {
                   41563:                     $this->log(0, $err->getMessage());
                   41564:                 }
                   41565: 
                   41566:                 $params[$i] = false;
                   41567:                 if (is_object($param)) {
                   41568:                     $param = $param->getChannel() . '/' . $param->getPackage();
                   41569:                 }
                   41570: 
                   41571:                 if (!isset($this->_options['soft'])) {
                   41572:                     $this->log(2, 'Package "' . $param . '" is not valid');
                   41573:                 }
                   41574: 
                   41575:                 // Message logged above in a specific verbose mode, passing null to not show up on CLI
                   41576:                 $this->pushError(null, PEAR_INSTALLER_SKIPPED);
                   41577:             } else {
                   41578:                 do {
                   41579:                     if ($params[$i] && $params[$i]->getType() == 'local') {
                   41580:                         // bug #7090 skip channel.xml check for local packages
                   41581:                         break;
                   41582:                     }
                   41583: 
                   41584:                     if ($params[$i] && !isset($channelschecked[$params[$i]->getChannel()]) &&
                   41585:                           !isset($this->_options['offline'])
                   41586:                     ) {
                   41587:                         $channelschecked[$params[$i]->getChannel()] = true;
                   41588:                         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   41589:                         if (!class_exists('System')) {
                   41590:                             require_once 'System.php';
                   41591:                         }
                   41592: 
                   41593:                         $curchannel = &$this->_registry->getChannel($params[$i]->getChannel());
                   41594:                         if (PEAR::isError($curchannel)) {
                   41595:                             PEAR::staticPopErrorHandling();
                   41596:                             return $this->raiseError($curchannel);
                   41597:                         }
                   41598: 
                   41599:                         if (PEAR::isError($dir = $this->getDownloadDir())) {
                   41600:                             PEAR::staticPopErrorHandling();
                   41601:                             break;
                   41602:                         }
                   41603: 
                   41604:                         $mirror = $this->config->get('preferred_mirror', null, $params[$i]->getChannel());
                   41605:                         $url    = 'http://' . $mirror . '/channel.xml';
                   41606:                         $a = $this->downloadHttp($url, $this->ui, $dir, null, $curchannel->lastModified());
                   41607: 
                   41608:                         PEAR::staticPopErrorHandling();
                   41609:                         if (PEAR::isError($a) || !$a) {
                   41610:                             // Attempt fallback to https automatically
                   41611:                             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   41612:                             $a = $this->downloadHttp('https://' . $mirror .
                   41613:                                 '/channel.xml', $this->ui, $dir, null, $curchannel->lastModified());
                   41614: 
                   41615:                             PEAR::staticPopErrorHandling();
                   41616:                             if (PEAR::isError($a) || !$a) {
                   41617:                                 break;
                   41618:                             }
                   41619:                         }
                   41620:                         $this->log(0, 'WARNING: channel "' . $params[$i]->getChannel() . '" has ' .
                   41621:                             'updated its protocols, use "' . PEAR_RUNTYPE . ' channel-update ' . $params[$i]->getChannel() .
                   41622:                             '" to update');
                   41623:                     }
                   41624:                 } while (false);
                   41625: 
                   41626:                 if ($params[$i] && !isset($this->_options['downloadonly'])) {
                   41627:                     if (isset($this->_options['packagingroot'])) {
                   41628:                         $checkdir = $this->_prependPath(
                   41629:                             $this->config->get('php_dir', null, $params[$i]->getChannel()),
                   41630:                             $this->_options['packagingroot']);
                   41631:                     } else {
                   41632:                         $checkdir = $this->config->get('php_dir',
                   41633:                             null, $params[$i]->getChannel());
                   41634:                     }
                   41635: 
                   41636:                     while ($checkdir && $checkdir != '/' && !file_exists($checkdir)) {
                   41637:                         $checkdir = dirname($checkdir);
                   41638:                     }
                   41639: 
                   41640:                     if ($checkdir == '.') {
                   41641:                         $checkdir = '/';
                   41642:                     }
                   41643: 
                   41644:                     if (!is_writeable($checkdir)) {
                   41645:                         return PEAR::raiseError('Cannot install, php_dir for channel "' .
                   41646:                             $params[$i]->getChannel() . '" is not writeable by the current user');
                   41647:                     }
                   41648:                 }
                   41649:             }
                   41650:         }
                   41651: 
                   41652:         unset($channelschecked);
                   41653:         PEAR_Downloader_Package::removeDuplicates($params);
                   41654:         if (!count($params)) {
                   41655:             $a = array();
                   41656:             return $a;
                   41657:         }
                   41658: 
                   41659:         if (!isset($this->_options['nodeps']) && !isset($this->_options['offline'])) {
                   41660:             $reverify = true;
                   41661:             while ($reverify) {
                   41662:                 $reverify = false;
                   41663:                 foreach ($params as $i => $param) {
                   41664:                     //PHP Bug 40768 / PEAR Bug #10944
                   41665:                     //Nested foreaches fail in PHP 5.2.1
                   41666:                     key($params);
                   41667:                     $ret = $params[$i]->detectDependencies($params);
                   41668:                     if (PEAR::isError($ret)) {
                   41669:                         $reverify = true;
                   41670:                         $params[$i] = false;
                   41671:                         PEAR_Downloader_Package::removeDuplicates($params);
                   41672:                         if (!isset($this->_options['soft'])) {
                   41673:                             $this->log(0, $ret->getMessage());
                   41674:                         }
                   41675:                         continue 2;
                   41676:                     }
                   41677:                 }
                   41678:             }
                   41679:         }
                   41680: 
                   41681:         if (isset($this->_options['offline'])) {
                   41682:             $this->log(3, 'Skipping dependency download check, --offline specified');
                   41683:         }
                   41684: 
                   41685:         if (!count($params)) {
                   41686:             $a = array();
                   41687:             return $a;
                   41688:         }
                   41689: 
                   41690:         while (PEAR_Downloader_Package::mergeDependencies($params));
                   41691:         PEAR_Downloader_Package::removeDuplicates($params, true);
                   41692:         $errorparams = array();
                   41693:         if (PEAR_Downloader_Package::detectStupidDuplicates($params, $errorparams)) {
                   41694:             if (count($errorparams)) {
                   41695:                 foreach ($errorparams as $param) {
                   41696:                     $name = $this->_registry->parsedPackageNameToString($param->getParsedPackage());
                   41697:                     $this->pushError('Duplicate package ' . $name . ' found', PEAR_INSTALLER_FAILED);
                   41698:                 }
                   41699:                 $a = array();
                   41700:                 return $a;
                   41701:             }
                   41702:         }
                   41703: 
                   41704:         PEAR_Downloader_Package::removeInstalled($params);
                   41705:         if (!count($params)) {
                   41706:             $this->pushError('No valid packages found', PEAR_INSTALLER_FAILED);
                   41707:             $a = array();
                   41708:             return $a;
                   41709:         }
                   41710: 
                   41711:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   41712:         $err = $this->analyzeDependencies($params);
                   41713:         PEAR::popErrorHandling();
                   41714:         if (!count($params)) {
                   41715:             $this->pushError('No valid packages found', PEAR_INSTALLER_FAILED);
                   41716:             $a = array();
                   41717:             return $a;
                   41718:         }
                   41719: 
                   41720:         $ret = array();
                   41721:         $newparams = array();
                   41722:         if (isset($this->_options['pretend'])) {
                   41723:             return $params;
                   41724:         }
                   41725: 
                   41726:         $somefailed = false;
                   41727:         foreach ($params as $i => $package) {
                   41728:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   41729:             $pf = &$params[$i]->download();
                   41730:             PEAR::staticPopErrorHandling();
                   41731:             if (PEAR::isError($pf)) {
                   41732:                 if (!isset($this->_options['soft'])) {
                   41733:                     $this->log(1, $pf->getMessage());
                   41734:                     $this->log(0, 'Error: cannot download "' .
                   41735:                         $this->_registry->parsedPackageNameToString($package->getParsedPackage(),
                   41736:                             true) .
                   41737:                         '"');
                   41738:                 }
                   41739:                 $somefailed = true;
                   41740:                 continue;
                   41741:             }
                   41742: 
                   41743:             $newparams[] = &$params[$i];
                   41744:             $ret[] = array(
                   41745:                 'file' => $pf->getArchiveFile(),
                   41746:                 'info' => &$pf,
                   41747:                 'pkg'  => $pf->getPackage()
                   41748:             );
                   41749:         }
                   41750: 
                   41751:         if ($somefailed) {
                   41752:             // remove params that did not download successfully
                   41753:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   41754:             $err = $this->analyzeDependencies($newparams, true);
                   41755:             PEAR::popErrorHandling();
                   41756:             if (!count($newparams)) {
                   41757:                 $this->pushError('Download failed', PEAR_INSTALLER_FAILED);
                   41758:                 $a = array();
                   41759:                 return $a;
                   41760:             }
                   41761:         }
                   41762: 
                   41763:         $this->_downloadedPackages = $ret;
                   41764:         return $newparams;
                   41765:     }
                   41766: 
                   41767:     /**
                   41768:      * @param array all packages to be installed
                   41769:      */
                   41770:     function analyzeDependencies(&$params, $force = false)
                   41771:     {
                   41772:         if (isset($this->_options['downloadonly'])) {
                   41773:             return;
                   41774:         }
                   41775: 
                   41776:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   41777:         $redo  = true;
                   41778:         $reset = $hasfailed = $failed = false;
                   41779:         while ($redo) {
                   41780:             $redo = false;
                   41781:             foreach ($params as $i => $param) {
                   41782:                 $deps = $param->getDeps();
                   41783:                 if (!$deps) {
                   41784:                     $depchecker = &$this->getDependency2Object($this->config, $this->getOptions(),
                   41785:                         $param->getParsedPackage(), PEAR_VALIDATE_DOWNLOADING);
                   41786:                     $send = $param->getPackageFile();
                   41787: 
                   41788:                     $installcheck = $depchecker->validatePackage($send, $this, $params);
                   41789:                     if (PEAR::isError($installcheck)) {
                   41790:                         if (!isset($this->_options['soft'])) {
                   41791:                             $this->log(0, $installcheck->getMessage());
                   41792:                         }
                   41793:                         $hasfailed  = true;
                   41794:                         $params[$i] = false;
                   41795:                         $reset      = true;
                   41796:                         $redo       = true;
                   41797:                         $failed     = false;
                   41798:                         PEAR_Downloader_Package::removeDuplicates($params);
                   41799:                         continue 2;
                   41800:                     }
                   41801:                     continue;
                   41802:                 }
                   41803: 
                   41804:                 if (!$reset && $param->alreadyValidated() && !$force) {
                   41805:                     continue;
                   41806:                 }
                   41807: 
                   41808:                 if (count($deps)) {
                   41809:                     $depchecker = &$this->getDependency2Object($this->config, $this->getOptions(),
                   41810:                         $param->getParsedPackage(), PEAR_VALIDATE_DOWNLOADING);
                   41811:                     $send = $param->getPackageFile();
                   41812:                     if ($send === null) {
                   41813:                         $send = $param->getDownloadURL();
                   41814:                     }
                   41815: 
                   41816:                     $installcheck = $depchecker->validatePackage($send, $this, $params);
                   41817:                     if (PEAR::isError($installcheck)) {
                   41818:                         if (!isset($this->_options['soft'])) {
                   41819:                             $this->log(0, $installcheck->getMessage());
                   41820:                         }
                   41821:                         $hasfailed  = true;
                   41822:                         $params[$i] = false;
                   41823:                         $reset      = true;
                   41824:                         $redo       = true;
                   41825:                         $failed     = false;
                   41826:                         PEAR_Downloader_Package::removeDuplicates($params);
                   41827:                         continue 2;
                   41828:                     }
                   41829: 
                   41830:                     $failed = false;
                   41831:                     if (isset($deps['required']) && is_array($deps['required'])) {
                   41832:                         foreach ($deps['required'] as $type => $dep) {
                   41833:                             // note: Dependency2 will never return a PEAR_Error if ignore-errors
                   41834:                             // is specified, so soft is needed to turn off logging
                   41835:                             if (!isset($dep[0])) {
                   41836:                                 if (PEAR::isError($e = $depchecker->{"validate{$type}Dependency"}($dep,
                   41837:                                       true, $params))) {
                   41838:                                     $failed = true;
                   41839:                                     if (!isset($this->_options['soft'])) {
                   41840:                                         $this->log(0, $e->getMessage());
                   41841:                                     }
                   41842:                                 } elseif (is_array($e) && !$param->alreadyValidated()) {
                   41843:                                     if (!isset($this->_options['soft'])) {
                   41844:                                         $this->log(0, $e[0]);
                   41845:                                     }
                   41846:                                 }
                   41847:                             } else {
                   41848:                                 foreach ($dep as $d) {
                   41849:                                     if (PEAR::isError($e =
                   41850:                                           $depchecker->{"validate{$type}Dependency"}($d,
                   41851:                                           true, $params))) {
                   41852:                                         $failed = true;
                   41853:                                         if (!isset($this->_options['soft'])) {
                   41854:                                             $this->log(0, $e->getMessage());
                   41855:                                         }
                   41856:                                     } elseif (is_array($e) && !$param->alreadyValidated()) {
                   41857:                                         if (!isset($this->_options['soft'])) {
                   41858:                                             $this->log(0, $e[0]);
                   41859:                                         }
                   41860:                                     }
                   41861:                                 }
                   41862:                             }
                   41863:                         }
                   41864: 
                   41865:                         if (isset($deps['optional']) && is_array($deps['optional'])) {
                   41866:                             foreach ($deps['optional'] as $type => $dep) {
                   41867:                                 if (!isset($dep[0])) {
                   41868:                                     if (PEAR::isError($e =
                   41869:                                           $depchecker->{"validate{$type}Dependency"}($dep,
                   41870:                                           false, $params))) {
                   41871:                                         $failed = true;
                   41872:                                         if (!isset($this->_options['soft'])) {
                   41873:                                             $this->log(0, $e->getMessage());
                   41874:                                         }
                   41875:                                     } elseif (is_array($e) && !$param->alreadyValidated()) {
                   41876:                                         if (!isset($this->_options['soft'])) {
                   41877:                                             $this->log(0, $e[0]);
                   41878:                                         }
                   41879:                                     }
                   41880:                                 } else {
                   41881:                                     foreach ($dep as $d) {
                   41882:                                         if (PEAR::isError($e =
                   41883:                                               $depchecker->{"validate{$type}Dependency"}($d,
                   41884:                                               false, $params))) {
                   41885:                                             $failed = true;
                   41886:                                             if (!isset($this->_options['soft'])) {
                   41887:                                                 $this->log(0, $e->getMessage());
                   41888:                                             }
                   41889:                                         } elseif (is_array($e) && !$param->alreadyValidated()) {
                   41890:                                             if (!isset($this->_options['soft'])) {
                   41891:                                                 $this->log(0, $e[0]);
                   41892:                                             }
                   41893:                                         }
                   41894:                                     }
                   41895:                                 }
                   41896:                             }
                   41897:                         }
                   41898: 
                   41899:                         $groupname = $param->getGroup();
                   41900:                         if (isset($deps['group']) && $groupname) {
                   41901:                             if (!isset($deps['group'][0])) {
                   41902:                                 $deps['group'] = array($deps['group']);
                   41903:                             }
                   41904: 
                   41905:                             $found = false;
                   41906:                             foreach ($deps['group'] as $group) {
                   41907:                                 if ($group['attribs']['name'] == $groupname) {
                   41908:                                     $found = true;
                   41909:                                     break;
                   41910:                                 }
                   41911:                             }
                   41912: 
                   41913:                             if ($found) {
                   41914:                                 unset($group['attribs']);
                   41915:                                 foreach ($group as $type => $dep) {
                   41916:                                     if (!isset($dep[0])) {
                   41917:                                         if (PEAR::isError($e =
                   41918:                                               $depchecker->{"validate{$type}Dependency"}($dep,
                   41919:                                               false, $params))) {
                   41920:                                             $failed = true;
                   41921:                                             if (!isset($this->_options['soft'])) {
                   41922:                                                 $this->log(0, $e->getMessage());
                   41923:                                             }
                   41924:                                         } elseif (is_array($e) && !$param->alreadyValidated()) {
                   41925:                                             if (!isset($this->_options['soft'])) {
                   41926:                                                 $this->log(0, $e[0]);
                   41927:                                             }
                   41928:                                         }
                   41929:                                     } else {
                   41930:                                         foreach ($dep as $d) {
                   41931:                                             if (PEAR::isError($e =
                   41932:                                                   $depchecker->{"validate{$type}Dependency"}($d,
                   41933:                                                   false, $params))) {
                   41934:                                                 $failed = true;
                   41935:                                                 if (!isset($this->_options['soft'])) {
                   41936:                                                     $this->log(0, $e->getMessage());
                   41937:                                                 }
                   41938:                                             } elseif (is_array($e) && !$param->alreadyValidated()) {
                   41939:                                                 if (!isset($this->_options['soft'])) {
                   41940:                                                     $this->log(0, $e[0]);
                   41941:                                                 }
                   41942:                                             }
                   41943:                                         }
                   41944:                                     }
                   41945:                                 }
                   41946:                             }
                   41947:                         }
                   41948:                     } else {
                   41949:                         foreach ($deps as $dep) {
                   41950:                             if (PEAR::isError($e = $depchecker->validateDependency1($dep, $params))) {
                   41951:                                 $failed = true;
                   41952:                                 if (!isset($this->_options['soft'])) {
                   41953:                                     $this->log(0, $e->getMessage());
                   41954:                                 }
                   41955:                             } elseif (is_array($e) && !$param->alreadyValidated()) {
                   41956:                                 if (!isset($this->_options['soft'])) {
                   41957:                                     $this->log(0, $e[0]);
                   41958:                                 }
                   41959:                             }
                   41960:                         }
                   41961:                     }
                   41962:                     $params[$i]->setValidated();
                   41963:                 }
                   41964: 
                   41965:                 if ($failed) {
                   41966:                     $hasfailed  = true;
                   41967:                     $params[$i] = false;
                   41968:                     $reset      = true;
                   41969:                     $redo       = true;
                   41970:                     $failed     = false;
                   41971:                     PEAR_Downloader_Package::removeDuplicates($params);
                   41972:                     continue 2;
                   41973:                 }
                   41974:             }
                   41975:         }
                   41976: 
                   41977:         PEAR::staticPopErrorHandling();
                   41978:         if ($hasfailed && (isset($this->_options['ignore-errors']) ||
                   41979:               isset($this->_options['nodeps']))) {
                   41980:             // this is probably not needed, but just in case
                   41981:             if (!isset($this->_options['soft'])) {
                   41982:                 $this->log(0, 'WARNING: dependencies failed');
                   41983:             }
                   41984:         }
                   41985:     }
                   41986: 
                   41987:     /**
                   41988:      * Retrieve the directory that downloads will happen in
                   41989:      * @access private
                   41990:      * @return string
                   41991:      */
                   41992:     function getDownloadDir()
                   41993:     {
                   41994:         if (isset($this->_downloadDir)) {
                   41995:             return $this->_downloadDir;
                   41996:         }
                   41997: 
                   41998:         $downloaddir = $this->config->get('download_dir');
                   41999:         if (empty($downloaddir) || (is_dir($downloaddir) && !is_writable($downloaddir))) {
                   42000:             if  (is_dir($downloaddir) && !is_writable($downloaddir)) {
                   42001:                 $this->log(0, 'WARNING: configuration download directory "' . $downloaddir .
                   42002:                     '" is not writeable.  Change download_dir config variable to ' .
                   42003:                     'a writeable dir to avoid this warning');
                   42004:             }
                   42005: 
                   42006:             if (!class_exists('System')) {
                   42007:                 require_once 'System.php';
                   42008:             }
                   42009: 
                   42010:             if (PEAR::isError($downloaddir = System::mktemp('-d'))) {
                   42011:                 return $downloaddir;
                   42012:             }
                   42013:             $this->log(3, '+ tmp dir created at ' . $downloaddir);
                   42014:         }
                   42015: 
                   42016:         if (!is_writable($downloaddir)) {
                   42017:             if (PEAR::isError(System::mkdir(array('-p', $downloaddir))) ||
                   42018:                   !is_writable($downloaddir)) {
                   42019:                 return PEAR::raiseError('download directory "' . $downloaddir .
                   42020:                     '" is not writeable.  Change download_dir config variable to ' .
                   42021:                     'a writeable dir');
                   42022:             }
                   42023:         }
                   42024: 
                   42025:         return $this->_downloadDir = $downloaddir;
                   42026:     }
                   42027: 
                   42028:     function setDownloadDir($dir)
                   42029:     {
                   42030:         if (!@is_writable($dir)) {
                   42031:             if (PEAR::isError(System::mkdir(array('-p', $dir)))) {
                   42032:                 return PEAR::raiseError('download directory "' . $dir .
                   42033:                     '" is not writeable.  Change download_dir config variable to ' .
                   42034:                     'a writeable dir');
                   42035:             }
                   42036:         }
                   42037:         $this->_downloadDir = $dir;
                   42038:     }
                   42039: 
                   42040:     function configSet($key, $value, $layer = 'user', $channel = false)
                   42041:     {
                   42042:         $this->config->set($key, $value, $layer, $channel);
                   42043:         $this->_preferredState = $this->config->get('preferred_state', null, $channel);
                   42044:         if (!$this->_preferredState) {
                   42045:             // don't inadvertantly use a non-set preferred_state
                   42046:             $this->_preferredState = null;
                   42047:         }
                   42048:     }
                   42049: 
                   42050:     function setOptions($options)
                   42051:     {
                   42052:         $this->_options = $options;
                   42053:     }
                   42054: 
                   42055:     function getOptions()
                   42056:     {
                   42057:         return $this->_options;
                   42058:     }
                   42059: 
                   42060: 
                   42061:     /**
                   42062:      * @param array output of {@link parsePackageName()}
                   42063:      * @access private
                   42064:      */
                   42065:     function _getPackageDownloadUrl($parr)
                   42066:     {
                   42067:         $curchannel = $this->config->get('default_channel');
                   42068:         $this->configSet('default_channel', $parr['channel']);
                   42069:         // getDownloadURL returns an array.  On error, it only contains information
                   42070:         // on the latest release as array(version, info).  On success it contains
                   42071:         // array(version, info, download url string)
                   42072:         $state = isset($parr['state']) ? $parr['state'] : $this->config->get('preferred_state');
                   42073:         if (!$this->_registry->channelExists($parr['channel'])) {
                   42074:             do {
                   42075:                 if ($this->config->get('auto_discover') && $this->discover($parr['channel'])) {
                   42076:                     break;
                   42077:                 }
                   42078: 
                   42079:                 $this->configSet('default_channel', $curchannel);
                   42080:                 return PEAR::raiseError('Unknown remote channel: ' . $parr['channel']);
                   42081:             } while (false);
                   42082:         }
                   42083: 
                   42084:         $chan = &$this->_registry->getChannel($parr['channel']);
                   42085:         if (PEAR::isError($chan)) {
                   42086:             return $chan;
                   42087:         }
                   42088: 
                   42089:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   42090:         $version   = $this->_registry->packageInfo($parr['package'], 'version', $parr['channel']);
                   42091:         $stability = $this->_registry->packageInfo($parr['package'], 'stability', $parr['channel']);
                   42092:         // package is installed - use the installed release stability level
                   42093:         if (!isset($parr['state']) && $stability !== null) {
                   42094:             $state = $stability['release'];
                   42095:         }
                   42096:         PEAR::staticPopErrorHandling();
                   42097:         $base2 = false;
                   42098: 
                   42099:         $preferred_mirror = $this->config->get('preferred_mirror');
                   42100:         if (!$chan->supportsREST($preferred_mirror) ||
                   42101:               (
                   42102:                !($base2 = $chan->getBaseURL('REST1.3', $preferred_mirror))
                   42103:                &&
                   42104:                !($base = $chan->getBaseURL('REST1.0', $preferred_mirror))
                   42105:               )
                   42106:         ) {
                   42107:             return $this->raiseError($parr['channel'] . ' is using a unsupported protocol - This should never happen.');
                   42108:         }
                   42109: 
                   42110:         if ($base2) {
                   42111:             $rest = &$this->config->getREST('1.3', $this->_options);
                   42112:             $base = $base2;
                   42113:         } else {
                   42114:             $rest = &$this->config->getREST('1.0', $this->_options);
                   42115:         }
                   42116: 
                   42117:         $downloadVersion = false;
                   42118:         if (!isset($parr['version']) && !isset($parr['state']) && $version
                   42119:               && !PEAR::isError($version)
                   42120:               && !isset($this->_options['downloadonly'])
                   42121:         ) {
                   42122:             $downloadVersion = $version;
                   42123:         }
                   42124: 
                   42125:         $url = $rest->getDownloadURL($base, $parr, $state, $downloadVersion, $chan->getName());
                   42126:         if (PEAR::isError($url)) {
                   42127:             $this->configSet('default_channel', $curchannel);
                   42128:             return $url;
                   42129:         }
                   42130: 
                   42131:         if ($parr['channel'] != $curchannel) {
                   42132:             $this->configSet('default_channel', $curchannel);
                   42133:         }
                   42134: 
                   42135:         if (!is_array($url)) {
                   42136:             return $url;
                   42137:         }
                   42138: 
                   42139:         $url['raw'] = false; // no checking is necessary for REST
                   42140:         if (!is_array($url['info'])) {
                   42141:             return PEAR::raiseError('Invalid remote dependencies retrieved from REST - ' .
                   42142:                 'this should never happen');
                   42143:         }
                   42144: 
                   42145:         if (!isset($this->_options['force']) &&
                   42146:               !isset($this->_options['downloadonly']) &&
                   42147:               $version &&
                   42148:               !PEAR::isError($version) &&
                   42149:               !isset($parr['group'])
                   42150:         ) {
                   42151:             if (version_compare($version, $url['version'], '=')) {
                   42152:                 return PEAR::raiseError($this->_registry->parsedPackageNameToString(
                   42153:                     $parr, true) . ' is already installed and is the same as the ' .
                   42154:                     'released version ' . $url['version'], -976);
                   42155:             }
                   42156: 
                   42157:             if (version_compare($version, $url['version'], '>')) {
                   42158:                 return PEAR::raiseError($this->_registry->parsedPackageNameToString(
                   42159:                     $parr, true) . ' is already installed and is newer than detected ' .
                   42160:                     'released version ' . $url['version'], -976);
                   42161:             }
                   42162:         }
                   42163: 
                   42164:         if (isset($url['info']['required']) || $url['compatible']) {
                   42165:             require_once 'PEAR/PackageFile/v2.php';
                   42166:             $pf = new PEAR_PackageFile_v2;
                   42167:             $pf->setRawChannel($parr['channel']);
                   42168:             if ($url['compatible']) {
                   42169:                 $pf->setRawCompatible($url['compatible']);
                   42170:             }
                   42171:         } else {
                   42172:             require_once 'PEAR/PackageFile/v1.php';
                   42173:             $pf = new PEAR_PackageFile_v1;
                   42174:         }
                   42175: 
                   42176:         $pf->setRawPackage($url['package']);
                   42177:         $pf->setDeps($url['info']);
                   42178:         if ($url['compatible']) {
                   42179:             $pf->setCompatible($url['compatible']);
                   42180:         }
                   42181: 
                   42182:         $pf->setRawState($url['stability']);
                   42183:         $url['info'] = &$pf;
                   42184:         if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) {
                   42185:             $ext = '.tar';
                   42186:         } else {
                   42187:             $ext = '.tgz';
                   42188:         }
                   42189: 
                   42190:         if (is_array($url) && isset($url['url'])) {
                   42191:             $url['url'] .= $ext;
                   42192:         }
                   42193: 
                   42194:         return $url;
                   42195:     }
                   42196: 
                   42197:     /**
                   42198:      * @param array dependency array
                   42199:      * @access private
                   42200:      */
                   42201:     function _getDepPackageDownloadUrl($dep, $parr)
                   42202:     {
                   42203:         $xsdversion = isset($dep['rel']) ? '1.0' : '2.0';
                   42204:         $curchannel = $this->config->get('default_channel');
                   42205:         if (isset($dep['uri'])) {
                   42206:             $xsdversion = '2.0';
                   42207:             $chan = &$this->_registry->getChannel('__uri');
                   42208:             if (PEAR::isError($chan)) {
                   42209:                 return $chan;
                   42210:             }
                   42211: 
                   42212:             $version = $this->_registry->packageInfo($dep['name'], 'version', '__uri');
                   42213:             $this->configSet('default_channel', '__uri');
                   42214:         } else {
                   42215:             if (isset($dep['channel'])) {
                   42216:                 $remotechannel = $dep['channel'];
                   42217:             } else {
                   42218:                 $remotechannel = 'pear.php.net';
                   42219:             }
                   42220: 
                   42221:             if (!$this->_registry->channelExists($remotechannel)) {
                   42222:                 do {
                   42223:                     if ($this->config->get('auto_discover')) {
                   42224:                         if ($this->discover($remotechannel)) {
                   42225:                             break;
                   42226:                         }
                   42227:                     }
                   42228:                     return PEAR::raiseError('Unknown remote channel: ' . $remotechannel);
                   42229:                 } while (false);
                   42230:             }
                   42231: 
                   42232:             $chan = &$this->_registry->getChannel($remotechannel);
                   42233:             if (PEAR::isError($chan)) {
                   42234:                 return $chan;
                   42235:             }
                   42236: 
                   42237:             $version = $this->_registry->packageInfo($dep['name'], 'version', $remotechannel);
                   42238:             $this->configSet('default_channel', $remotechannel);
                   42239:         }
                   42240: 
                   42241:         $state = isset($parr['state']) ? $parr['state'] : $this->config->get('preferred_state');
                   42242:         if (isset($parr['state']) && isset($parr['version'])) {
                   42243:             unset($parr['state']);
                   42244:         }
                   42245: 
                   42246:         if (isset($dep['uri'])) {
                   42247:             $info = &$this->newDownloaderPackage($this);
                   42248:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   42249:             $err = $info->initialize($dep);
                   42250:             PEAR::staticPopErrorHandling();
                   42251:             if (!$err) {
                   42252:                 // skip parameters that were missed by preferred_state
                   42253:                 return PEAR::raiseError('Cannot initialize dependency');
                   42254:             }
                   42255: 
                   42256:             if (PEAR::isError($err)) {
                   42257:                 if (!isset($this->_options['soft'])) {
                   42258:                     $this->log(0, $err->getMessage());
                   42259:                 }
                   42260: 
                   42261:                 if (is_object($info)) {
                   42262:                     $param = $info->getChannel() . '/' . $info->getPackage();
                   42263:                 }
                   42264:                 return PEAR::raiseError('Package "' . $param . '" is not valid');
                   42265:             }
                   42266:             return $info;
                   42267:         } elseif ($chan->supportsREST($this->config->get('preferred_mirror'))
                   42268:               &&
                   42269:                 (
                   42270:                   ($base2 = $chan->getBaseURL('REST1.3', $this->config->get('preferred_mirror')))
                   42271:                     ||
                   42272:                   ($base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror')))
                   42273:                 )
                   42274:         ) {
                   42275:             if ($base2) {
                   42276:                 $base = $base2;
                   42277:                 $rest = &$this->config->getREST('1.3', $this->_options);
                   42278:             } else {
                   42279:                 $rest = &$this->config->getREST('1.0', $this->_options);
                   42280:             }
                   42281: 
                   42282:             $url = $rest->getDepDownloadURL($base, $xsdversion, $dep, $parr,
                   42283:                     $state, $version, $chan->getName());
                   42284:             if (PEAR::isError($url)) {
                   42285:                 return $url;
                   42286:             }
                   42287: 
                   42288:             if ($parr['channel'] != $curchannel) {
                   42289:                 $this->configSet('default_channel', $curchannel);
                   42290:             }
                   42291: 
                   42292:             if (!is_array($url)) {
                   42293:                 return $url;
                   42294:             }
                   42295: 
                   42296:             $url['raw'] = false; // no checking is necessary for REST
                   42297:             if (!is_array($url['info'])) {
                   42298:                 return PEAR::raiseError('Invalid remote dependencies retrieved from REST - ' .
                   42299:                     'this should never happen');
                   42300:             }
                   42301: 
                   42302:             if (isset($url['info']['required'])) {
                   42303:                 if (!class_exists('PEAR_PackageFile_v2')) {
                   42304:                     require_once 'PEAR/PackageFile/v2.php';
                   42305:                 }
                   42306:                 $pf = new PEAR_PackageFile_v2;
                   42307:                 $pf->setRawChannel($remotechannel);
                   42308:             } else {
                   42309:                 if (!class_exists('PEAR_PackageFile_v1')) {
                   42310:                     require_once 'PEAR/PackageFile/v1.php';
                   42311:                 }
                   42312:                 $pf = new PEAR_PackageFile_v1;
                   42313: 
                   42314:             }
                   42315:             $pf->setRawPackage($url['package']);
                   42316:             $pf->setDeps($url['info']);
                   42317:             if ($url['compatible']) {
                   42318:                 $pf->setCompatible($url['compatible']);
                   42319:             }
                   42320: 
                   42321:             $pf->setRawState($url['stability']);
                   42322:             $url['info'] = &$pf;
                   42323:             if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) {
                   42324:                 $ext = '.tar';
                   42325:             } else {
                   42326:                 $ext = '.tgz';
                   42327:             }
                   42328: 
                   42329:             if (is_array($url) && isset($url['url'])) {
                   42330:                 $url['url'] .= $ext;
                   42331:             }
                   42332: 
                   42333:             return $url;
                   42334:         }
                   42335: 
                   42336:         return $this->raiseError($parr['channel'] . ' is using a unsupported protocol - This should never happen.');
                   42337:     }
                   42338: 
                   42339:     /**
                   42340:      * @deprecated in favor of _getPackageDownloadUrl
                   42341:      */
                   42342:     function getPackageDownloadUrl($package, $version = null, $channel = false)
                   42343:     {
                   42344:         if ($version) {
                   42345:             $package .= "-$version";
                   42346:         }
                   42347:         if ($this === null || $this->_registry === null) {
                   42348:             $package = "http://pear.php.net/get/$package";
                   42349:         } else {
                   42350:             $chan = $this->_registry->getChannel($channel);
                   42351:             if (PEAR::isError($chan)) {
                   42352:                 return '';
                   42353:             }
                   42354:             $package = "http://" . $chan->getServer() . "/get/$package";
                   42355:         }
                   42356:         if (!extension_loaded("zlib")) {
                   42357:             $package .= '?uncompress=yes';
                   42358:         }
                   42359:         return $package;
                   42360:     }
                   42361: 
                   42362:     /**
                   42363:      * Retrieve a list of downloaded packages after a call to {@link download()}.
                   42364:      *
                   42365:      * Also resets the list of downloaded packages.
                   42366:      * @return array
                   42367:      */
                   42368:     function getDownloadedPackages()
                   42369:     {
                   42370:         $ret = $this->_downloadedPackages;
                   42371:         $this->_downloadedPackages = array();
                   42372:         $this->_toDownload = array();
                   42373:         return $ret;
                   42374:     }
                   42375: 
                   42376:     function _downloadCallback($msg, $params = null)
                   42377:     {
                   42378:         switch ($msg) {
                   42379:             case 'saveas':
                   42380:                 $this->log(1, "downloading $params ...");
                   42381:                 break;
                   42382:             case 'done':
                   42383:                 $this->log(1, '...done: ' . number_format($params, 0, '', ',') . ' bytes');
                   42384:                 break;
                   42385:             case 'bytesread':
                   42386:                 static $bytes;
                   42387:                 if (empty($bytes)) {
                   42388:                     $bytes = 0;
                   42389:                 }
                   42390:                 if (!($bytes % 10240)) {
                   42391:                     $this->log(1, '.', false);
                   42392:                 }
                   42393:                 $bytes += $params;
                   42394:                 break;
                   42395:             case 'start':
                   42396:                 if($params[1] == -1) {
                   42397:                     $length = "Unknown size";
                   42398:                 } else {
                   42399:                     $length = number_format($params[1], 0, '', ',')." bytes";
                   42400:                 }
                   42401:                 $this->log(1, "Starting to download {$params[0]} ($length)");
                   42402:                 break;
                   42403:         }
                   42404:         if (method_exists($this->ui, '_downloadCallback'))
                   42405:             $this->ui->_downloadCallback($msg, $params);
                   42406:     }
                   42407: 
                   42408:     function _prependPath($path, $prepend)
                   42409:     {
                   42410:         if (strlen($prepend) > 0) {
                   42411:             if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) {
                   42412:                 if (preg_match('/^[a-z]:/i', $prepend)) {
                   42413:                     $prepend = substr($prepend, 2);
                   42414:                 } elseif ($prepend{0} != '\\') {
                   42415:                     $prepend = "\\$prepend";
                   42416:                 }
                   42417:                 $path = substr($path, 0, 2) . $prepend . substr($path, 2);
                   42418:             } else {
                   42419:                 $path = $prepend . $path;
                   42420:             }
                   42421:         }
                   42422:         return $path;
                   42423:     }
                   42424: 
                   42425:     /**
                   42426:      * @param string
                   42427:      * @param integer
                   42428:      */
                   42429:     function pushError($errmsg, $code = -1)
                   42430:     {
                   42431:         array_push($this->_errorStack, array($errmsg, $code));
                   42432:     }
                   42433: 
                   42434:     function getErrorMsgs()
                   42435:     {
                   42436:         $msgs = array();
                   42437:         $errs = $this->_errorStack;
                   42438:         foreach ($errs as $err) {
                   42439:             $msgs[] = $err[0];
                   42440:         }
                   42441:         $this->_errorStack = array();
                   42442:         return $msgs;
                   42443:     }
                   42444: 
                   42445:     /**
                   42446:      * for BC
                   42447:      *
                   42448:      * @deprecated
                   42449:      */
                   42450:     function sortPkgDeps(&$packages, $uninstall = false)
                   42451:     {
                   42452:         $uninstall ?
                   42453:             $this->sortPackagesForUninstall($packages) :
                   42454:             $this->sortPackagesForInstall($packages);
                   42455:     }
                   42456: 
                   42457:     /**
                   42458:      * Sort a list of arrays of array(downloaded packagefilename) by dependency.
                   42459:      *
                   42460:      * This uses the topological sort method from graph theory, and the
                   42461:      * Structures_Graph package to properly sort dependencies for installation.
                   42462:      * @param array an array of downloaded PEAR_Downloader_Packages
                   42463:      * @return array array of array(packagefilename, package.xml contents)
                   42464:      */
                   42465:     function sortPackagesForInstall(&$packages)
                   42466:     {
                   42467:         require_once 'Structures/Graph.php';
                   42468:         require_once 'Structures/Graph/Node.php';
                   42469:         require_once 'Structures/Graph/Manipulator/TopologicalSorter.php';
                   42470:         $depgraph = new Structures_Graph(true);
                   42471:         $nodes = array();
                   42472:         $reg = &$this->config->getRegistry();
                   42473:         foreach ($packages as $i => $package) {
                   42474:             $pname = $reg->parsedPackageNameToString(
                   42475:                 array(
                   42476:                     'channel' => $package->getChannel(),
                   42477:                     'package' => strtolower($package->getPackage()),
                   42478:                 ));
                   42479:             $nodes[$pname] = new Structures_Graph_Node;
                   42480:             $nodes[$pname]->setData($packages[$i]);
                   42481:             $depgraph->addNode($nodes[$pname]);
                   42482:         }
                   42483: 
                   42484:         $deplinks = array();
                   42485:         foreach ($nodes as $package => $node) {
                   42486:             $pf = &$node->getData();
                   42487:             $pdeps = $pf->getDeps(true);
                   42488:             if (!$pdeps) {
                   42489:                 continue;
                   42490:             }
                   42491: 
                   42492:             if ($pf->getPackagexmlVersion() == '1.0') {
                   42493:                 foreach ($pdeps as $dep) {
                   42494:                     if ($dep['type'] != 'pkg' ||
                   42495:                           (isset($dep['optional']) && $dep['optional'] == 'yes')) {
                   42496:                         continue;
                   42497:                     }
                   42498: 
                   42499:                     $dname = $reg->parsedPackageNameToString(
                   42500:                           array(
                   42501:                               'channel' => 'pear.php.net',
                   42502:                               'package' => strtolower($dep['name']),
                   42503:                           ));
                   42504: 
                   42505:                     if (isset($nodes[$dname])) {
                   42506:                         if (!isset($deplinks[$dname])) {
                   42507:                             $deplinks[$dname] = array();
                   42508:                         }
                   42509: 
                   42510:                         $deplinks[$dname][$package] = 1;
                   42511:                         // dependency is in installed packages
                   42512:                         continue;
                   42513:                     }
                   42514: 
                   42515:                     $dname = $reg->parsedPackageNameToString(
                   42516:                           array(
                   42517:                               'channel' => 'pecl.php.net',
                   42518:                               'package' => strtolower($dep['name']),
                   42519:                           ));
                   42520: 
                   42521:                     if (isset($nodes[$dname])) {
                   42522:                         if (!isset($deplinks[$dname])) {
                   42523:                             $deplinks[$dname] = array();
                   42524:                         }
                   42525: 
                   42526:                         $deplinks[$dname][$package] = 1;
                   42527:                         // dependency is in installed packages
                   42528:                         continue;
                   42529:                     }
                   42530:                 }
                   42531:             } else {
                   42532:                 // the only ordering we care about is:
                   42533:                 // 1) subpackages must be installed before packages that depend on them
                   42534:                 // 2) required deps must be installed before packages that depend on them
                   42535:                 if (isset($pdeps['required']['subpackage'])) {
                   42536:                     $t = $pdeps['required']['subpackage'];
                   42537:                     if (!isset($t[0])) {
                   42538:                         $t = array($t);
                   42539:                     }
                   42540: 
                   42541:                     $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
                   42542:                 }
                   42543: 
                   42544:                 if (isset($pdeps['group'])) {
                   42545:                     if (!isset($pdeps['group'][0])) {
                   42546:                         $pdeps['group'] = array($pdeps['group']);
                   42547:                     }
                   42548: 
                   42549:                     foreach ($pdeps['group'] as $group) {
                   42550:                         if (isset($group['subpackage'])) {
                   42551:                             $t = $group['subpackage'];
                   42552:                             if (!isset($t[0])) {
                   42553:                                 $t = array($t);
                   42554:                             }
                   42555: 
                   42556:                             $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
                   42557:                         }
                   42558:                     }
                   42559:                 }
                   42560: 
                   42561:                 if (isset($pdeps['optional']['subpackage'])) {
                   42562:                     $t = $pdeps['optional']['subpackage'];
                   42563:                     if (!isset($t[0])) {
                   42564:                         $t = array($t);
                   42565:                     }
                   42566: 
                   42567:                     $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
                   42568:                 }
                   42569: 
                   42570:                 if (isset($pdeps['required']['package'])) {
                   42571:                     $t = $pdeps['required']['package'];
                   42572:                     if (!isset($t[0])) {
                   42573:                         $t = array($t);
                   42574:                     }
                   42575: 
                   42576:                     $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
                   42577:                 }
                   42578: 
                   42579:                 if (isset($pdeps['group'])) {
                   42580:                     if (!isset($pdeps['group'][0])) {
                   42581:                         $pdeps['group'] = array($pdeps['group']);
                   42582:                     }
                   42583: 
                   42584:                     foreach ($pdeps['group'] as $group) {
                   42585:                         if (isset($group['package'])) {
                   42586:                             $t = $group['package'];
                   42587:                             if (!isset($t[0])) {
                   42588:                                 $t = array($t);
                   42589:                             }
                   42590: 
                   42591:                             $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
                   42592:                         }
                   42593:                     }
                   42594:                 }
                   42595:             }
                   42596:         }
                   42597: 
                   42598:         $this->_detectDepCycle($deplinks);
                   42599:         foreach ($deplinks as $dependent => $parents) {
                   42600:             foreach ($parents as $parent => $unused) {
                   42601:                 $nodes[$dependent]->connectTo($nodes[$parent]);
                   42602:             }
                   42603:         }
                   42604: 
                   42605:         $installOrder = Structures_Graph_Manipulator_TopologicalSorter::sort($depgraph);
                   42606:         $ret = array();
                   42607:         for ($i = 0, $count = count($installOrder); $i < $count; $i++) {
                   42608:             foreach ($installOrder[$i] as $index => $sortedpackage) {
                   42609:                 $data = &$installOrder[$i][$index]->getData();
                   42610:                 $ret[] = &$nodes[$reg->parsedPackageNameToString(
                   42611:                           array(
                   42612:                               'channel' => $data->getChannel(),
                   42613:                               'package' => strtolower($data->getPackage()),
                   42614:                           ))]->getData();
                   42615:             }
                   42616:         }
                   42617: 
                   42618:         $packages = $ret;
                   42619:         return;
                   42620:     }
                   42621: 
                   42622:     /**
                   42623:      * Detect recursive links between dependencies and break the cycles
                   42624:      *
                   42625:      * @param array
                   42626:      * @access private
                   42627:      */
                   42628:     function _detectDepCycle(&$deplinks)
                   42629:     {
                   42630:         do {
                   42631:             $keepgoing = false;
                   42632:             foreach ($deplinks as $dep => $parents) {
                   42633:                 foreach ($parents as $parent => $unused) {
                   42634:                     // reset the parent cycle detector
                   42635:                     $this->_testCycle(null, null, null);
                   42636:                     if ($this->_testCycle($dep, $deplinks, $parent)) {
                   42637:                         $keepgoing = true;
                   42638:                         unset($deplinks[$dep][$parent]);
                   42639:                         if (count($deplinks[$dep]) == 0) {
                   42640:                             unset($deplinks[$dep]);
                   42641:                         }
                   42642: 
                   42643:                         continue 3;
                   42644:                     }
                   42645:                 }
                   42646:             }
                   42647:         } while ($keepgoing);
                   42648:     }
                   42649: 
                   42650:     function _testCycle($test, $deplinks, $dep)
                   42651:     {
                   42652:         static $visited = array();
                   42653:         if ($test === null) {
                   42654:             $visited = array();
                   42655:             return;
                   42656:         }
                   42657: 
                   42658:         // this happens when a parent has a dep cycle on another dependency
                   42659:         // but the child is not part of the cycle
                   42660:         if (isset($visited[$dep])) {
                   42661:             return false;
                   42662:         }
                   42663: 
                   42664:         $visited[$dep] = 1;
                   42665:         if ($test == $dep) {
                   42666:             return true;
                   42667:         }
                   42668: 
                   42669:         if (isset($deplinks[$dep])) {
                   42670:             if (in_array($test, array_keys($deplinks[$dep]), true)) {
                   42671:                 return true;
                   42672:             }
                   42673: 
                   42674:             foreach ($deplinks[$dep] as $parent => $unused) {
                   42675:                 if ($this->_testCycle($test, $deplinks, $parent)) {
                   42676:                     return true;
                   42677:                 }
                   42678:             }
                   42679:         }
                   42680: 
                   42681:         return false;
                   42682:     }
                   42683: 
                   42684:     /**
                   42685:      * Set up the dependency for installation parsing
                   42686:      *
                   42687:      * @param array $t dependency information
                   42688:      * @param PEAR_Registry $reg
                   42689:      * @param array $deplinks list of dependency links already established
                   42690:      * @param array $nodes all existing package nodes
                   42691:      * @param string $package parent package name
                   42692:      * @access private
                   42693:      */
                   42694:     function _setupGraph($t, $reg, &$deplinks, &$nodes, $package)
                   42695:     {
                   42696:         foreach ($t as $dep) {
                   42697:             $depchannel = !isset($dep['channel']) ? '__uri': $dep['channel'];
                   42698:             $dname = $reg->parsedPackageNameToString(
                   42699:                   array(
                   42700:                       'channel' => $depchannel,
                   42701:                       'package' => strtolower($dep['name']),
                   42702:                   ));
                   42703: 
                   42704:             if (isset($nodes[$dname])) {
                   42705:                 if (!isset($deplinks[$dname])) {
                   42706:                     $deplinks[$dname] = array();
                   42707:                 }
                   42708:                 $deplinks[$dname][$package] = 1;
                   42709:             }
                   42710:         }
                   42711:     }
                   42712: 
                   42713:     function _dependsOn($a, $b)
                   42714:     {
                   42715:         return $this->_checkDepTree(strtolower($a->getChannel()), strtolower($a->getPackage()), $b);
                   42716:     }
                   42717: 
                   42718:     function _checkDepTree($channel, $package, $b, $checked = array())
                   42719:     {
                   42720:         $checked[$channel][$package] = true;
                   42721:         if (!isset($this->_depTree[$channel][$package])) {
                   42722:             return false;
                   42723:         }
                   42724: 
                   42725:         if (isset($this->_depTree[$channel][$package][strtolower($b->getChannel())]
                   42726:               [strtolower($b->getPackage())])) {
                   42727:             return true;
                   42728:         }
                   42729: 
                   42730:         foreach ($this->_depTree[$channel][$package] as $ch => $packages) {
                   42731:             foreach ($packages as $pa => $true) {
                   42732:                 if ($this->_checkDepTree($ch, $pa, $b, $checked)) {
                   42733:                     return true;
                   42734:                 }
                   42735:             }
                   42736:         }
                   42737: 
                   42738:         return false;
                   42739:     }
                   42740: 
                   42741:     function _sortInstall($a, $b)
                   42742:     {
                   42743:         if (!$a->getDeps() && !$b->getDeps()) {
                   42744:             return 0; // neither package has dependencies, order is insignificant
                   42745:         }
                   42746:         if ($a->getDeps() && !$b->getDeps()) {
                   42747:             return 1; // $a must be installed after $b because $a has dependencies
                   42748:         }
                   42749:         if (!$a->getDeps() && $b->getDeps()) {
                   42750:             return -1; // $b must be installed after $a because $b has dependencies
                   42751:         }
                   42752:         // both packages have dependencies
                   42753:         if ($this->_dependsOn($a, $b)) {
                   42754:             return 1;
                   42755:         }
                   42756:         if ($this->_dependsOn($b, $a)) {
                   42757:             return -1;
                   42758:         }
                   42759:         return 0;
                   42760:     }
                   42761: 
                   42762:     /**
                   42763:      * Download a file through HTTP.  Considers suggested file name in
                   42764:      * Content-disposition: header and can run a callback function for
                   42765:      * different events.  The callback will be called with two
                   42766:      * parameters: the callback type, and parameters.  The implemented
                   42767:      * callback types are:
                   42768:      *
                   42769:      *  'setup'       called at the very beginning, parameter is a UI object
                   42770:      *                that should be used for all output
                   42771:      *  'message'     the parameter is a string with an informational message
                   42772:      *  'saveas'      may be used to save with a different file name, the
                   42773:      *                parameter is the filename that is about to be used.
                   42774:      *                If a 'saveas' callback returns a non-empty string,
                   42775:      *                that file name will be used as the filename instead.
                   42776:      *                Note that $save_dir will not be affected by this, only
                   42777:      *                the basename of the file.
                   42778:      *  'start'       download is starting, parameter is number of bytes
                   42779:      *                that are expected, or -1 if unknown
                   42780:      *  'bytesread'   parameter is the number of bytes read so far
                   42781:      *  'done'        download is complete, parameter is the total number
                   42782:      *                of bytes read
                   42783:      *  'connfailed'  if the TCP/SSL connection fails, this callback is called
                   42784:      *                with array(host,port,errno,errmsg)
                   42785:      *  'writefailed' if writing to disk fails, this callback is called
                   42786:      *                with array(destfile,errmsg)
                   42787:      *
                   42788:      * If an HTTP proxy has been configured (http_proxy PEAR_Config
                   42789:      * setting), the proxy will be used.
                   42790:      *
                   42791:      * @param string  $url       the URL to download
                   42792:      * @param object  $ui        PEAR_Frontend_* instance
                   42793:      * @param object  $config    PEAR_Config instance
                   42794:      * @param string  $save_dir  directory to save file in
                   42795:      * @param mixed   $callback  function/method to call for status
                   42796:      *                           updates
                   42797:      * @param false|string|array $lastmodified header values to check against for caching
                   42798:      *                           use false to return the header values from this download
                   42799:      * @param false|array $accept Accept headers to send
                   42800:      * @param false|string $channel Channel to use for retrieving authentication
                   42801:      * @return string|array  Returns the full path of the downloaded file or a PEAR
                   42802:      *                       error on failure.  If the error is caused by
                   42803:      *                       socket-related errors, the error object will
                   42804:      *                       have the fsockopen error code available through
                   42805:      *                       getCode().  If caching is requested, then return the header
                   42806:      *                       values.
                   42807:      *
                   42808:      * @access public
                   42809:      */
                   42810:     function downloadHttp($url, &$ui, $save_dir = '.', $callback = null, $lastmodified = null,
                   42811:                           $accept = false, $channel = false)
                   42812:     {
                   42813:         static $redirect = 0;
                   42814:         // always reset , so we are clean case of error
                   42815:         $wasredirect = $redirect;
                   42816:         $redirect = 0;
                   42817:         if ($callback) {
                   42818:             call_user_func($callback, 'setup', array(&$ui));
                   42819:         }
                   42820: 
                   42821:         $info = parse_url($url);
                   42822:         if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) {
                   42823:             return PEAR::raiseError('Cannot download non-http URL "' . $url . '"');
                   42824:         }
                   42825: 
                   42826:         if (!isset($info['host'])) {
                   42827:             return PEAR::raiseError('Cannot download from non-URL "' . $url . '"');
                   42828:         }
                   42829: 
                   42830:         $host = isset($info['host']) ? $info['host'] : null;
                   42831:         $port = isset($info['port']) ? $info['port'] : null;
                   42832:         $path = isset($info['path']) ? $info['path'] : null;
                   42833: 
                   42834:         if (isset($this)) {
                   42835:             $config = &$this->config;
                   42836:         } else {
                   42837:             $config = &PEAR_Config::singleton();
                   42838:         }
                   42839: 
                   42840:         $proxy_host = $proxy_port = $proxy_user = $proxy_pass = '';
                   42841:         if ($config->get('http_proxy') &&
                   42842:               $proxy = parse_url($config->get('http_proxy'))) {
                   42843:             $proxy_host = isset($proxy['host']) ? $proxy['host'] : null;
                   42844:             if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') {
                   42845:                 $proxy_host = 'ssl://' . $proxy_host;
                   42846:             }
                   42847:             $proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080;
                   42848:             $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null;
                   42849:             $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null;
                   42850: 
                   42851:             if ($callback) {
                   42852:                 call_user_func($callback, 'message', "Using HTTP proxy $host:$port");
                   42853:             }
                   42854:         }
                   42855: 
                   42856:         if (empty($port)) {
                   42857:             $port = (isset($info['scheme']) && $info['scheme'] == 'https') ? 443 : 80;
                   42858:         }
                   42859: 
                   42860:         $scheme = (isset($info['scheme']) && $info['scheme'] == 'https') ? 'https' : 'http';
                   42861: 
                   42862:         if ($proxy_host != '') {
                   42863:             $fp = @fsockopen($proxy_host, $proxy_port, $errno, $errstr);
                   42864:             if (!$fp) {
                   42865:                 if ($callback) {
                   42866:                     call_user_func($callback, 'connfailed', array($proxy_host, $proxy_port,
                   42867:                                                                   $errno, $errstr));
                   42868:                 }
                   42869:                 return PEAR::raiseError("Connection to `$proxy_host:$proxy_port' failed: $errstr", $errno);
                   42870:             }
                   42871: 
                   42872:             if ($lastmodified === false || $lastmodified) {
                   42873:                 $request  = "GET $url HTTP/1.1\r\n";
                   42874:                 $request .= "Host: $host\r\n";
                   42875:             } else {
                   42876:                 $request  = "GET $url HTTP/1.0\r\n";
                   42877:                 $request .= "Host: $host\r\n";
                   42878:             }
                   42879:         } else {
                   42880:             $network_host = $host;
                   42881:             if (isset($info['scheme']) && $info['scheme'] == 'https') {
                   42882:                 $network_host = 'ssl://' . $host;
                   42883:             }
                   42884: 
                   42885:             $fp = @fsockopen($network_host, $port, $errno, $errstr);
                   42886:             if (!$fp) {
                   42887:                 if ($callback) {
                   42888:                     call_user_func($callback, 'connfailed', array($host, $port,
                   42889:                                                                   $errno, $errstr));
                   42890:                 }
                   42891:                 return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno);
                   42892:             }
                   42893: 
                   42894:             if ($lastmodified === false || $lastmodified) {
                   42895:                 $request = "GET $path HTTP/1.1\r\n";
                   42896:                 $request .= "Host: $host\r\n";
                   42897:             } else {
                   42898:                 $request = "GET $path HTTP/1.0\r\n";
                   42899:                 $request .= "Host: $host\r\n";
                   42900:             }
                   42901:         }
                   42902: 
                   42903:         $ifmodifiedsince = '';
                   42904:         if (is_array($lastmodified)) {
                   42905:             if (isset($lastmodified['Last-Modified'])) {
                   42906:                 $ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n";
                   42907:             }
                   42908: 
                   42909:             if (isset($lastmodified['ETag'])) {
                   42910:                 $ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n";
                   42911:             }
                   42912:         } else {
                   42913:             $ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : '');
                   42914:         }
                   42915: 
                   42916:         $request .= $ifmodifiedsince .
                   42917:             "User-Agent: PEAR/1.9.4/PHP/" . PHP_VERSION . "\r\n";
                   42918: 
                   42919:         if (isset($this)) { // only pass in authentication for non-static calls
                   42920:             $username = $config->get('username', null, $channel);
                   42921:             $password = $config->get('password', null, $channel);
                   42922:             if ($username && $password) {
                   42923:                 $tmp = base64_encode("$username:$password");
                   42924:                 $request .= "Authorization: Basic $tmp\r\n";
                   42925:             }
                   42926:         }
                   42927: 
                   42928:         if ($proxy_host != '' && $proxy_user != '') {
                   42929:             $request .= 'Proxy-Authorization: Basic ' .
                   42930:                 base64_encode($proxy_user . ':' . $proxy_pass) . "\r\n";
                   42931:         }
                   42932: 
                   42933:         if ($accept) {
                   42934:             $request .= 'Accept: ' . implode(', ', $accept) . "\r\n";
                   42935:         }
                   42936: 
                   42937:         $request .= "Connection: close\r\n";
                   42938:         $request .= "\r\n";
                   42939:         fwrite($fp, $request);
                   42940:         $headers = array();
                   42941:         $reply = 0;
                   42942:         while (trim($line = fgets($fp, 1024))) {
                   42943:             if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) {
                   42944:                 $headers[strtolower($matches[1])] = trim($matches[2]);
                   42945:             } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) {
                   42946:                 $reply = (int)$matches[1];
                   42947:                 if ($reply == 304 && ($lastmodified || ($lastmodified === false))) {
                   42948:                     return false;
                   42949:                 }
                   42950: 
                   42951:                 if (!in_array($reply, array(200, 301, 302, 303, 305, 307))) {
                   42952:                     return PEAR::raiseError("File $scheme://$host:$port$path not valid (received: $line)");
                   42953:                 }
                   42954:             }
                   42955:         }
                   42956: 
                   42957:         if ($reply != 200) {
                   42958:             if (!isset($headers['location'])) {
                   42959:                 return PEAR::raiseError("File $scheme://$host:$port$path not valid (redirected but no location)");
                   42960:             }
                   42961: 
                   42962:             if ($wasredirect > 4) {
                   42963:                 return PEAR::raiseError("File $scheme://$host:$port$path not valid (redirection looped more than 5 times)");
                   42964:             }
                   42965: 
                   42966:             $redirect = $wasredirect + 1;
                   42967:             return $this->downloadHttp($headers['location'],
                   42968:                     $ui, $save_dir, $callback, $lastmodified, $accept);
                   42969:         }
                   42970: 
                   42971:         if (isset($headers['content-disposition']) &&
                   42972:             preg_match('/\sfilename=\"([^;]*\S)\"\s*(;|\\z)/', $headers['content-disposition'], $matches)) {
                   42973:             $save_as = basename($matches[1]);
                   42974:         } else {
                   42975:             $save_as = basename($url);
                   42976:         }
                   42977: 
                   42978:         if ($callback) {
                   42979:             $tmp = call_user_func($callback, 'saveas', $save_as);
                   42980:             if ($tmp) {
                   42981:                 $save_as = $tmp;
                   42982:             }
                   42983:         }
                   42984: 
                   42985:         $dest_file = $save_dir . DIRECTORY_SEPARATOR . $save_as;
                   42986:         if (is_link($dest_file)) {
                   42987:             return PEAR::raiseError('SECURITY ERROR: Will not write to ' . $dest_file . ' as it is symlinked to ' . readlink($dest_file) . ' - Possible symlink attack');
                   42988:         }
                   42989: 
                   42990:         if (!$wp = @fopen($dest_file, 'wb')) {
                   42991:             fclose($fp);
                   42992:             if ($callback) {
                   42993:                 call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg));
                   42994:             }
                   42995:             return PEAR::raiseError("could not open $dest_file for writing");
                   42996:         }
                   42997: 
                   42998:         $length = isset($headers['content-length']) ? $headers['content-length'] : -1;
                   42999: 
                   43000:         $bytes = 0;
                   43001:         if ($callback) {
                   43002:             call_user_func($callback, 'start', array(basename($dest_file), $length));
                   43003:         }
                   43004: 
                   43005:         while ($data = fread($fp, 1024)) {
                   43006:             $bytes += strlen($data);
                   43007:             if ($callback) {
                   43008:                 call_user_func($callback, 'bytesread', $bytes);
                   43009:             }
                   43010:             if (!@fwrite($wp, $data)) {
                   43011:                 fclose($fp);
                   43012:                 if ($callback) {
                   43013:                     call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg));
                   43014:                 }
                   43015:                 return PEAR::raiseError("$dest_file: write failed ($php_errormsg)");
                   43016:             }
                   43017:         }
                   43018: 
                   43019:         fclose($fp);
                   43020:         fclose($wp);
                   43021:         if ($callback) {
                   43022:             call_user_func($callback, 'done', $bytes);
                   43023:         }
                   43024: 
                   43025:         if ($lastmodified === false || $lastmodified) {
                   43026:             if (isset($headers['etag'])) {
                   43027:                 $lastmodified = array('ETag' => $headers['etag']);
                   43028:             }
                   43029: 
                   43030:             if (isset($headers['last-modified'])) {
                   43031:                 if (is_array($lastmodified)) {
                   43032:                     $lastmodified['Last-Modified'] = $headers['last-modified'];
                   43033:                 } else {
                   43034:                     $lastmodified = $headers['last-modified'];
                   43035:                 }
                   43036:             }
                   43037:             return array($dest_file, $lastmodified, $headers);
                   43038:         }
                   43039:         return $dest_file;
                   43040:     }
1.1.1.2 ! misho    43041: }PEAR-1.9.4/PEAR/ErrorStack.php0000644000076500000240000010225111605156614014554 0ustar  helgistaff<?php
1.1       misho    43042: /**
                   43043:  * Error Stack Implementation
                   43044:  * 
                   43045:  * This is an incredibly simple implementation of a very complex error handling
                   43046:  * facility.  It contains the ability
                   43047:  * to track multiple errors from multiple packages simultaneously.  In addition,
                   43048:  * it can track errors of many levels, save data along with the error, context
                   43049:  * information such as the exact file, line number, class and function that
                   43050:  * generated the error, and if necessary, it can raise a traditional PEAR_Error.
                   43051:  * It has built-in support for PEAR::Log, to log errors as they occur
                   43052:  * 
                   43053:  * Since version 0.2alpha, it is also possible to selectively ignore errors,
                   43054:  * through the use of an error callback, see {@link pushCallback()}
                   43055:  * 
                   43056:  * Since version 0.3alpha, it is possible to specify the exception class
                   43057:  * returned from {@link push()}
                   43058:  *
                   43059:  * Since version PEAR1.3.2, ErrorStack no longer instantiates an exception class.  This can
                   43060:  * still be done quite handily in an error callback or by manipulating the returned array
                   43061:  * @category   Debugging
                   43062:  * @package    PEAR_ErrorStack
                   43063:  * @author     Greg Beaver <cellog@php.net>
                   43064:  * @copyright  2004-2008 Greg Beaver
                   43065:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   43066:  * @version    CVS: $Id: ErrorStack.php 313023 2011-07-06 19:17:11Z dufuz $
                   43067:  * @link       http://pear.php.net/package/PEAR_ErrorStack
                   43068:  */
                   43069: 
                   43070: /**
                   43071:  * Singleton storage
                   43072:  * 
                   43073:  * Format:
                   43074:  * <pre>
                   43075:  * array(
                   43076:  *  'package1' => PEAR_ErrorStack object,
                   43077:  *  'package2' => PEAR_ErrorStack object,
                   43078:  *  ...
                   43079:  * )
                   43080:  * </pre>
                   43081:  * @access private
                   43082:  * @global array $GLOBALS['_PEAR_ERRORSTACK_SINGLETON']
                   43083:  */
                   43084: $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] = array();
                   43085: 
                   43086: /**
                   43087:  * Global error callback (default)
                   43088:  * 
                   43089:  * This is only used if set to non-false.  * is the default callback for
                   43090:  * all packages, whereas specific packages may set a default callback
                   43091:  * for all instances, regardless of whether they are a singleton or not.
                   43092:  *
                   43093:  * To exclude non-singletons, only set the local callback for the singleton
                   43094:  * @see PEAR_ErrorStack::setDefaultCallback()
                   43095:  * @access private
                   43096:  * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']
                   43097:  */
                   43098: $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] = array(
                   43099:     '*' => false,
                   43100: );
                   43101: 
                   43102: /**
                   43103:  * Global Log object (default)
                   43104:  * 
                   43105:  * This is only used if set to non-false.  Use to set a default log object for
                   43106:  * all stacks, regardless of instantiation order or location
                   43107:  * @see PEAR_ErrorStack::setDefaultLogger()
                   43108:  * @access private
                   43109:  * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']
                   43110:  */
                   43111: $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = false;
                   43112: 
                   43113: /**
                   43114:  * Global Overriding Callback
                   43115:  * 
                   43116:  * This callback will override any error callbacks that specific loggers have set.
                   43117:  * Use with EXTREME caution
                   43118:  * @see PEAR_ErrorStack::staticPushCallback()
                   43119:  * @access private
                   43120:  * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']
                   43121:  */
                   43122: $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();
                   43123: 
                   43124: /**#@+
                   43125:  * One of four possible return values from the error Callback
                   43126:  * @see PEAR_ErrorStack::_errorCallback()
                   43127:  */
                   43128: /**
                   43129:  * If this is returned, then the error will be both pushed onto the stack
                   43130:  * and logged.
                   43131:  */
                   43132: define('PEAR_ERRORSTACK_PUSHANDLOG', 1);
                   43133: /**
                   43134:  * If this is returned, then the error will only be pushed onto the stack,
                   43135:  * and not logged.
                   43136:  */
                   43137: define('PEAR_ERRORSTACK_PUSH', 2);
                   43138: /**
                   43139:  * If this is returned, then the error will only be logged, but not pushed
                   43140:  * onto the error stack.
                   43141:  */
                   43142: define('PEAR_ERRORSTACK_LOG', 3);
                   43143: /**
                   43144:  * If this is returned, then the error is completely ignored.
                   43145:  */
                   43146: define('PEAR_ERRORSTACK_IGNORE', 4);
                   43147: /**
                   43148:  * If this is returned, then the error is logged and die() is called.
                   43149:  */
                   43150: define('PEAR_ERRORSTACK_DIE', 5);
                   43151: /**#@-*/
                   43152: 
                   43153: /**
                   43154:  * Error code for an attempt to instantiate a non-class as a PEAR_ErrorStack in
                   43155:  * the singleton method.
                   43156:  */
                   43157: define('PEAR_ERRORSTACK_ERR_NONCLASS', 1);
                   43158: 
                   43159: /**
                   43160:  * Error code for an attempt to pass an object into {@link PEAR_ErrorStack::getMessage()}
                   43161:  * that has no __toString() method
                   43162:  */
                   43163: define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2);
                   43164: /**
                   43165:  * Error Stack Implementation
                   43166:  *
                   43167:  * Usage:
                   43168:  * <code>
                   43169:  * // global error stack
                   43170:  * $global_stack = &PEAR_ErrorStack::singleton('MyPackage');
                   43171:  * // local error stack
                   43172:  * $local_stack = new PEAR_ErrorStack('MyPackage');
                   43173:  * </code>
                   43174:  * @author     Greg Beaver <cellog@php.net>
                   43175:  * @version    1.9.4
                   43176:  * @package    PEAR_ErrorStack
                   43177:  * @category   Debugging
                   43178:  * @copyright  2004-2008 Greg Beaver
                   43179:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   43180:  * @version    CVS: $Id: ErrorStack.php 313023 2011-07-06 19:17:11Z dufuz $
                   43181:  * @link       http://pear.php.net/package/PEAR_ErrorStack
                   43182:  */
                   43183: class PEAR_ErrorStack {
                   43184:     /**
                   43185:      * Errors are stored in the order that they are pushed on the stack.
                   43186:      * @since 0.4alpha Errors are no longer organized by error level.
                   43187:      * This renders pop() nearly unusable, and levels could be more easily
                   43188:      * handled in a callback anyway
                   43189:      * @var array
                   43190:      * @access private
                   43191:      */
                   43192:     var $_errors = array();
                   43193: 
                   43194:     /**
                   43195:      * Storage of errors by level.
                   43196:      *
                   43197:      * Allows easy retrieval and deletion of only errors from a particular level
                   43198:      * @since PEAR 1.4.0dev
                   43199:      * @var array
                   43200:      * @access private
                   43201:      */
                   43202:     var $_errorsByLevel = array();
                   43203: 
                   43204:     /**
                   43205:      * Package name this error stack represents
                   43206:      * @var string
                   43207:      * @access protected
                   43208:      */
                   43209:     var $_package;
                   43210:     
                   43211:     /**
                   43212:      * Determines whether a PEAR_Error is thrown upon every error addition
                   43213:      * @var boolean
                   43214:      * @access private
                   43215:      */
                   43216:     var $_compat = false;
                   43217:     
                   43218:     /**
                   43219:      * If set to a valid callback, this will be used to generate the error
                   43220:      * message from the error code, otherwise the message passed in will be
                   43221:      * used
                   43222:      * @var false|string|array
                   43223:      * @access private
                   43224:      */
                   43225:     var $_msgCallback = false;
                   43226:     
                   43227:     /**
                   43228:      * If set to a valid callback, this will be used to generate the error
                   43229:      * context for an error.  For PHP-related errors, this will be a file
                   43230:      * and line number as retrieved from debug_backtrace(), but can be
                   43231:      * customized for other purposes.  The error might actually be in a separate
                   43232:      * configuration file, or in a database query.
                   43233:      * @var false|string|array
                   43234:      * @access protected
                   43235:      */
                   43236:     var $_contextCallback = false;
                   43237:     
                   43238:     /**
                   43239:      * If set to a valid callback, this will be called every time an error
                   43240:      * is pushed onto the stack.  The return value will be used to determine
                   43241:      * whether to allow an error to be pushed or logged.
                   43242:      * 
                   43243:      * The return value must be one an PEAR_ERRORSTACK_* constant
                   43244:      * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
                   43245:      * @var false|string|array
                   43246:      * @access protected
                   43247:      */
                   43248:     var $_errorCallback = array();
                   43249:     
                   43250:     /**
                   43251:      * PEAR::Log object for logging errors
                   43252:      * @var false|Log
                   43253:      * @access protected
                   43254:      */
                   43255:     var $_logger = false;
                   43256:     
                   43257:     /**
                   43258:      * Error messages - designed to be overridden
                   43259:      * @var array
                   43260:      * @abstract
                   43261:      */
                   43262:     var $_errorMsgs = array();
                   43263:     
                   43264:     /**
                   43265:      * Set up a new error stack
                   43266:      * 
                   43267:      * @param string   $package name of the package this error stack represents
                   43268:      * @param callback $msgCallback callback used for error message generation
                   43269:      * @param callback $contextCallback callback used for context generation,
                   43270:      *                 defaults to {@link getFileLine()}
                   43271:      * @param boolean  $throwPEAR_Error
                   43272:      */
                   43273:     function PEAR_ErrorStack($package, $msgCallback = false, $contextCallback = false,
                   43274:                          $throwPEAR_Error = false)
                   43275:     {
                   43276:         $this->_package = $package;
                   43277:         $this->setMessageCallback($msgCallback);
                   43278:         $this->setContextCallback($contextCallback);
                   43279:         $this->_compat = $throwPEAR_Error;
                   43280:     }
                   43281:     
                   43282:     /**
                   43283:      * Return a single error stack for this package.
                   43284:      * 
                   43285:      * Note that all parameters are ignored if the stack for package $package
                   43286:      * has already been instantiated
                   43287:      * @param string   $package name of the package this error stack represents
                   43288:      * @param callback $msgCallback callback used for error message generation
                   43289:      * @param callback $contextCallback callback used for context generation,
                   43290:      *                 defaults to {@link getFileLine()}
                   43291:      * @param boolean  $throwPEAR_Error
                   43292:      * @param string   $stackClass class to instantiate
                   43293:      * @static
                   43294:      * @return PEAR_ErrorStack
                   43295:      */
                   43296:     function &singleton($package, $msgCallback = false, $contextCallback = false,
                   43297:                          $throwPEAR_Error = false, $stackClass = 'PEAR_ErrorStack')
                   43298:     {
                   43299:         if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
                   43300:             return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
                   43301:         }
                   43302:         if (!class_exists($stackClass)) {
                   43303:             if (function_exists('debug_backtrace')) {
                   43304:                 $trace = debug_backtrace();
                   43305:             }
                   43306:             PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_NONCLASS,
                   43307:                 'exception', array('stackclass' => $stackClass),
                   43308:                 'stack class "%stackclass%" is not a valid class name (should be like PEAR_ErrorStack)',
                   43309:                 false, $trace);
                   43310:         }
                   43311:         $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package] =
                   43312:             new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error);
                   43313: 
                   43314:         return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
                   43315:     }
                   43316: 
                   43317:     /**
                   43318:      * Internal error handler for PEAR_ErrorStack class
                   43319:      * 
                   43320:      * Dies if the error is an exception (and would have died anyway)
                   43321:      * @access private
                   43322:      */
                   43323:     function _handleError($err)
                   43324:     {
                   43325:         if ($err['level'] == 'exception') {
                   43326:             $message = $err['message'];
                   43327:             if (isset($_SERVER['REQUEST_URI'])) {
                   43328:                 echo '<br />';
                   43329:             } else {
                   43330:                 echo "\n";
                   43331:             }
                   43332:             var_dump($err['context']);
                   43333:             die($message);
                   43334:         }
                   43335:     }
                   43336:     
                   43337:     /**
                   43338:      * Set up a PEAR::Log object for all error stacks that don't have one
                   43339:      * @param Log $log 
                   43340:      * @static
                   43341:      */
                   43342:     function setDefaultLogger(&$log)
                   43343:     {
                   43344:         if (is_object($log) && method_exists($log, 'log') ) {
                   43345:             $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
                   43346:         } elseif (is_callable($log)) {
                   43347:             $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
                   43348:        }
                   43349:     }
                   43350:     
                   43351:     /**
                   43352:      * Set up a PEAR::Log object for this error stack
                   43353:      * @param Log $log 
                   43354:      */
                   43355:     function setLogger(&$log)
                   43356:     {
                   43357:         if (is_object($log) && method_exists($log, 'log') ) {
                   43358:             $this->_logger = &$log;
                   43359:         } elseif (is_callable($log)) {
                   43360:             $this->_logger = &$log;
                   43361:         }
                   43362:     }
                   43363:     
                   43364:     /**
                   43365:      * Set an error code => error message mapping callback
                   43366:      * 
                   43367:      * This method sets the callback that can be used to generate error
                   43368:      * messages for any instance
                   43369:      * @param array|string Callback function/method
                   43370:      */
                   43371:     function setMessageCallback($msgCallback)
                   43372:     {
                   43373:         if (!$msgCallback) {
                   43374:             $this->_msgCallback = array(&$this, 'getErrorMessage');
                   43375:         } else {
                   43376:             if (is_callable($msgCallback)) {
                   43377:                 $this->_msgCallback = $msgCallback;
                   43378:             }
                   43379:         }
                   43380:     }
                   43381:     
                   43382:     /**
                   43383:      * Get an error code => error message mapping callback
                   43384:      * 
                   43385:      * This method returns the current callback that can be used to generate error
                   43386:      * messages
                   43387:      * @return array|string|false Callback function/method or false if none
                   43388:      */
                   43389:     function getMessageCallback()
                   43390:     {
                   43391:         return $this->_msgCallback;
                   43392:     }
                   43393:     
                   43394:     /**
                   43395:      * Sets a default callback to be used by all error stacks
                   43396:      * 
                   43397:      * This method sets the callback that can be used to generate error
                   43398:      * messages for a singleton
                   43399:      * @param array|string Callback function/method
                   43400:      * @param string Package name, or false for all packages
                   43401:      * @static
                   43402:      */
                   43403:     function setDefaultCallback($callback = false, $package = false)
                   43404:     {
                   43405:         if (!is_callable($callback)) {
                   43406:             $callback = false;
                   43407:         }
                   43408:         $package = $package ? $package : '*';
                   43409:         $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$package] = $callback;
                   43410:     }
                   43411:     
                   43412:     /**
                   43413:      * Set a callback that generates context information (location of error) for an error stack
                   43414:      * 
                   43415:      * This method sets the callback that can be used to generate context
                   43416:      * information for an error.  Passing in NULL will disable context generation
                   43417:      * and remove the expensive call to debug_backtrace()
                   43418:      * @param array|string|null Callback function/method
                   43419:      */
                   43420:     function setContextCallback($contextCallback)
                   43421:     {
                   43422:         if ($contextCallback === null) {
                   43423:             return $this->_contextCallback = false;
                   43424:         }
                   43425:         if (!$contextCallback) {
                   43426:             $this->_contextCallback = array(&$this, 'getFileLine');
                   43427:         } else {
                   43428:             if (is_callable($contextCallback)) {
                   43429:                 $this->_contextCallback = $contextCallback;
                   43430:             }
                   43431:         }
                   43432:     }
                   43433:     
                   43434:     /**
                   43435:      * Set an error Callback
                   43436:      * If set to a valid callback, this will be called every time an error
                   43437:      * is pushed onto the stack.  The return value will be used to determine
                   43438:      * whether to allow an error to be pushed or logged.
                   43439:      * 
                   43440:      * The return value must be one of the ERRORSTACK_* constants.
                   43441:      * 
                   43442:      * This functionality can be used to emulate PEAR's pushErrorHandling, and
                   43443:      * the PEAR_ERROR_CALLBACK mode, without affecting the integrity of
                   43444:      * the error stack or logging
                   43445:      * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
                   43446:      * @see popCallback()
                   43447:      * @param string|array $cb
                   43448:      */
                   43449:     function pushCallback($cb)
                   43450:     {
                   43451:         array_push($this->_errorCallback, $cb);
                   43452:     }
                   43453:     
                   43454:     /**
                   43455:      * Remove a callback from the error callback stack
                   43456:      * @see pushCallback()
                   43457:      * @return array|string|false
                   43458:      */
                   43459:     function popCallback()
                   43460:     {
                   43461:         if (!count($this->_errorCallback)) {
                   43462:             return false;
                   43463:         }
                   43464:         return array_pop($this->_errorCallback);
                   43465:     }
                   43466:     
                   43467:     /**
                   43468:      * Set a temporary overriding error callback for every package error stack
                   43469:      *
                   43470:      * Use this to temporarily disable all existing callbacks (can be used
                   43471:      * to emulate the @ operator, for instance)
                   43472:      * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
                   43473:      * @see staticPopCallback(), pushCallback()
                   43474:      * @param string|array $cb
                   43475:      * @static
                   43476:      */
                   43477:     function staticPushCallback($cb)
                   43478:     {
                   43479:         array_push($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'], $cb);
                   43480:     }
                   43481:     
                   43482:     /**
                   43483:      * Remove a temporary overriding error callback
                   43484:      * @see staticPushCallback()
                   43485:      * @return array|string|false
                   43486:      * @static
                   43487:      */
                   43488:     function staticPopCallback()
                   43489:     {
                   43490:         $ret = array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']);
                   43491:         if (!is_array($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'])) {
                   43492:             $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();
                   43493:         }
                   43494:         return $ret;
                   43495:     }
                   43496:     
                   43497:     /**
                   43498:      * Add an error to the stack
                   43499:      * 
                   43500:      * If the message generator exists, it is called with 2 parameters.
                   43501:      *  - the current Error Stack object
                   43502:      *  - an array that is in the same format as an error.  Available indices
                   43503:      *    are 'code', 'package', 'time', 'params', 'level', and 'context'
                   43504:      * 
                   43505:      * Next, if the error should contain context information, this is
                   43506:      * handled by the context grabbing method.
                   43507:      * Finally, the error is pushed onto the proper error stack
                   43508:      * @param int    $code      Package-specific error code
                   43509:      * @param string $level     Error level.  This is NOT spell-checked
                   43510:      * @param array  $params    associative array of error parameters
                   43511:      * @param string $msg       Error message, or a portion of it if the message
                   43512:      *                          is to be generated
                   43513:      * @param array  $repackage If this error re-packages an error pushed by
                   43514:      *                          another package, place the array returned from
                   43515:      *                          {@link pop()} in this parameter
                   43516:      * @param array  $backtrace Protected parameter: use this to pass in the
                   43517:      *                          {@link debug_backtrace()} that should be used
                   43518:      *                          to find error context
                   43519:      * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also
                   43520:      * thrown.  If a PEAR_Error is returned, the userinfo
                   43521:      * property is set to the following array:
                   43522:      * 
                   43523:      * <code>
                   43524:      * array(
                   43525:      *    'code' => $code,
                   43526:      *    'params' => $params,
                   43527:      *    'package' => $this->_package,
                   43528:      *    'level' => $level,
                   43529:      *    'time' => time(),
                   43530:      *    'context' => $context,
                   43531:      *    'message' => $msg,
                   43532:      * //['repackage' => $err] repackaged error array/Exception class
                   43533:      * );
                   43534:      * </code>
                   43535:      * 
                   43536:      * Normally, the previous array is returned.
                   43537:      */
                   43538:     function push($code, $level = 'error', $params = array(), $msg = false,
                   43539:                   $repackage = false, $backtrace = false)
                   43540:     {
                   43541:         $context = false;
                   43542:         // grab error context
                   43543:         if ($this->_contextCallback) {
                   43544:             if (!$backtrace) {
                   43545:                 $backtrace = debug_backtrace();
                   43546:             }
                   43547:             $context = call_user_func($this->_contextCallback, $code, $params, $backtrace);
                   43548:         }
                   43549:         
                   43550:         // save error
                   43551:         $time = explode(' ', microtime());
                   43552:         $time = $time[1] + $time[0];
                   43553:         $err = array(
                   43554:                 'code' => $code,
                   43555:                 'params' => $params,
                   43556:                 'package' => $this->_package,
                   43557:                 'level' => $level,
                   43558:                 'time' => $time,
                   43559:                 'context' => $context,
                   43560:                 'message' => $msg,
                   43561:                );
                   43562: 
                   43563:         if ($repackage) {
                   43564:             $err['repackage'] = $repackage;
                   43565:         }
                   43566: 
                   43567:         // set up the error message, if necessary
                   43568:         if ($this->_msgCallback) {
                   43569:             $msg = call_user_func_array($this->_msgCallback,
                   43570:                                         array(&$this, $err));
                   43571:             $err['message'] = $msg;
                   43572:         }        
                   43573:         $push = $log = true;
                   43574:         $die = false;
                   43575:         // try the overriding callback first
                   43576:         $callback = $this->staticPopCallback();
                   43577:         if ($callback) {
                   43578:             $this->staticPushCallback($callback);
                   43579:         }
                   43580:         if (!is_callable($callback)) {
                   43581:             // try the local callback next
                   43582:             $callback = $this->popCallback();
                   43583:             if (is_callable($callback)) {
                   43584:                 $this->pushCallback($callback);
                   43585:             } else {
                   43586:                 // try the default callback
                   43587:                 $callback = isset($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package]) ?
                   43588:                     $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package] :
                   43589:                     $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']['*'];
                   43590:             }
                   43591:         }
                   43592:         if (is_callable($callback)) {
                   43593:             switch(call_user_func($callback, $err)){
                   43594:                case PEAR_ERRORSTACK_IGNORE: 
                   43595:                        return $err;
                   43596:                        break;
                   43597:                case PEAR_ERRORSTACK_PUSH: 
                   43598:                        $log = false;
                   43599:                        break;
                   43600:                case PEAR_ERRORSTACK_LOG: 
                   43601:                        $push = false;
                   43602:                        break;
                   43603:                case PEAR_ERRORSTACK_DIE: 
                   43604:                        $die = true;
                   43605:                        break;
                   43606:                 // anything else returned has the same effect as pushandlog
                   43607:             }
                   43608:         }
                   43609:         if ($push) {
                   43610:             array_unshift($this->_errors, $err);
                   43611:             if (!isset($this->_errorsByLevel[$err['level']])) {
                   43612:                 $this->_errorsByLevel[$err['level']] = array();
                   43613:             }
                   43614:             $this->_errorsByLevel[$err['level']][] = &$this->_errors[0];
                   43615:         }
                   43616:         if ($log) {
                   43617:             if ($this->_logger || $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']) {
                   43618:                 $this->_log($err);
                   43619:             }
                   43620:         }
                   43621:         if ($die) {
                   43622:             die();
                   43623:         }
                   43624:         if ($this->_compat && $push) {
                   43625:             return $this->raiseError($msg, $code, null, null, $err);
                   43626:         }
                   43627:         return $err;
                   43628:     }
                   43629:     
                   43630:     /**
                   43631:      * Static version of {@link push()}
                   43632:      * 
                   43633:      * @param string $package   Package name this error belongs to
                   43634:      * @param int    $code      Package-specific error code
                   43635:      * @param string $level     Error level.  This is NOT spell-checked
                   43636:      * @param array  $params    associative array of error parameters
                   43637:      * @param string $msg       Error message, or a portion of it if the message
                   43638:      *                          is to be generated
                   43639:      * @param array  $repackage If this error re-packages an error pushed by
                   43640:      *                          another package, place the array returned from
                   43641:      *                          {@link pop()} in this parameter
                   43642:      * @param array  $backtrace Protected parameter: use this to pass in the
                   43643:      *                          {@link debug_backtrace()} that should be used
                   43644:      *                          to find error context
                   43645:      * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also
                   43646:      *                          thrown.  see docs for {@link push()}
                   43647:      * @static
                   43648:      */
                   43649:     function staticPush($package, $code, $level = 'error', $params = array(),
                   43650:                         $msg = false, $repackage = false, $backtrace = false)
                   43651:     {
                   43652:         $s = &PEAR_ErrorStack::singleton($package);
                   43653:         if ($s->_contextCallback) {
                   43654:             if (!$backtrace) {
                   43655:                 if (function_exists('debug_backtrace')) {
                   43656:                     $backtrace = debug_backtrace();
                   43657:                 }
                   43658:             }
                   43659:         }
                   43660:         return $s->push($code, $level, $params, $msg, $repackage, $backtrace);
                   43661:     }
                   43662:     
                   43663:     /**
                   43664:      * Log an error using PEAR::Log
                   43665:      * @param array $err Error array
                   43666:      * @param array $levels Error level => Log constant map
                   43667:      * @access protected
                   43668:      */
                   43669:     function _log($err)
                   43670:     {
                   43671:         if ($this->_logger) {
                   43672:             $logger = &$this->_logger;
                   43673:         } else {
                   43674:             $logger = &$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'];
                   43675:         }
                   43676:         if (is_a($logger, 'Log')) {
                   43677:             $levels = array(
                   43678:                 'exception' => PEAR_LOG_CRIT,
                   43679:                 'alert' => PEAR_LOG_ALERT,
                   43680:                 'critical' => PEAR_LOG_CRIT,
                   43681:                 'error' => PEAR_LOG_ERR,
                   43682:                 'warning' => PEAR_LOG_WARNING,
                   43683:                 'notice' => PEAR_LOG_NOTICE,
                   43684:                 'info' => PEAR_LOG_INFO,
                   43685:                 'debug' => PEAR_LOG_DEBUG);
                   43686:             if (isset($levels[$err['level']])) {
                   43687:                 $level = $levels[$err['level']];
                   43688:             } else {
                   43689:                 $level = PEAR_LOG_INFO;
                   43690:             }
                   43691:             $logger->log($err['message'], $level, $err);
                   43692:         } else { // support non-standard logs
                   43693:             call_user_func($logger, $err);
                   43694:         }
                   43695:     }
                   43696: 
                   43697:     
                   43698:     /**
                   43699:      * Pop an error off of the error stack
                   43700:      * 
                   43701:      * @return false|array
                   43702:      * @since 0.4alpha it is no longer possible to specify a specific error
                   43703:      * level to return - the last error pushed will be returned, instead
                   43704:      */
                   43705:     function pop()
                   43706:     {
                   43707:         $err = @array_shift($this->_errors);
                   43708:         if (!is_null($err)) {
                   43709:             @array_pop($this->_errorsByLevel[$err['level']]);
                   43710:             if (!count($this->_errorsByLevel[$err['level']])) {
                   43711:                 unset($this->_errorsByLevel[$err['level']]);
                   43712:             }
                   43713:         }
                   43714:         return $err;
                   43715:     }
                   43716: 
                   43717:     /**
                   43718:      * Pop an error off of the error stack, static method
                   43719:      *
                   43720:      * @param string package name
                   43721:      * @return boolean
                   43722:      * @since PEAR1.5.0a1
                   43723:      */
                   43724:     function staticPop($package)
                   43725:     {
                   43726:         if ($package) {
                   43727:             if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
                   43728:                 return false;
                   43729:             }
                   43730:             return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->pop();
                   43731:         }
                   43732:     }
                   43733: 
                   43734:     /**
                   43735:      * Determine whether there are any errors on the stack
                   43736:      * @param string|array Level name.  Use to determine if any errors
                   43737:      * of level (string), or levels (array) have been pushed
                   43738:      * @return boolean
                   43739:      */
                   43740:     function hasErrors($level = false)
                   43741:     {
                   43742:         if ($level) {
                   43743:             return isset($this->_errorsByLevel[$level]);
                   43744:         }
                   43745:         return count($this->_errors);
                   43746:     }
                   43747:     
                   43748:     /**
                   43749:      * Retrieve all errors since last purge
                   43750:      * 
                   43751:      * @param boolean set in order to empty the error stack
                   43752:      * @param string level name, to return only errors of a particular severity
                   43753:      * @return array
                   43754:      */
                   43755:     function getErrors($purge = false, $level = false)
                   43756:     {
                   43757:         if (!$purge) {
                   43758:             if ($level) {
                   43759:                 if (!isset($this->_errorsByLevel[$level])) {
                   43760:                     return array();
                   43761:                 } else {
                   43762:                     return $this->_errorsByLevel[$level];
                   43763:                 }
                   43764:             } else {
                   43765:                 return $this->_errors;
                   43766:             }
                   43767:         }
                   43768:         if ($level) {
                   43769:             $ret = $this->_errorsByLevel[$level];
                   43770:             foreach ($this->_errorsByLevel[$level] as $i => $unused) {
                   43771:                 // entries are references to the $_errors array
                   43772:                 $this->_errorsByLevel[$level][$i] = false;
                   43773:             }
                   43774:             // array_filter removes all entries === false
                   43775:             $this->_errors = array_filter($this->_errors);
                   43776:             unset($this->_errorsByLevel[$level]);
                   43777:             return $ret;
                   43778:         }
                   43779:         $ret = $this->_errors;
                   43780:         $this->_errors = array();
                   43781:         $this->_errorsByLevel = array();
                   43782:         return $ret;
                   43783:     }
                   43784:     
                   43785:     /**
                   43786:      * Determine whether there are any errors on a single error stack, or on any error stack
                   43787:      *
                   43788:      * The optional parameter can be used to test the existence of any errors without the need of
                   43789:      * singleton instantiation
                   43790:      * @param string|false Package name to check for errors
                   43791:      * @param string Level name to check for a particular severity
                   43792:      * @return boolean
                   43793:      * @static
                   43794:      */
                   43795:     function staticHasErrors($package = false, $level = false)
                   43796:     {
                   43797:         if ($package) {
                   43798:             if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
                   43799:                 return false;
                   43800:             }
                   43801:             return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->hasErrors($level);
                   43802:         }
                   43803:         foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
                   43804:             if ($obj->hasErrors($level)) {
                   43805:                 return true;
                   43806:             }
                   43807:         }
                   43808:         return false;
                   43809:     }
                   43810:     
                   43811:     /**
                   43812:      * Get a list of all errors since last purge, organized by package
                   43813:      * @since PEAR 1.4.0dev BC break! $level is now in the place $merge used to be
                   43814:      * @param boolean $purge Set to purge the error stack of existing errors
                   43815:      * @param string  $level Set to a level name in order to retrieve only errors of a particular level
                   43816:      * @param boolean $merge Set to return a flat array, not organized by package
                   43817:      * @param array   $sortfunc Function used to sort a merged array - default
                   43818:      *        sorts by time, and should be good for most cases
                   43819:      * @static
                   43820:      * @return array 
                   43821:      */
                   43822:     function staticGetErrors($purge = false, $level = false, $merge = false,
                   43823:                              $sortfunc = array('PEAR_ErrorStack', '_sortErrors'))
                   43824:     {
                   43825:         $ret = array();
                   43826:         if (!is_callable($sortfunc)) {
                   43827:             $sortfunc = array('PEAR_ErrorStack', '_sortErrors');
                   43828:         }
                   43829:         foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
                   43830:             $test = $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->getErrors($purge, $level);
                   43831:             if ($test) {
                   43832:                 if ($merge) {
                   43833:                     $ret = array_merge($ret, $test);
                   43834:                 } else {
                   43835:                     $ret[$package] = $test;
                   43836:                 }
                   43837:             }
                   43838:         }
                   43839:         if ($merge) {
                   43840:             usort($ret, $sortfunc);
                   43841:         }
                   43842:         return $ret;
                   43843:     }
                   43844:     
                   43845:     /**
                   43846:      * Error sorting function, sorts by time
                   43847:      * @access private
                   43848:      */
                   43849:     function _sortErrors($a, $b)
                   43850:     {
                   43851:         if ($a['time'] == $b['time']) {
                   43852:             return 0;
                   43853:         }
                   43854:         if ($a['time'] < $b['time']) {
                   43855:             return 1;
                   43856:         }
                   43857:         return -1;
                   43858:     }
                   43859: 
                   43860:     /**
                   43861:      * Standard file/line number/function/class context callback
                   43862:      *
                   43863:      * This function uses a backtrace generated from {@link debug_backtrace()}
                   43864:      * and so will not work at all in PHP < 4.3.0.  The frame should
                   43865:      * reference the frame that contains the source of the error.
                   43866:      * @return array|false either array('file' => file, 'line' => line,
                   43867:      *         'function' => function name, 'class' => class name) or
                   43868:      *         if this doesn't work, then false
                   43869:      * @param unused
                   43870:      * @param integer backtrace frame.
                   43871:      * @param array Results of debug_backtrace()
                   43872:      * @static
                   43873:      */
                   43874:     function getFileLine($code, $params, $backtrace = null)
                   43875:     {
                   43876:         if ($backtrace === null) {
                   43877:             return false;
                   43878:         }
                   43879:         $frame = 0;
                   43880:         $functionframe = 1;
                   43881:         if (!isset($backtrace[1])) {
                   43882:             $functionframe = 0;
                   43883:         } else {
                   43884:             while (isset($backtrace[$functionframe]['function']) &&
                   43885:                   $backtrace[$functionframe]['function'] == 'eval' &&
                   43886:                   isset($backtrace[$functionframe + 1])) {
                   43887:                 $functionframe++;
                   43888:             }
                   43889:         }
                   43890:         if (isset($backtrace[$frame])) {
                   43891:             if (!isset($backtrace[$frame]['file'])) {
                   43892:                 $frame++;
                   43893:             }
                   43894:             $funcbacktrace = $backtrace[$functionframe];
                   43895:             $filebacktrace = $backtrace[$frame];
                   43896:             $ret = array('file' => $filebacktrace['file'],
                   43897:                          'line' => $filebacktrace['line']);
                   43898:             // rearrange for eval'd code or create function errors
                   43899:             if (strpos($filebacktrace['file'], '(') && 
                   43900:                  preg_match(';^(.*?)\((\d+)\) : (.*?)\\z;', $filebacktrace['file'],
                   43901:                   $matches)) {
                   43902:                 $ret['file'] = $matches[1];
                   43903:                 $ret['line'] = $matches[2] + 0;
                   43904:             }
                   43905:             if (isset($funcbacktrace['function']) && isset($backtrace[1])) {
                   43906:                 if ($funcbacktrace['function'] != 'eval') {
                   43907:                     if ($funcbacktrace['function'] == '__lambda_func') {
                   43908:                         $ret['function'] = 'create_function() code';
                   43909:                     } else {
                   43910:                         $ret['function'] = $funcbacktrace['function'];
                   43911:                     }
                   43912:                 }
                   43913:             }
                   43914:             if (isset($funcbacktrace['class']) && isset($backtrace[1])) {
                   43915:                 $ret['class'] = $funcbacktrace['class'];
                   43916:             }
                   43917:             return $ret;
                   43918:         }
                   43919:         return false;
                   43920:     }
                   43921:     
                   43922:     /**
                   43923:      * Standard error message generation callback
                   43924:      * 
                   43925:      * This method may also be called by a custom error message generator
                   43926:      * to fill in template values from the params array, simply
                   43927:      * set the third parameter to the error message template string to use
                   43928:      * 
                   43929:      * The special variable %__msg% is reserved: use it only to specify
                   43930:      * where a message passed in by the user should be placed in the template,
                   43931:      * like so:
                   43932:      * 
                   43933:      * Error message: %msg% - internal error
                   43934:      * 
                   43935:      * If the message passed like so:
                   43936:      * 
                   43937:      * <code>
                   43938:      * $stack->push(ERROR_CODE, 'error', array(), 'server error 500');
                   43939:      * </code>
                   43940:      * 
                   43941:      * The returned error message will be "Error message: server error 500 -
                   43942:      * internal error"
                   43943:      * @param PEAR_ErrorStack
                   43944:      * @param array
                   43945:      * @param string|false Pre-generated error message template
                   43946:      * @static
                   43947:      * @return string
                   43948:      */
                   43949:     function getErrorMessage(&$stack, $err, $template = false)
                   43950:     {
                   43951:         if ($template) {
                   43952:             $mainmsg = $template;
                   43953:         } else {
                   43954:             $mainmsg = $stack->getErrorMessageTemplate($err['code']);
                   43955:         }
                   43956:         $mainmsg = str_replace('%__msg%', $err['message'], $mainmsg);
                   43957:         if (is_array($err['params']) && count($err['params'])) {
                   43958:             foreach ($err['params'] as $name => $val) {
                   43959:                 if (is_array($val)) {
                   43960:                     // @ is needed in case $val is a multi-dimensional array
                   43961:                     $val = @implode(', ', $val);
                   43962:                 }
                   43963:                 if (is_object($val)) {
                   43964:                     if (method_exists($val, '__toString')) {
                   43965:                         $val = $val->__toString();
                   43966:                     } else {
                   43967:                         PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_OBJTOSTRING,
                   43968:                             'warning', array('obj' => get_class($val)),
                   43969:                             'object %obj% passed into getErrorMessage, but has no __toString() method');
                   43970:                         $val = 'Object';
                   43971:                     }
                   43972:                 }
                   43973:                 $mainmsg = str_replace('%' . $name . '%', $val, $mainmsg);
                   43974:             }
                   43975:         }
                   43976:         return $mainmsg;
                   43977:     }
                   43978:     
                   43979:     /**
                   43980:      * Standard Error Message Template generator from code
                   43981:      * @return string
                   43982:      */
                   43983:     function getErrorMessageTemplate($code)
                   43984:     {
                   43985:         if (!isset($this->_errorMsgs[$code])) {
                   43986:             return '%__msg%';
                   43987:         }
                   43988:         return $this->_errorMsgs[$code];
                   43989:     }
                   43990:     
                   43991:     /**
                   43992:      * Set the Error Message Template array
                   43993:      * 
                   43994:      * The array format must be:
                   43995:      * <pre>
                   43996:      * array(error code => 'message template',...)
                   43997:      * </pre>
                   43998:      * 
                   43999:      * Error message parameters passed into {@link push()} will be used as input
                   44000:      * for the error message.  If the template is 'message %foo% was %bar%', and the
                   44001:      * parameters are array('foo' => 'one', 'bar' => 'six'), the error message returned will
                   44002:      * be 'message one was six'
                   44003:      * @return string
                   44004:      */
                   44005:     function setErrorMessageTemplate($template)
                   44006:     {
                   44007:         $this->_errorMsgs = $template;
                   44008:     }
                   44009:     
                   44010:     
                   44011:     /**
                   44012:      * emulate PEAR::raiseError()
                   44013:      * 
                   44014:      * @return PEAR_Error
                   44015:      */
                   44016:     function raiseError()
                   44017:     {
                   44018:         require_once 'PEAR.php';
                   44019:         $args = func_get_args();
                   44020:         return call_user_func_array(array('PEAR', 'raiseError'), $args);
                   44021:     }
                   44022: }
                   44023: $stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack');
                   44024: $stack->pushCallback(array('PEAR_ErrorStack', '_handleError'));
                   44025: ?>
1.1.1.2 ! misho    44026: PEAR-1.9.4/PEAR/Exception.php0000644000076500000240000003326611605156614014444 0ustar  helgistaff<?php
1.1       misho    44027: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
                   44028: /**
                   44029:  * PEAR_Exception
                   44030:  *
                   44031:  * PHP versions 4 and 5
                   44032:  *
                   44033:  * @category   pear
                   44034:  * @package    PEAR
                   44035:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   44036:  * @author     Hans Lellelid <hans@velum.net>
                   44037:  * @author     Bertrand Mansion <bmansion@mamasam.com>
                   44038:  * @author     Greg Beaver <cellog@php.net>
                   44039:  * @copyright  1997-2009 The Authors
                   44040:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   44041:  * @version    CVS: $Id: Exception.php 313023 2011-07-06 19:17:11Z dufuz $
                   44042:  * @link       http://pear.php.net/package/PEAR
                   44043:  * @since      File available since Release 1.3.3
                   44044:  */
                   44045: 
                   44046: 
                   44047: /**
                   44048:  * Base PEAR_Exception Class
                   44049:  *
                   44050:  * 1) Features:
                   44051:  *
                   44052:  * - Nestable exceptions (throw new PEAR_Exception($msg, $prev_exception))
                   44053:  * - Definable triggers, shot when exceptions occur
                   44054:  * - Pretty and informative error messages
                   44055:  * - Added more context info available (like class, method or cause)
                   44056:  * - cause can be a PEAR_Exception or an array of mixed
                   44057:  *   PEAR_Exceptions/PEAR_ErrorStack warnings
                   44058:  * - callbacks for specific exception classes and their children
                   44059:  *
                   44060:  * 2) Ideas:
                   44061:  *
                   44062:  * - Maybe a way to define a 'template' for the output
                   44063:  *
                   44064:  * 3) Inherited properties from PHP Exception Class:
                   44065:  *
                   44066:  * protected $message
                   44067:  * protected $code
                   44068:  * protected $line
                   44069:  * protected $file
                   44070:  * private   $trace
                   44071:  *
                   44072:  * 4) Inherited methods from PHP Exception Class:
                   44073:  *
                   44074:  * __clone
                   44075:  * __construct
                   44076:  * getMessage
                   44077:  * getCode
                   44078:  * getFile
                   44079:  * getLine
                   44080:  * getTraceSafe
                   44081:  * getTraceSafeAsString
                   44082:  * __toString
                   44083:  *
                   44084:  * 5) Usage example
                   44085:  *
                   44086:  * <code>
                   44087:  *  require_once 'PEAR/Exception.php';
                   44088:  *
                   44089:  *  class Test {
                   44090:  *     function foo() {
                   44091:  *         throw new PEAR_Exception('Error Message', ERROR_CODE);
                   44092:  *     }
                   44093:  *  }
                   44094:  *
                   44095:  *  function myLogger($pear_exception) {
                   44096:  *     echo $pear_exception->getMessage();
                   44097:  *  }
                   44098:  *  // each time a exception is thrown the 'myLogger' will be called
                   44099:  *  // (its use is completely optional)
                   44100:  *  PEAR_Exception::addObserver('myLogger');
                   44101:  *  $test = new Test;
                   44102:  *  try {
                   44103:  *     $test->foo();
                   44104:  *  } catch (PEAR_Exception $e) {
                   44105:  *     print $e;
                   44106:  *  }
                   44107:  * </code>
                   44108:  *
                   44109:  * @category   pear
                   44110:  * @package    PEAR
                   44111:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   44112:  * @author     Hans Lellelid <hans@velum.net>
                   44113:  * @author     Bertrand Mansion <bmansion@mamasam.com>
                   44114:  * @author     Greg Beaver <cellog@php.net>
                   44115:  * @copyright  1997-2009 The Authors
                   44116:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   44117:  * @version    Release: 1.9.4
                   44118:  * @link       http://pear.php.net/package/PEAR
                   44119:  * @since      Class available since Release 1.3.3
                   44120:  *
                   44121:  */
                   44122: class PEAR_Exception extends Exception
                   44123: {
                   44124:     const OBSERVER_PRINT = -2;
                   44125:     const OBSERVER_TRIGGER = -4;
                   44126:     const OBSERVER_DIE = -8;
                   44127:     protected $cause;
                   44128:     private static $_observers = array();
                   44129:     private static $_uniqueid = 0;
                   44130:     private $_trace;
                   44131: 
                   44132:     /**
                   44133:      * Supported signatures:
                   44134:      *  - PEAR_Exception(string $message);
                   44135:      *  - PEAR_Exception(string $message, int $code);
                   44136:      *  - PEAR_Exception(string $message, Exception $cause);
                   44137:      *  - PEAR_Exception(string $message, Exception $cause, int $code);
                   44138:      *  - PEAR_Exception(string $message, PEAR_Error $cause);
                   44139:      *  - PEAR_Exception(string $message, PEAR_Error $cause, int $code);
                   44140:      *  - PEAR_Exception(string $message, array $causes);
                   44141:      *  - PEAR_Exception(string $message, array $causes, int $code);
                   44142:      * @param string exception message
                   44143:      * @param int|Exception|PEAR_Error|array|null exception cause
                   44144:      * @param int|null exception code or null
                   44145:      */
                   44146:     public function __construct($message, $p2 = null, $p3 = null)
                   44147:     {
                   44148:         if (is_int($p2)) {
                   44149:             $code = $p2;
                   44150:             $this->cause = null;
                   44151:         } elseif (is_object($p2) || is_array($p2)) {
                   44152:             // using is_object allows both Exception and PEAR_Error
                   44153:             if (is_object($p2) && !($p2 instanceof Exception)) {
                   44154:                 if (!class_exists('PEAR_Error') || !($p2 instanceof PEAR_Error)) {
                   44155:                     throw new PEAR_Exception('exception cause must be Exception, ' .
                   44156:                         'array, or PEAR_Error');
                   44157:                 }
                   44158:             }
                   44159:             $code = $p3;
                   44160:             if (is_array($p2) && isset($p2['message'])) {
                   44161:                 // fix potential problem of passing in a single warning
                   44162:                 $p2 = array($p2);
                   44163:             }
                   44164:             $this->cause = $p2;
                   44165:         } else {
                   44166:             $code = null;
                   44167:             $this->cause = null;
                   44168:         }
                   44169:         parent::__construct($message, $code);
                   44170:         $this->signal();
                   44171:     }
                   44172: 
                   44173:     /**
                   44174:      * @param mixed $callback  - A valid php callback, see php func is_callable()
                   44175:      *                         - A PEAR_Exception::OBSERVER_* constant
                   44176:      *                         - An array(const PEAR_Exception::OBSERVER_*,
                   44177:      *                           mixed $options)
                   44178:      * @param string $label    The name of the observer. Use this if you want
                   44179:      *                         to remove it later with removeObserver()
                   44180:      */
                   44181:     public static function addObserver($callback, $label = 'default')
                   44182:     {
                   44183:         self::$_observers[$label] = $callback;
                   44184:     }
                   44185: 
                   44186:     public static function removeObserver($label = 'default')
                   44187:     {
                   44188:         unset(self::$_observers[$label]);
                   44189:     }
                   44190: 
                   44191:     /**
                   44192:      * @return int unique identifier for an observer
                   44193:      */
                   44194:     public static function getUniqueId()
                   44195:     {
                   44196:         return self::$_uniqueid++;
                   44197:     }
                   44198: 
                   44199:     private function signal()
                   44200:     {
                   44201:         foreach (self::$_observers as $func) {
                   44202:             if (is_callable($func)) {
                   44203:                 call_user_func($func, $this);
                   44204:                 continue;
                   44205:             }
                   44206:             settype($func, 'array');
                   44207:             switch ($func[0]) {
                   44208:                 case self::OBSERVER_PRINT :
                   44209:                     $f = (isset($func[1])) ? $func[1] : '%s';
                   44210:                     printf($f, $this->getMessage());
                   44211:                     break;
                   44212:                 case self::OBSERVER_TRIGGER :
                   44213:                     $f = (isset($func[1])) ? $func[1] : E_USER_NOTICE;
                   44214:                     trigger_error($this->getMessage(), $f);
                   44215:                     break;
                   44216:                 case self::OBSERVER_DIE :
                   44217:                     $f = (isset($func[1])) ? $func[1] : '%s';
                   44218:                     die(printf($f, $this->getMessage()));
                   44219:                     break;
                   44220:                 default:
                   44221:                     trigger_error('invalid observer type', E_USER_WARNING);
                   44222:             }
                   44223:         }
                   44224:     }
                   44225: 
                   44226:     /**
                   44227:      * Return specific error information that can be used for more detailed
                   44228:      * error messages or translation.
                   44229:      *
                   44230:      * This method may be overridden in child exception classes in order
                   44231:      * to add functionality not present in PEAR_Exception and is a placeholder
                   44232:      * to define API
                   44233:      *
                   44234:      * The returned array must be an associative array of parameter => value like so:
                   44235:      * <pre>
                   44236:      * array('name' => $name, 'context' => array(...))
                   44237:      * </pre>
                   44238:      * @return array
                   44239:      */
                   44240:     public function getErrorData()
                   44241:     {
                   44242:         return array();
                   44243:     }
                   44244: 
                   44245:     /**
                   44246:      * Returns the exception that caused this exception to be thrown
                   44247:      * @access public
                   44248:      * @return Exception|array The context of the exception
                   44249:      */
                   44250:     public function getCause()
                   44251:     {
                   44252:         return $this->cause;
                   44253:     }
                   44254: 
                   44255:     /**
                   44256:      * Function must be public to call on caused exceptions
                   44257:      * @param array
                   44258:      */
                   44259:     public function getCauseMessage(&$causes)
                   44260:     {
                   44261:         $trace = $this->getTraceSafe();
                   44262:         $cause = array('class'   => get_class($this),
                   44263:                        'message' => $this->message,
                   44264:                        'file' => 'unknown',
                   44265:                        'line' => 'unknown');
                   44266:         if (isset($trace[0])) {
                   44267:             if (isset($trace[0]['file'])) {
                   44268:                 $cause['file'] = $trace[0]['file'];
                   44269:                 $cause['line'] = $trace[0]['line'];
                   44270:             }
                   44271:         }
                   44272:         $causes[] = $cause;
                   44273:         if ($this->cause instanceof PEAR_Exception) {
                   44274:             $this->cause->getCauseMessage($causes);
                   44275:         } elseif ($this->cause instanceof Exception) {
                   44276:             $causes[] = array('class'   => get_class($this->cause),
                   44277:                               'message' => $this->cause->getMessage(),
                   44278:                               'file' => $this->cause->getFile(),
                   44279:                               'line' => $this->cause->getLine());
                   44280:         } elseif (class_exists('PEAR_Error') && $this->cause instanceof PEAR_Error) {
                   44281:             $causes[] = array('class' => get_class($this->cause),
                   44282:                               'message' => $this->cause->getMessage(),
                   44283:                               'file' => 'unknown',
                   44284:                               'line' => 'unknown');
                   44285:         } elseif (is_array($this->cause)) {
                   44286:             foreach ($this->cause as $cause) {
                   44287:                 if ($cause instanceof PEAR_Exception) {
                   44288:                     $cause->getCauseMessage($causes);
                   44289:                 } elseif ($cause instanceof Exception) {
                   44290:                     $causes[] = array('class'   => get_class($cause),
                   44291:                                    'message' => $cause->getMessage(),
                   44292:                                    'file' => $cause->getFile(),
                   44293:                                    'line' => $cause->getLine());
                   44294:                 } elseif (class_exists('PEAR_Error') && $cause instanceof PEAR_Error) {
                   44295:                     $causes[] = array('class' => get_class($cause),
                   44296:                                       'message' => $cause->getMessage(),
                   44297:                                       'file' => 'unknown',
                   44298:                                       'line' => 'unknown');
                   44299:                 } elseif (is_array($cause) && isset($cause['message'])) {
                   44300:                     // PEAR_ErrorStack warning
                   44301:                     $causes[] = array(
                   44302:                         'class' => $cause['package'],
                   44303:                         'message' => $cause['message'],
                   44304:                         'file' => isset($cause['context']['file']) ?
                   44305:                                             $cause['context']['file'] :
                   44306:                                             'unknown',
                   44307:                         'line' => isset($cause['context']['line']) ?
                   44308:                                             $cause['context']['line'] :
                   44309:                                             'unknown',
                   44310:                     );
                   44311:                 }
                   44312:             }
                   44313:         }
                   44314:     }
                   44315: 
                   44316:     public function getTraceSafe()
                   44317:     {
                   44318:         if (!isset($this->_trace)) {
                   44319:             $this->_trace = $this->getTrace();
                   44320:             if (empty($this->_trace)) {
                   44321:                 $backtrace = debug_backtrace();
                   44322:                 $this->_trace = array($backtrace[count($backtrace)-1]);
                   44323:             }
                   44324:         }
                   44325:         return $this->_trace;
                   44326:     }
                   44327: 
                   44328:     public function getErrorClass()
                   44329:     {
                   44330:         $trace = $this->getTraceSafe();
                   44331:         return $trace[0]['class'];
                   44332:     }
                   44333: 
                   44334:     public function getErrorMethod()
                   44335:     {
                   44336:         $trace = $this->getTraceSafe();
                   44337:         return $trace[0]['function'];
                   44338:     }
                   44339: 
                   44340:     public function __toString()
                   44341:     {
                   44342:         if (isset($_SERVER['REQUEST_URI'])) {
                   44343:             return $this->toHtml();
                   44344:         }
                   44345:         return $this->toText();
                   44346:     }
                   44347: 
                   44348:     public function toHtml()
                   44349:     {
                   44350:         $trace = $this->getTraceSafe();
                   44351:         $causes = array();
                   44352:         $this->getCauseMessage($causes);
                   44353:         $html =  '<table style="border: 1px" cellspacing="0">' . "\n";
                   44354:         foreach ($causes as $i => $cause) {
                   44355:             $html .= '<tr><td colspan="3" style="background: #ff9999">'
                   44356:                . str_repeat('-', $i) . ' <b>' . $cause['class'] . '</b>: '
                   44357:                . htmlspecialchars($cause['message']) . ' in <b>' . $cause['file'] . '</b> '
                   44358:                . 'on line <b>' . $cause['line'] . '</b>'
                   44359:                . "</td></tr>\n";
                   44360:         }
                   44361:         $html .= '<tr><td colspan="3" style="background-color: #aaaaaa; text-align: center; font-weight: bold;">Exception trace</td></tr>' . "\n"
                   44362:                . '<tr><td style="text-align: center; background: #cccccc; width:20px; font-weight: bold;">#</td>'
                   44363:                . '<td style="text-align: center; background: #cccccc; font-weight: bold;">Function</td>'
                   44364:                . '<td style="text-align: center; background: #cccccc; font-weight: bold;">Location</td></tr>' . "\n";
                   44365: 
                   44366:         foreach ($trace as $k => $v) {
                   44367:             $html .= '<tr><td style="text-align: center;">' . $k . '</td>'
                   44368:                    . '<td>';
                   44369:             if (!empty($v['class'])) {
                   44370:                 $html .= $v['class'] . $v['type'];
                   44371:             }
                   44372:             $html .= $v['function'];
                   44373:             $args = array();
                   44374:             if (!empty($v['args'])) {
                   44375:                 foreach ($v['args'] as $arg) {
                   44376:                     if (is_null($arg)) $args[] = 'null';
                   44377:                     elseif (is_array($arg)) $args[] = 'Array';
                   44378:                     elseif (is_object($arg)) $args[] = 'Object('.get_class($arg).')';
                   44379:                     elseif (is_bool($arg)) $args[] = $arg ? 'true' : 'false';
                   44380:                     elseif (is_int($arg) || is_double($arg)) $args[] = $arg;
                   44381:                     else {
                   44382:                         $arg = (string)$arg;
                   44383:                         $str = htmlspecialchars(substr($arg, 0, 16));
                   44384:                         if (strlen($arg) > 16) $str .= '&hellip;';
                   44385:                         $args[] = "'" . $str . "'";
                   44386:                     }
                   44387:                 }
                   44388:             }
                   44389:             $html .= '(' . implode(', ',$args) . ')'
                   44390:                    . '</td>'
                   44391:                    . '<td>' . (isset($v['file']) ? $v['file'] : 'unknown')
                   44392:                    . ':' . (isset($v['line']) ? $v['line'] : 'unknown')
                   44393:                    . '</td></tr>' . "\n";
                   44394:         }
                   44395:         $html .= '<tr><td style="text-align: center;">' . ($k+1) . '</td>'
                   44396:                . '<td>{main}</td>'
                   44397:                . '<td>&nbsp;</td></tr>' . "\n"
                   44398:                . '</table>';
                   44399:         return $html;
                   44400:     }
                   44401: 
                   44402:     public function toText()
                   44403:     {
                   44404:         $causes = array();
                   44405:         $this->getCauseMessage($causes);
                   44406:         $causeMsg = '';
                   44407:         foreach ($causes as $i => $cause) {
                   44408:             $causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': '
                   44409:                    . $cause['message'] . ' in ' . $cause['file']
                   44410:                    . ' on line ' . $cause['line'] . "\n";
                   44411:         }
                   44412:         return $causeMsg . $this->getTraceAsString();
                   44413:     }
1.1.1.2 ! misho    44414: }PEAR-1.9.4/PEAR/FixPHP5PEARWarnings.php0000644000076500000240000000023111605156614016034 0ustar  helgistaff<?php
1.1       misho    44415: if ($skipmsg) {
                   44416:     $a = &new $ec($code, $mode, $options, $userinfo);
                   44417: } else {
                   44418:     $a = &new $ec($message, $code, $mode, $options, $userinfo);
                   44419: }
1.1.1.2 ! misho    44420: ?>PEAR-1.9.4/PEAR/Frontend.php0000644000076500000240000001507711605156614014265 0ustar  helgistaff<?php
1.1       misho    44421: /**
                   44422:  * PEAR_Frontend, the singleton-based frontend for user input/output
                   44423:  *
                   44424:  * PHP versions 4 and 5
                   44425:  *
                   44426:  * @category   pear
                   44427:  * @package    PEAR
                   44428:  * @author     Greg Beaver <cellog@php.net>
                   44429:  * @copyright  1997-2009 The Authors
                   44430:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   44431:  * @version    CVS: $Id: Frontend.php 313023 2011-07-06 19:17:11Z dufuz $
                   44432:  * @link       http://pear.php.net/package/PEAR
                   44433:  * @since      File available since Release 1.4.0a1
                   44434:  */
                   44435: 
                   44436: /**
                   44437:  * Include error handling
                   44438:  */
                   44439: //require_once 'PEAR.php';
                   44440: 
                   44441: /**
                   44442:  * Which user interface class is being used.
                   44443:  * @var string class name
                   44444:  */
                   44445: $GLOBALS['_PEAR_FRONTEND_CLASS'] = 'PEAR_Frontend_CLI';
                   44446: 
                   44447: /**
                   44448:  * Instance of $_PEAR_Command_uiclass.
                   44449:  * @var object
                   44450:  */
                   44451: $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = null;
                   44452: 
                   44453: /**
                   44454:  * Singleton-based frontend for PEAR user input/output
                   44455:  *
                   44456:  * @category   pear
                   44457:  * @package    PEAR
                   44458:  * @author     Greg Beaver <cellog@php.net>
                   44459:  * @copyright  1997-2009 The Authors
                   44460:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   44461:  * @version    Release: 1.9.4
                   44462:  * @link       http://pear.php.net/package/PEAR
                   44463:  * @since      Class available since Release 1.4.0a1
                   44464:  */
                   44465: class PEAR_Frontend extends PEAR
                   44466: {
                   44467:     /**
                   44468:      * Retrieve the frontend object
                   44469:      * @return PEAR_Frontend_CLI|PEAR_Frontend_Web|PEAR_Frontend_Gtk
                   44470:      * @static
                   44471:      */
                   44472:     function &singleton($type = null)
                   44473:     {
                   44474:         if ($type === null) {
                   44475:             if (!isset($GLOBALS['_PEAR_FRONTEND_SINGLETON'])) {
                   44476:                 $a = false;
                   44477:                 return $a;
                   44478:             }
                   44479:             return $GLOBALS['_PEAR_FRONTEND_SINGLETON'];
                   44480:         }
                   44481: 
                   44482:         $a = PEAR_Frontend::setFrontendClass($type);
                   44483:         return $a;
                   44484:     }
                   44485: 
                   44486:     /**
                   44487:      * Set the frontend class that will be used by calls to {@link singleton()}
                   44488:      *
                   44489:      * Frontends are expected to conform to the PEAR naming standard of
                   44490:      * _ => DIRECTORY_SEPARATOR (PEAR_Frontend_CLI is in PEAR/Frontend/CLI.php)
                   44491:      * @param string $uiclass full class name
                   44492:      * @return PEAR_Frontend
                   44493:      * @static
                   44494:      */
                   44495:     function &setFrontendClass($uiclass)
                   44496:     {
                   44497:         if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) &&
                   44498:               is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], $uiclass)) {
                   44499:             return $GLOBALS['_PEAR_FRONTEND_SINGLETON'];
                   44500:         }
                   44501: 
                   44502:         if (!class_exists($uiclass)) {
                   44503:             $file = str_replace('_', '/', $uiclass) . '.php';
                   44504:             if (PEAR_Frontend::isIncludeable($file)) {
                   44505:                 include_once $file;
                   44506:             }
                   44507:         }
                   44508: 
                   44509:         if (class_exists($uiclass)) {
                   44510:             $obj = &new $uiclass;
                   44511:             // quick test to see if this class implements a few of the most
                   44512:             // important frontend methods
                   44513:             if (is_a($obj, 'PEAR_Frontend')) {
                   44514:                 $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$obj;
                   44515:                 $GLOBALS['_PEAR_FRONTEND_CLASS'] = $uiclass;
                   44516:                 return $obj;
                   44517:             }
                   44518: 
                   44519:             $err = PEAR::raiseError("not a frontend class: $uiclass");
                   44520:             return $err;
                   44521:         }
                   44522: 
                   44523:         $err = PEAR::raiseError("no such class: $uiclass");
                   44524:         return $err;
                   44525:     }
                   44526: 
                   44527:     /**
                   44528:      * Set the frontend class that will be used by calls to {@link singleton()}
                   44529:      *
                   44530:      * Frontends are expected to be a descendant of PEAR_Frontend
                   44531:      * @param PEAR_Frontend
                   44532:      * @return PEAR_Frontend
                   44533:      * @static
                   44534:      */
                   44535:     function &setFrontendObject($uiobject)
                   44536:     {
                   44537:         if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) &&
                   44538:               is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], get_class($uiobject))) {
                   44539:             return $GLOBALS['_PEAR_FRONTEND_SINGLETON'];
                   44540:         }
                   44541: 
                   44542:         if (!is_a($uiobject, 'PEAR_Frontend')) {
                   44543:             $err = PEAR::raiseError('not a valid frontend class: (' .
                   44544:                 get_class($uiobject) . ')');
                   44545:             return $err;
                   44546:         }
                   44547: 
                   44548:         $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$uiobject;
                   44549:         $GLOBALS['_PEAR_FRONTEND_CLASS'] = get_class($uiobject);
                   44550:         return $uiobject;
                   44551:     }
                   44552: 
                   44553:     /**
                   44554:      * @param string $path relative or absolute include path
                   44555:      * @return boolean
                   44556:      * @static
                   44557:      */
                   44558:     function isIncludeable($path)
                   44559:     {
                   44560:         if (file_exists($path) && is_readable($path)) {
                   44561:             return true;
                   44562:         }
                   44563: 
                   44564:         $fp = @fopen($path, 'r', true);
                   44565:         if ($fp) {
                   44566:             fclose($fp);
                   44567:             return true;
                   44568:         }
                   44569: 
                   44570:         return false;
                   44571:     }
                   44572: 
                   44573:     /**
                   44574:      * @param PEAR_Config
                   44575:      */
                   44576:     function setConfig(&$config)
                   44577:     {
                   44578:     }
                   44579: 
                   44580:     /**
                   44581:      * This can be overridden to allow session-based temporary file management
                   44582:      *
                   44583:      * By default, all files are deleted at the end of a session.  The web installer
                   44584:      * needs to be able to sustain a list over many sessions in order to support
                   44585:      * user interaction with install scripts
                   44586:      */
                   44587:     function addTempFile($file)
                   44588:     {
                   44589:         $GLOBALS['_PEAR_Common_tempfiles'][] = $file;
                   44590:     }
                   44591: 
                   44592:     /**
                   44593:      * Log an action
                   44594:      *
                   44595:      * @param string $msg the message to log
                   44596:      * @param boolean $append_crlf
                   44597:      * @return boolean true
                   44598:      * @abstract
                   44599:      */
                   44600:     function log($msg, $append_crlf = true)
                   44601:     {
                   44602:     }
                   44603: 
                   44604:     /**
                   44605:      * Run a post-installation script
                   44606:      *
                   44607:      * @param array $scripts array of post-install scripts
                   44608:      * @abstract
                   44609:      */
                   44610:     function runPostinstallScripts(&$scripts)
                   44611:     {
                   44612:     }
                   44613: 
                   44614:     /**
                   44615:      * Display human-friendly output formatted depending on the
                   44616:      * $command parameter.
                   44617:      *
                   44618:      * This should be able to handle basic output data with no command
                   44619:      * @param mixed  $data    data structure containing the information to display
                   44620:      * @param string $command command from which this method was called
                   44621:      * @abstract
                   44622:      */
                   44623:     function outputData($data, $command = '_default')
                   44624:     {
                   44625:     }
                   44626: 
                   44627:     /**
                   44628:      * Display a modal form dialog and return the given input
                   44629:      *
                   44630:      * A frontend that requires multiple requests to retrieve and process
                   44631:      * data must take these needs into account, and implement the request
                   44632:      * handling code.
                   44633:      * @param string $command  command from which this method was called
                   44634:      * @param array  $prompts  associative array. keys are the input field names
                   44635:      *                         and values are the description
                   44636:      * @param array  $types    array of input field types (text, password,
                   44637:      *                         etc.) keys have to be the same like in $prompts
                   44638:      * @param array  $defaults array of default values. again keys have
                   44639:      *                         to be the same like in $prompts.  Do not depend
                   44640:      *                         on a default value being set.
                   44641:      * @return array input sent by the user
                   44642:      * @abstract
                   44643:      */
                   44644:     function userDialog($command, $prompts, $types = array(), $defaults = array())
                   44645:     {
                   44646:     }
1.1.1.2 ! misho    44647: }PEAR-1.9.4/PEAR/Installer.php0000644000076500000240000021147511605156614014443 0ustar  helgistaff<?php
1.1       misho    44648: /**
                   44649:  * PEAR_Installer
                   44650:  *
                   44651:  * PHP versions 4 and 5
                   44652:  *
                   44653:  * @category   pear
                   44654:  * @package    PEAR
                   44655:  * @author     Stig Bakken <ssb@php.net>
                   44656:  * @author     Tomas V.V. Cox <cox@idecnet.com>
                   44657:  * @author     Martin Jansen <mj@php.net>
                   44658:  * @author     Greg Beaver <cellog@php.net>
                   44659:  * @copyright  1997-2009 The Authors
                   44660:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   44661:  * @version    CVS: $Id: Installer.php 313024 2011-07-06 19:51:24Z dufuz $
                   44662:  * @link       http://pear.php.net/package/PEAR
                   44663:  * @since      File available since Release 0.1
                   44664:  */
                   44665: 
                   44666: /**
                   44667:  * Used for installation groups in package.xml 2.0 and platform exceptions
                   44668:  */
                   44669: require_once 'OS/Guess.php';
                   44670: require_once 'PEAR/Downloader.php';
                   44671: 
                   44672: define('PEAR_INSTALLER_NOBINARY', -240);
                   44673: /**
                   44674:  * Administration class used to install PEAR packages and maintain the
                   44675:  * installed package database.
                   44676:  *
                   44677:  * @category   pear
                   44678:  * @package    PEAR
                   44679:  * @author     Stig Bakken <ssb@php.net>
                   44680:  * @author     Tomas V.V. Cox <cox@idecnet.com>
                   44681:  * @author     Martin Jansen <mj@php.net>
                   44682:  * @author     Greg Beaver <cellog@php.net>
                   44683:  * @copyright  1997-2009 The Authors
                   44684:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   44685:  * @version    Release: 1.9.4
                   44686:  * @link       http://pear.php.net/package/PEAR
                   44687:  * @since      Class available since Release 0.1
                   44688:  */
                   44689: class PEAR_Installer extends PEAR_Downloader
                   44690: {
                   44691:     // {{{ properties
                   44692: 
                   44693:     /** name of the package directory, for example Foo-1.0
                   44694:      * @var string
                   44695:      */
                   44696:     var $pkgdir;
                   44697: 
                   44698:     /** directory where PHP code files go
                   44699:      * @var string
                   44700:      */
                   44701:     var $phpdir;
                   44702: 
                   44703:     /** directory where PHP extension files go
                   44704:      * @var string
                   44705:      */
                   44706:     var $extdir;
                   44707: 
                   44708:     /** directory where documentation goes
                   44709:      * @var string
                   44710:      */
                   44711:     var $docdir;
                   44712: 
                   44713:     /** installation root directory (ala PHP's INSTALL_ROOT or
                   44714:      * automake's DESTDIR
                   44715:      * @var string
                   44716:      */
                   44717:     var $installroot = '';
                   44718: 
                   44719:     /** debug level
                   44720:      * @var int
                   44721:      */
                   44722:     var $debug = 1;
                   44723: 
                   44724:     /** temporary directory
                   44725:      * @var string
                   44726:      */
                   44727:     var $tmpdir;
                   44728: 
                   44729:     /**
                   44730:      * PEAR_Registry object used by the installer
                   44731:      * @var PEAR_Registry
                   44732:      */
                   44733:     var $registry;
                   44734: 
                   44735:     /**
                   44736:      * array of PEAR_Downloader_Packages
                   44737:      * @var array
                   44738:      */
                   44739:     var $_downloadedPackages;
                   44740: 
                   44741:     /** List of file transactions queued for an install/upgrade/uninstall.
                   44742:      *
                   44743:      *  Format:
                   44744:      *    array(
                   44745:      *      0 => array("rename => array("from-file", "to-file")),
                   44746:      *      1 => array("delete" => array("file-to-delete")),
                   44747:      *      ...
                   44748:      *    )
                   44749:      *
                   44750:      * @var array
                   44751:      */
                   44752:     var $file_operations = array();
                   44753: 
                   44754:     // }}}
                   44755: 
                   44756:     // {{{ constructor
                   44757: 
                   44758:     /**
                   44759:      * PEAR_Installer constructor.
                   44760:      *
                   44761:      * @param object $ui user interface object (instance of PEAR_Frontend_*)
                   44762:      *
                   44763:      * @access public
                   44764:      */
                   44765:     function PEAR_Installer(&$ui)
                   44766:     {
                   44767:         parent::PEAR_Common();
                   44768:         $this->setFrontendObject($ui);
                   44769:         $this->debug = $this->config->get('verbose');
                   44770:     }
                   44771: 
                   44772:     function setOptions($options)
                   44773:     {
                   44774:         $this->_options = $options;
                   44775:     }
                   44776: 
                   44777:     function setConfig(&$config)
                   44778:     {
                   44779:         $this->config    = &$config;
                   44780:         $this->_registry = &$config->getRegistry();
                   44781:     }
                   44782: 
                   44783:     // }}}
                   44784: 
                   44785:     function _removeBackups($files)
                   44786:     {
                   44787:         foreach ($files as $path) {
                   44788:             $this->addFileOperation('removebackup', array($path));
                   44789:         }
                   44790:     }
                   44791: 
                   44792:     // {{{ _deletePackageFiles()
                   44793: 
                   44794:     /**
                   44795:      * Delete a package's installed files, does not remove empty directories.
                   44796:      *
                   44797:      * @param string package name
                   44798:      * @param string channel name
                   44799:      * @param bool if true, then files are backed up first
                   44800:      * @return bool TRUE on success, or a PEAR error on failure
                   44801:      * @access protected
                   44802:      */
                   44803:     function _deletePackageFiles($package, $channel = false, $backup = false)
                   44804:     {
                   44805:         if (!$channel) {
                   44806:             $channel = 'pear.php.net';
                   44807:         }
                   44808: 
                   44809:         if (!strlen($package)) {
                   44810:             return $this->raiseError("No package to uninstall given");
                   44811:         }
                   44812: 
                   44813:         if (strtolower($package) == 'pear' && $channel == 'pear.php.net') {
                   44814:             // to avoid race conditions, include all possible needed files
                   44815:             require_once 'PEAR/Task/Common.php';
                   44816:             require_once 'PEAR/Task/Replace.php';
                   44817:             require_once 'PEAR/Task/Unixeol.php';
                   44818:             require_once 'PEAR/Task/Windowseol.php';
                   44819:             require_once 'PEAR/PackageFile/v1.php';
                   44820:             require_once 'PEAR/PackageFile/v2.php';
                   44821:             require_once 'PEAR/PackageFile/Generator/v1.php';
                   44822:             require_once 'PEAR/PackageFile/Generator/v2.php';
                   44823:         }
                   44824: 
                   44825:         $filelist = $this->_registry->packageInfo($package, 'filelist', $channel);
                   44826:         if ($filelist == null) {
                   44827:             return $this->raiseError("$channel/$package not installed");
                   44828:         }
                   44829: 
                   44830:         $ret = array();
                   44831:         foreach ($filelist as $file => $props) {
                   44832:             if (empty($props['installed_as'])) {
                   44833:                 continue;
                   44834:             }
                   44835: 
                   44836:             $path = $props['installed_as'];
                   44837:             if ($backup) {
                   44838:                 $this->addFileOperation('backup', array($path));
                   44839:                 $ret[] = $path;
                   44840:             }
                   44841: 
                   44842:             $this->addFileOperation('delete', array($path));
                   44843:         }
                   44844: 
                   44845:         if ($backup) {
                   44846:             return $ret;
                   44847:         }
                   44848: 
                   44849:         return true;
                   44850:     }
                   44851: 
                   44852:     // }}}
                   44853:     // {{{ _installFile()
                   44854: 
                   44855:     /**
                   44856:      * @param string filename
                   44857:      * @param array attributes from <file> tag in package.xml
                   44858:      * @param string path to install the file in
                   44859:      * @param array options from command-line
                   44860:      * @access private
                   44861:      */
                   44862:     function _installFile($file, $atts, $tmp_path, $options)
                   44863:     {
                   44864:         // {{{ return if this file is meant for another platform
                   44865:         static $os;
                   44866:         if (!isset($this->_registry)) {
                   44867:             $this->_registry = &$this->config->getRegistry();
                   44868:         }
                   44869: 
                   44870:         if (isset($atts['platform'])) {
                   44871:             if (empty($os)) {
                   44872:                 $os = new OS_Guess();
                   44873:             }
                   44874: 
                   44875:             if (strlen($atts['platform']) && $atts['platform']{0} == '!') {
                   44876:                 $negate   = true;
                   44877:                 $platform = substr($atts['platform'], 1);
                   44878:             } else {
                   44879:                 $negate    = false;
                   44880:                 $platform = $atts['platform'];
                   44881:             }
                   44882: 
                   44883:             if ((bool) $os->matchSignature($platform) === $negate) {
                   44884:                 $this->log(3, "skipped $file (meant for $atts[platform], we are ".$os->getSignature().")");
                   44885:                 return PEAR_INSTALLER_SKIPPED;
                   44886:             }
                   44887:         }
                   44888:         // }}}
                   44889: 
                   44890:         $channel = $this->pkginfo->getChannel();
                   44891:         // {{{ assemble the destination paths
                   44892:         switch ($atts['role']) {
                   44893:             case 'src':
                   44894:             case 'extsrc':
                   44895:                 $this->source_files++;
                   44896:                 return;
                   44897:             case 'doc':
                   44898:             case 'data':
                   44899:             case 'test':
                   44900:                 $dest_dir = $this->config->get($atts['role'] . '_dir', null, $channel) .
                   44901:                             DIRECTORY_SEPARATOR . $this->pkginfo->getPackage();
                   44902:                 unset($atts['baseinstalldir']);
                   44903:                 break;
                   44904:             case 'ext':
                   44905:             case 'php':
                   44906:                 $dest_dir = $this->config->get($atts['role'] . '_dir', null, $channel);
                   44907:                 break;
                   44908:             case 'script':
                   44909:                 $dest_dir = $this->config->get('bin_dir', null, $channel);
                   44910:                 break;
                   44911:             default:
                   44912:                 return $this->raiseError("Invalid role `$atts[role]' for file $file");
                   44913:         }
                   44914: 
                   44915:         $save_destdir = $dest_dir;
                   44916:         if (!empty($atts['baseinstalldir'])) {
                   44917:             $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
                   44918:         }
                   44919: 
                   44920:         if (dirname($file) != '.' && empty($atts['install-as'])) {
                   44921:             $dest_dir .= DIRECTORY_SEPARATOR . dirname($file);
                   44922:         }
                   44923: 
                   44924:         if (empty($atts['install-as'])) {
                   44925:             $dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file);
                   44926:         } else {
                   44927:             $dest_file = $dest_dir . DIRECTORY_SEPARATOR . $atts['install-as'];
                   44928:         }
                   44929:         $orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file;
                   44930: 
                   44931:         // Clean up the DIRECTORY_SEPARATOR mess
                   44932:         $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
                   44933:         list($dest_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"),
                   44934:                                                     array(DIRECTORY_SEPARATOR,
                   44935:                                                           DIRECTORY_SEPARATOR,
                   44936:                                                           DIRECTORY_SEPARATOR),
                   44937:                                                     array($dest_file, $orig_file));
                   44938:         $final_dest_file = $installed_as = $dest_file;
                   44939:         if (isset($this->_options['packagingroot'])) {
                   44940:             $installedas_dest_dir  = dirname($final_dest_file);
                   44941:             $installedas_dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
                   44942:             $final_dest_file = $this->_prependPath($final_dest_file, $this->_options['packagingroot']);
                   44943:         } else {
                   44944:             $installedas_dest_dir  = dirname($final_dest_file);
                   44945:             $installedas_dest_file = $installedas_dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
                   44946:         }
                   44947: 
                   44948:         $dest_dir  = dirname($final_dest_file);
                   44949:         $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
                   44950:         if (preg_match('~/\.\.(/|\\z)|^\.\./~', str_replace('\\', '/', $dest_file))) {
                   44951:             return $this->raiseError("SECURITY ERROR: file $file (installed to $dest_file) contains parent directory reference ..", PEAR_INSTALLER_FAILED);
                   44952:         }
                   44953:         // }}}
                   44954: 
                   44955:         if (empty($this->_options['register-only']) &&
                   44956:               (!file_exists($dest_dir) || !is_dir($dest_dir))) {
                   44957:             if (!$this->mkDirHier($dest_dir)) {
                   44958:                 return $this->raiseError("failed to mkdir $dest_dir",
                   44959:                                          PEAR_INSTALLER_FAILED);
                   44960:             }
                   44961:             $this->log(3, "+ mkdir $dest_dir");
                   44962:         }
                   44963: 
                   44964:         // pretty much nothing happens if we are only registering the install
                   44965:         if (empty($this->_options['register-only'])) {
                   44966:             if (empty($atts['replacements'])) {
                   44967:                 if (!file_exists($orig_file)) {
                   44968:                     return $this->raiseError("file $orig_file does not exist",
                   44969:                                              PEAR_INSTALLER_FAILED);
                   44970:                 }
                   44971: 
                   44972:                 if (!@copy($orig_file, $dest_file)) {
                   44973:                     return $this->raiseError("failed to write $dest_file: $php_errormsg",
                   44974:                                              PEAR_INSTALLER_FAILED);
                   44975:                 }
                   44976: 
                   44977:                 $this->log(3, "+ cp $orig_file $dest_file");
                   44978:                 if (isset($atts['md5sum'])) {
                   44979:                     $md5sum = md5_file($dest_file);
                   44980:                 }
                   44981:             } else {
                   44982:                 // {{{ file with replacements
                   44983:                 if (!file_exists($orig_file)) {
                   44984:                     return $this->raiseError("file does not exist",
                   44985:                                              PEAR_INSTALLER_FAILED);
                   44986:                 }
                   44987: 
                   44988:                 $contents = file_get_contents($orig_file);
                   44989:                 if ($contents === false) {
                   44990:                     $contents = '';
                   44991:                 }
                   44992: 
                   44993:                 if (isset($atts['md5sum'])) {
                   44994:                     $md5sum = md5($contents);
                   44995:                 }
                   44996: 
                   44997:                 $subst_from = $subst_to = array();
                   44998:                 foreach ($atts['replacements'] as $a) {
                   44999:                     $to = '';
                   45000:                     if ($a['type'] == 'php-const') {
                   45001:                         if (preg_match('/^[a-z0-9_]+\\z/i', $a['to'])) {
                   45002:                             eval("\$to = $a[to];");
                   45003:                         } else {
                   45004:                             if (!isset($options['soft'])) {
                   45005:                                 $this->log(0, "invalid php-const replacement: $a[to]");
                   45006:                             }
                   45007:                             continue;
                   45008:                         }
                   45009:                     } elseif ($a['type'] == 'pear-config') {
                   45010:                         if ($a['to'] == 'master_server') {
                   45011:                             $chan = $this->_registry->getChannel($channel);
                   45012:                             if (!PEAR::isError($chan)) {
                   45013:                                 $to = $chan->getServer();
                   45014:                             } else {
                   45015:                                 $to = $this->config->get($a['to'], null, $channel);
                   45016:                             }
                   45017:                         } else {
                   45018:                             $to = $this->config->get($a['to'], null, $channel);
                   45019:                         }
                   45020:                         if (is_null($to)) {
                   45021:                             if (!isset($options['soft'])) {
                   45022:                                 $this->log(0, "invalid pear-config replacement: $a[to]");
                   45023:                             }
                   45024:                             continue;
                   45025:                         }
                   45026:                     } elseif ($a['type'] == 'package-info') {
                   45027:                         if ($t = $this->pkginfo->packageInfo($a['to'])) {
                   45028:                             $to = $t;
                   45029:                         } else {
                   45030:                             if (!isset($options['soft'])) {
                   45031:                                 $this->log(0, "invalid package-info replacement: $a[to]");
                   45032:                             }
                   45033:                             continue;
                   45034:                         }
                   45035:                     }
                   45036:                     if (!is_null($to)) {
                   45037:                         $subst_from[] = $a['from'];
                   45038:                         $subst_to[] = $to;
                   45039:                     }
                   45040:                 }
                   45041: 
                   45042:                 $this->log(3, "doing ".sizeof($subst_from)." substitution(s) for $final_dest_file");
                   45043:                 if (sizeof($subst_from)) {
                   45044:                     $contents = str_replace($subst_from, $subst_to, $contents);
                   45045:                 }
                   45046: 
                   45047:                 $wp = @fopen($dest_file, "wb");
                   45048:                 if (!is_resource($wp)) {
                   45049:                     return $this->raiseError("failed to create $dest_file: $php_errormsg",
                   45050:                                              PEAR_INSTALLER_FAILED);
                   45051:                 }
                   45052: 
                   45053:                 if (@fwrite($wp, $contents) === false) {
                   45054:                     return $this->raiseError("failed writing to $dest_file: $php_errormsg",
                   45055:                                              PEAR_INSTALLER_FAILED);
                   45056:                 }
                   45057: 
                   45058:                 fclose($wp);
                   45059:                 // }}}
                   45060:             }
                   45061: 
                   45062:             // {{{ check the md5
                   45063:             if (isset($md5sum)) {
                   45064:                 if (strtolower($md5sum) === strtolower($atts['md5sum'])) {
                   45065:                     $this->log(2, "md5sum ok: $final_dest_file");
                   45066:                 } else {
                   45067:                     if (empty($options['force'])) {
                   45068:                         // delete the file
                   45069:                         if (file_exists($dest_file)) {
                   45070:                             unlink($dest_file);
                   45071:                         }
                   45072: 
                   45073:                         if (!isset($options['ignore-errors'])) {
                   45074:                             return $this->raiseError("bad md5sum for file $final_dest_file",
                   45075:                                                  PEAR_INSTALLER_FAILED);
                   45076:                         }
                   45077: 
                   45078:                         if (!isset($options['soft'])) {
                   45079:                             $this->log(0, "warning : bad md5sum for file $final_dest_file");
                   45080:                         }
                   45081:                     } else {
                   45082:                         if (!isset($options['soft'])) {
                   45083:                             $this->log(0, "warning : bad md5sum for file $final_dest_file");
                   45084:                         }
                   45085:                     }
                   45086:                 }
                   45087:             }
                   45088:             // }}}
                   45089:             // {{{ set file permissions
                   45090:             if (!OS_WINDOWS) {
                   45091:                 if ($atts['role'] == 'script') {
                   45092:                     $mode = 0777 & ~(int)octdec($this->config->get('umask'));
                   45093:                     $this->log(3, "+ chmod +x $dest_file");
                   45094:                 } else {
                   45095:                     $mode = 0666 & ~(int)octdec($this->config->get('umask'));
                   45096:                 }
                   45097: 
                   45098:                 if ($atts['role'] != 'src') {
                   45099:                     $this->addFileOperation("chmod", array($mode, $dest_file));
                   45100:                     if (!@chmod($dest_file, $mode)) {
                   45101:                         if (!isset($options['soft'])) {
                   45102:                             $this->log(0, "failed to change mode of $dest_file: $php_errormsg");
                   45103:                         }
                   45104:                     }
                   45105:                 }
                   45106:             }
                   45107:             // }}}
                   45108: 
                   45109:             if ($atts['role'] == 'src') {
                   45110:                 rename($dest_file, $final_dest_file);
                   45111:                 $this->log(2, "renamed source file $dest_file to $final_dest_file");
                   45112:             } else {
                   45113:                 $this->addFileOperation("rename", array($dest_file, $final_dest_file,
                   45114:                     $atts['role'] == 'ext'));
                   45115:             }
                   45116:         }
                   45117: 
                   45118:         // Store the full path where the file was installed for easy unistall
                   45119:         if ($atts['role'] != 'script') {
                   45120:             $loc = $this->config->get($atts['role'] . '_dir');
                   45121:         } else {
                   45122:             $loc = $this->config->get('bin_dir');
                   45123:         }
                   45124: 
                   45125:         if ($atts['role'] != 'src') {
                   45126:             $this->addFileOperation("installed_as", array($file, $installed_as,
                   45127:                                     $loc,
                   45128:                                     dirname(substr($installedas_dest_file, strlen($loc)))));
                   45129:         }
                   45130: 
                   45131:         //$this->log(2, "installed: $dest_file");
                   45132:         return PEAR_INSTALLER_OK;
                   45133:     }
                   45134: 
                   45135:     // }}}
                   45136:     // {{{ _installFile2()
                   45137: 
                   45138:     /**
                   45139:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   45140:      * @param string filename
                   45141:      * @param array attributes from <file> tag in package.xml
                   45142:      * @param string path to install the file in
                   45143:      * @param array options from command-line
                   45144:      * @access private
                   45145:      */
                   45146:     function _installFile2(&$pkg, $file, &$real_atts, $tmp_path, $options)
                   45147:     {
                   45148:         $atts = $real_atts;
                   45149:         if (!isset($this->_registry)) {
                   45150:             $this->_registry = &$this->config->getRegistry();
                   45151:         }
                   45152: 
                   45153:         $channel = $pkg->getChannel();
                   45154:         // {{{ assemble the destination paths
                   45155:         if (!in_array($atts['attribs']['role'],
                   45156:               PEAR_Installer_Role::getValidRoles($pkg->getPackageType()))) {
                   45157:             return $this->raiseError('Invalid role `' . $atts['attribs']['role'] .
                   45158:                     "' for file $file");
                   45159:         }
                   45160: 
                   45161:         $role = &PEAR_Installer_Role::factory($pkg, $atts['attribs']['role'], $this->config);
                   45162:         $err  = $role->setup($this, $pkg, $atts['attribs'], $file);
                   45163:         if (PEAR::isError($err)) {
                   45164:             return $err;
                   45165:         }
                   45166: 
                   45167:         if (!$role->isInstallable()) {
                   45168:             return;
                   45169:         }
                   45170: 
                   45171:         $info = $role->processInstallation($pkg, $atts['attribs'], $file, $tmp_path);
                   45172:         if (PEAR::isError($info)) {
                   45173:             return $info;
                   45174:         }
                   45175: 
                   45176:         list($save_destdir, $dest_dir, $dest_file, $orig_file) = $info;
                   45177:         if (preg_match('~/\.\.(/|\\z)|^\.\./~', str_replace('\\', '/', $dest_file))) {
                   45178:             return $this->raiseError("SECURITY ERROR: file $file (installed to $dest_file) contains parent directory reference ..", PEAR_INSTALLER_FAILED);
                   45179:         }
                   45180: 
                   45181:         $final_dest_file = $installed_as = $dest_file;
                   45182:         if (isset($this->_options['packagingroot'])) {
                   45183:             $final_dest_file = $this->_prependPath($final_dest_file,
                   45184:                 $this->_options['packagingroot']);
                   45185:         }
                   45186: 
                   45187:         $dest_dir  = dirname($final_dest_file);
                   45188:         $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
                   45189:         // }}}
                   45190: 
                   45191:         if (empty($this->_options['register-only'])) {
                   45192:             if (!file_exists($dest_dir) || !is_dir($dest_dir)) {
                   45193:                 if (!$this->mkDirHier($dest_dir)) {
                   45194:                     return $this->raiseError("failed to mkdir $dest_dir",
                   45195:                                              PEAR_INSTALLER_FAILED);
                   45196:                 }
                   45197:                 $this->log(3, "+ mkdir $dest_dir");
                   45198:             }
                   45199:         }
                   45200: 
                   45201:         $attribs = $atts['attribs'];
                   45202:         unset($atts['attribs']);
                   45203:         // pretty much nothing happens if we are only registering the install
                   45204:         if (empty($this->_options['register-only'])) {
                   45205:             if (!count($atts)) { // no tasks
                   45206:                 if (!file_exists($orig_file)) {
                   45207:                     return $this->raiseError("file $orig_file does not exist",
                   45208:                                              PEAR_INSTALLER_FAILED);
                   45209:                 }
                   45210: 
                   45211:                 if (!@copy($orig_file, $dest_file)) {
                   45212:                     return $this->raiseError("failed to write $dest_file: $php_errormsg",
                   45213:                                              PEAR_INSTALLER_FAILED);
                   45214:                 }
                   45215: 
                   45216:                 $this->log(3, "+ cp $orig_file $dest_file");
                   45217:                 if (isset($attribs['md5sum'])) {
                   45218:                     $md5sum = md5_file($dest_file);
                   45219:                 }
                   45220:             } else { // file with tasks
                   45221:                 if (!file_exists($orig_file)) {
                   45222:                     return $this->raiseError("file $orig_file does not exist",
                   45223:                                              PEAR_INSTALLER_FAILED);
                   45224:                 }
                   45225: 
                   45226:                 $contents = file_get_contents($orig_file);
                   45227:                 if ($contents === false) {
                   45228:                     $contents = '';
                   45229:                 }
                   45230: 
                   45231:                 if (isset($attribs['md5sum'])) {
                   45232:                     $md5sum = md5($contents);
                   45233:                 }
                   45234: 
                   45235:                 foreach ($atts as $tag => $raw) {
                   45236:                     $tag = str_replace(array($pkg->getTasksNs() . ':', '-'), array('', '_'), $tag);
                   45237:                     $task = "PEAR_Task_$tag";
                   45238:                     $task = &new $task($this->config, $this, PEAR_TASK_INSTALL);
                   45239:                     if (!$task->isScript()) { // scripts are only handled after installation
                   45240:                         $task->init($raw, $attribs, $pkg->getLastInstalledVersion());
                   45241:                         $res = $task->startSession($pkg, $contents, $final_dest_file);
                   45242:                         if ($res === false) {
                   45243:                             continue; // skip this file
                   45244:                         }
                   45245: 
                   45246:                         if (PEAR::isError($res)) {
                   45247:                             return $res;
                   45248:                         }
                   45249: 
                   45250:                         $contents = $res; // save changes
                   45251:                     }
                   45252: 
                   45253:                     $wp = @fopen($dest_file, "wb");
                   45254:                     if (!is_resource($wp)) {
                   45255:                         return $this->raiseError("failed to create $dest_file: $php_errormsg",
                   45256:                                                  PEAR_INSTALLER_FAILED);
                   45257:                     }
                   45258: 
                   45259:                     if (fwrite($wp, $contents) === false) {
                   45260:                         return $this->raiseError("failed writing to $dest_file: $php_errormsg",
                   45261:                                                  PEAR_INSTALLER_FAILED);
                   45262:                     }
                   45263: 
                   45264:                     fclose($wp);
                   45265:                 }
                   45266:             }
                   45267: 
                   45268:             // {{{ check the md5
                   45269:             if (isset($md5sum)) {
                   45270:                 // Make sure the original md5 sum matches with expected
                   45271:                 if (strtolower($md5sum) === strtolower($attribs['md5sum'])) {
                   45272:                     $this->log(2, "md5sum ok: $final_dest_file");
                   45273: 
                   45274:                     if (isset($contents)) {
                   45275:                         // set md5 sum based on $content in case any tasks were run.
                   45276:                         $real_atts['attribs']['md5sum'] = md5($contents);
                   45277:                     }
                   45278:                 } else {
                   45279:                     if (empty($options['force'])) {
                   45280:                         // delete the file
                   45281:                         if (file_exists($dest_file)) {
                   45282:                             unlink($dest_file);
                   45283:                         }
                   45284: 
                   45285:                         if (!isset($options['ignore-errors'])) {
                   45286:                             return $this->raiseError("bad md5sum for file $final_dest_file",
                   45287:                                                      PEAR_INSTALLER_FAILED);
                   45288:                         }
                   45289: 
                   45290:                         if (!isset($options['soft'])) {
                   45291:                             $this->log(0, "warning : bad md5sum for file $final_dest_file");
                   45292:                         }
                   45293:                     } else {
                   45294:                         if (!isset($options['soft'])) {
                   45295:                             $this->log(0, "warning : bad md5sum for file $final_dest_file");
                   45296:                         }
                   45297:                     }
                   45298:                 }
                   45299:             } else {
                   45300:                 $real_atts['attribs']['md5sum'] = md5_file($dest_file);
                   45301:             }
                   45302: 
                   45303:             // }}}
                   45304:             // {{{ set file permissions
                   45305:             if (!OS_WINDOWS) {
                   45306:                 if ($role->isExecutable()) {
                   45307:                     $mode = 0777 & ~(int)octdec($this->config->get('umask'));
                   45308:                     $this->log(3, "+ chmod +x $dest_file");
                   45309:                 } else {
                   45310:                     $mode = 0666 & ~(int)octdec($this->config->get('umask'));
                   45311:                 }
                   45312: 
                   45313:                 if ($attribs['role'] != 'src') {
                   45314:                     $this->addFileOperation("chmod", array($mode, $dest_file));
                   45315:                     if (!@chmod($dest_file, $mode)) {
                   45316:                         if (!isset($options['soft'])) {
                   45317:                             $this->log(0, "failed to change mode of $dest_file: $php_errormsg");
                   45318:                         }
                   45319:                     }
                   45320:                 }
                   45321:             }
                   45322:             // }}}
                   45323: 
                   45324:             if ($attribs['role'] == 'src') {
                   45325:                 rename($dest_file, $final_dest_file);
                   45326:                 $this->log(2, "renamed source file $dest_file to $final_dest_file");
                   45327:             } else {
                   45328:                 $this->addFileOperation("rename", array($dest_file, $final_dest_file, $role->isExtension()));
                   45329:             }
                   45330:         }
                   45331: 
                   45332:         // Store the full path where the file was installed for easy uninstall
                   45333:         if ($attribs['role'] != 'src') {
                   45334:             $loc = $this->config->get($role->getLocationConfig(), null, $channel);
                   45335:             $this->addFileOperation('installed_as', array($file, $installed_as,
                   45336:                                 $loc,
                   45337:                                 dirname(substr($installed_as, strlen($loc)))));
                   45338:         }
                   45339: 
                   45340:         //$this->log(2, "installed: $dest_file");
                   45341:         return PEAR_INSTALLER_OK;
                   45342:     }
                   45343: 
                   45344:     // }}}
                   45345:     // {{{ addFileOperation()
                   45346: 
                   45347:     /**
                   45348:      * Add a file operation to the current file transaction.
                   45349:      *
                   45350:      * @see startFileTransaction()
                   45351:      * @param string $type This can be one of:
                   45352:      *    - rename:  rename a file ($data has 3 values)
                   45353:      *    - backup:  backup an existing file ($data has 1 value)
                   45354:      *    - removebackup:  clean up backups created during install ($data has 1 value)
                   45355:      *    - chmod:   change permissions on a file ($data has 2 values)
                   45356:      *    - delete:  delete a file ($data has 1 value)
                   45357:      *    - rmdir:   delete a directory if empty ($data has 1 value)
                   45358:      *    - installed_as: mark a file as installed ($data has 4 values).
                   45359:      * @param array $data For all file operations, this array must contain the
                   45360:      *    full path to the file or directory that is being operated on.  For
                   45361:      *    the rename command, the first parameter must be the file to rename,
                   45362:      *    the second its new name, the third whether this is a PHP extension.
                   45363:      *
                   45364:      *    The installed_as operation contains 4 elements in this order:
                   45365:      *    1. Filename as listed in the filelist element from package.xml
                   45366:      *    2. Full path to the installed file
                   45367:      *    3. Full path from the php_dir configuration variable used in this
                   45368:      *       installation
                   45369:      *    4. Relative path from the php_dir that this file is installed in
                   45370:      */
                   45371:     function addFileOperation($type, $data)
                   45372:     {
                   45373:         if (!is_array($data)) {
                   45374:             return $this->raiseError('Internal Error: $data in addFileOperation'
                   45375:                 . ' must be an array, was ' . gettype($data));
                   45376:         }
                   45377: 
                   45378:         if ($type == 'chmod') {
                   45379:             $octmode = decoct($data[0]);
                   45380:             $this->log(3, "adding to transaction: $type $octmode $data[1]");
                   45381:         } else {
                   45382:             $this->log(3, "adding to transaction: $type " . implode(" ", $data));
                   45383:         }
                   45384:         $this->file_operations[] = array($type, $data);
                   45385:     }
                   45386: 
                   45387:     // }}}
                   45388:     // {{{ startFileTransaction()
                   45389: 
                   45390:     function startFileTransaction($rollback_in_case = false)
                   45391:     {
                   45392:         if (count($this->file_operations) && $rollback_in_case) {
                   45393:             $this->rollbackFileTransaction();
                   45394:         }
                   45395:         $this->file_operations = array();
                   45396:     }
                   45397: 
                   45398:     // }}}
                   45399:     // {{{ commitFileTransaction()
                   45400: 
                   45401:     function commitFileTransaction()
                   45402:     {
                   45403:         // {{{ first, check permissions and such manually
                   45404:         $errors = array();
                   45405:         foreach ($this->file_operations as $key => $tr) {
                   45406:             list($type, $data) = $tr;
                   45407:             switch ($type) {
                   45408:                 case 'rename':
                   45409:                     if (!file_exists($data[0])) {
                   45410:                         $errors[] = "cannot rename file $data[0], doesn't exist";
                   45411:                     }
                   45412: 
                   45413:                     // check that dest dir. is writable
                   45414:                     if (!is_writable(dirname($data[1]))) {
                   45415:                         $errors[] = "permission denied ($type): $data[1]";
                   45416:                     }
                   45417:                     break;
                   45418:                 case 'chmod':
                   45419:                     // check that file is writable
                   45420:                     if (!is_writable($data[1])) {
                   45421:                         $errors[] = "permission denied ($type): $data[1] " . decoct($data[0]);
                   45422:                     }
                   45423:                     break;
                   45424:                 case 'delete':
                   45425:                     if (!file_exists($data[0])) {
                   45426:                         $this->log(2, "warning: file $data[0] doesn't exist, can't be deleted");
                   45427:                     }
                   45428:                     // check that directory is writable
                   45429:                     if (file_exists($data[0])) {
                   45430:                         if (!is_writable(dirname($data[0]))) {
                   45431:                             $errors[] = "permission denied ($type): $data[0]";
                   45432:                         } else {
                   45433:                             // make sure the file to be deleted can be opened for writing
                   45434:                             $fp = false;
                   45435:                             if (!is_dir($data[0]) &&
                   45436:                                   (!is_writable($data[0]) || !($fp = @fopen($data[0], 'a')))) {
                   45437:                                 $errors[] = "permission denied ($type): $data[0]";
                   45438:                             } elseif ($fp) {
                   45439:                                 fclose($fp);
                   45440:                             }
                   45441:                         }
                   45442: 
                   45443:                         /* Verify we are not deleting a file owned by another package
                   45444:                          * This can happen when a file moves from package A to B in
                   45445:                          * an upgrade ala http://pear.php.net/17986
                   45446:                          */
                   45447:                         $info = array(
                   45448:                             'package' => strtolower($this->pkginfo->getName()),
                   45449:                             'channel' => strtolower($this->pkginfo->getChannel()),
                   45450:                         );
                   45451:                         $result = $this->_registry->checkFileMap($data[0], $info, '1.1');
                   45452:                         if (is_array($result)) {
                   45453:                             $res = array_diff($result, $info);
                   45454:                             if (!empty($res)) {
                   45455:                                 $new = $this->_registry->getPackage($result[1], $result[0]);
                   45456:                                 $this->file_operations[$key] = false;
                   45457:                                 $this->log(3, "file $data[0] was scheduled for removal from {$this->pkginfo->getName()} but is owned by {$new->getChannel()}/{$new->getName()}, removal has been cancelled.");
                   45458:                             }
                   45459:                         }
                   45460:                     }
                   45461:                     break;
                   45462:             }
                   45463: 
                   45464:         }
                   45465:         // }}}
                   45466: 
                   45467:         $n = count($this->file_operations);
                   45468:         $this->log(2, "about to commit $n file operations for " . $this->pkginfo->getName());
                   45469: 
                   45470:         $m = count($errors);
                   45471:         if ($m > 0) {
                   45472:             foreach ($errors as $error) {
                   45473:                 if (!isset($this->_options['soft'])) {
                   45474:                     $this->log(1, $error);
                   45475:                 }
                   45476:             }
                   45477: 
                   45478:             if (!isset($this->_options['ignore-errors'])) {
                   45479:                 return false;
                   45480:             }
                   45481:         }
                   45482: 
                   45483:         $this->_dirtree = array();
                   45484:         // {{{ really commit the transaction
                   45485:         foreach ($this->file_operations as $i => $tr) {
                   45486:             if (!$tr) {
                   45487:                 // support removal of non-existing backups
                   45488:                 continue;
                   45489:             }
                   45490: 
                   45491:             list($type, $data) = $tr;
                   45492:             switch ($type) {
                   45493:                 case 'backup':
                   45494:                     if (!file_exists($data[0])) {
                   45495:                         $this->file_operations[$i] = false;
                   45496:                         break;
                   45497:                     }
                   45498: 
                   45499:                     if (!@copy($data[0], $data[0] . '.bak')) {
                   45500:                         $this->log(1, 'Could not copy ' . $data[0] . ' to ' . $data[0] .
                   45501:                             '.bak ' . $php_errormsg);
                   45502:                         return false;
                   45503:                     }
                   45504:                     $this->log(3, "+ backup $data[0] to $data[0].bak");
                   45505:                     break;
                   45506:                 case 'removebackup':
                   45507:                     if (file_exists($data[0] . '.bak') && is_writable($data[0] . '.bak')) {
                   45508:                         unlink($data[0] . '.bak');
                   45509:                         $this->log(3, "+ rm backup of $data[0] ($data[0].bak)");
                   45510:                     }
                   45511:                     break;
                   45512:                 case 'rename':
                   45513:                     $test = file_exists($data[1]) ? @unlink($data[1]) : null;
                   45514:                     if (!$test && file_exists($data[1])) {
                   45515:                         if ($data[2]) {
                   45516:                             $extra = ', this extension must be installed manually.  Rename to "' .
                   45517:                                 basename($data[1]) . '"';
                   45518:                         } else {
                   45519:                             $extra = '';
                   45520:                         }
                   45521: 
                   45522:                         if (!isset($this->_options['soft'])) {
                   45523:                             $this->log(1, 'Could not delete ' . $data[1] . ', cannot rename ' .
                   45524:                                 $data[0] . $extra);
                   45525:                         }
                   45526: 
                   45527:                         if (!isset($this->_options['ignore-errors'])) {
                   45528:                             return false;
                   45529:                         }
                   45530:                     }
                   45531: 
                   45532:                     // permissions issues with rename - copy() is far superior
                   45533:                     $perms = @fileperms($data[0]);
                   45534:                     if (!@copy($data[0], $data[1])) {
                   45535:                         $this->log(1, 'Could not rename ' . $data[0] . ' to ' . $data[1] .
                   45536:                             ' ' . $php_errormsg);
                   45537:                         return false;
                   45538:                     }
                   45539: 
                   45540:                     // copy over permissions, otherwise they are lost
                   45541:                     @chmod($data[1], $perms);
                   45542:                     @unlink($data[0]);
                   45543:                     $this->log(3, "+ mv $data[0] $data[1]");
                   45544:                     break;
                   45545:                 case 'chmod':
                   45546:                     if (!@chmod($data[1], $data[0])) {
                   45547:                         $this->log(1, 'Could not chmod ' . $data[1] . ' to ' .
                   45548:                             decoct($data[0]) . ' ' . $php_errormsg);
                   45549:                         return false;
                   45550:                     }
                   45551: 
                   45552:                     $octmode = decoct($data[0]);
                   45553:                     $this->log(3, "+ chmod $octmode $data[1]");
                   45554:                     break;
                   45555:                 case 'delete':
                   45556:                     if (file_exists($data[0])) {
                   45557:                         if (!@unlink($data[0])) {
                   45558:                             $this->log(1, 'Could not delete ' . $data[0] . ' ' .
                   45559:                                 $php_errormsg);
                   45560:                             return false;
                   45561:                         }
                   45562:                         $this->log(3, "+ rm $data[0]");
                   45563:                     }
                   45564:                     break;
                   45565:                 case 'rmdir':
                   45566:                     if (file_exists($data[0])) {
                   45567:                         do {
                   45568:                             $testme = opendir($data[0]);
                   45569:                             while (false !== ($entry = readdir($testme))) {
                   45570:                                 if ($entry == '.' || $entry == '..') {
                   45571:                                     continue;
                   45572:                                 }
                   45573:                                 closedir($testme);
                   45574:                                 break 2; // this directory is not empty and can't be
                   45575:                                          // deleted
                   45576:                             }
                   45577: 
                   45578:                             closedir($testme);
                   45579:                             if (!@rmdir($data[0])) {
                   45580:                                 $this->log(1, 'Could not rmdir ' . $data[0] . ' ' .
                   45581:                                     $php_errormsg);
                   45582:                                 return false;
                   45583:                             }
                   45584:                             $this->log(3, "+ rmdir $data[0]");
                   45585:                         } while (false);
                   45586:                     }
                   45587:                     break;
                   45588:                 case 'installed_as':
                   45589:                     $this->pkginfo->setInstalledAs($data[0], $data[1]);
                   45590:                     if (!isset($this->_dirtree[dirname($data[1])])) {
                   45591:                         $this->_dirtree[dirname($data[1])] = true;
                   45592:                         $this->pkginfo->setDirtree(dirname($data[1]));
                   45593: 
                   45594:                         while(!empty($data[3]) && dirname($data[3]) != $data[3] &&
                   45595:                                 $data[3] != '/' && $data[3] != '\\') {
                   45596:                             $this->pkginfo->setDirtree($pp =
                   45597:                                 $this->_prependPath($data[3], $data[2]));
                   45598:                             $this->_dirtree[$pp] = true;
                   45599:                             $data[3] = dirname($data[3]);
                   45600:                         }
                   45601:                     }
                   45602:                     break;
                   45603:             }
                   45604:         }
                   45605:         // }}}
                   45606:         $this->log(2, "successfully committed $n file operations");
                   45607:         $this->file_operations = array();
                   45608:         return true;
                   45609:     }
                   45610: 
                   45611:     // }}}
                   45612:     // {{{ rollbackFileTransaction()
                   45613: 
                   45614:     function rollbackFileTransaction()
                   45615:     {
                   45616:         $n = count($this->file_operations);
                   45617:         $this->log(2, "rolling back $n file operations");
                   45618:         foreach ($this->file_operations as $tr) {
                   45619:             list($type, $data) = $tr;
                   45620:             switch ($type) {
                   45621:                 case 'backup':
                   45622:                     if (file_exists($data[0] . '.bak')) {
                   45623:                         if (file_exists($data[0] && is_writable($data[0]))) {
                   45624:                             unlink($data[0]);
                   45625:                         }
                   45626:                         @copy($data[0] . '.bak', $data[0]);
                   45627:                         $this->log(3, "+ restore $data[0] from $data[0].bak");
                   45628:                     }
                   45629:                     break;
                   45630:                 case 'removebackup':
                   45631:                     if (file_exists($data[0] . '.bak') && is_writable($data[0] . '.bak')) {
                   45632:                         unlink($data[0] . '.bak');
                   45633:                         $this->log(3, "+ rm backup of $data[0] ($data[0].bak)");
                   45634:                     }
                   45635:                     break;
                   45636:                 case 'rename':
                   45637:                     @unlink($data[0]);
                   45638:                     $this->log(3, "+ rm $data[0]");
                   45639:                     break;
                   45640:                 case 'mkdir':
                   45641:                     @rmdir($data[0]);
                   45642:                     $this->log(3, "+ rmdir $data[0]");
                   45643:                     break;
                   45644:                 case 'chmod':
                   45645:                     break;
                   45646:                 case 'delete':
                   45647:                     break;
                   45648:                 case 'installed_as':
                   45649:                     $this->pkginfo->setInstalledAs($data[0], false);
                   45650:                     break;
                   45651:             }
                   45652:         }
                   45653:         $this->pkginfo->resetDirtree();
                   45654:         $this->file_operations = array();
                   45655:     }
                   45656: 
                   45657:     // }}}
                   45658:     // {{{ mkDirHier($dir)
                   45659: 
                   45660:     function mkDirHier($dir)
                   45661:     {
                   45662:         $this->addFileOperation('mkdir', array($dir));
                   45663:         return parent::mkDirHier($dir);
                   45664:     }
                   45665: 
                   45666:     // }}}
                   45667:     // {{{ download()
                   45668: 
                   45669:     /**
                   45670:      * Download any files and their dependencies, if necessary
                   45671:      *
                   45672:      * @param array a mixed list of package names, local files, or package.xml
                   45673:      * @param PEAR_Config
                   45674:      * @param array options from the command line
                   45675:      * @param array this is the array that will be populated with packages to
                   45676:      *              install.  Format of each entry:
                   45677:      *
                   45678:      * <code>
                   45679:      * array('pkg' => 'package_name', 'file' => '/path/to/local/file',
                   45680:      *    'info' => array() // parsed package.xml
                   45681:      * );
                   45682:      * </code>
                   45683:      * @param array this will be populated with any error messages
                   45684:      * @param false private recursion variable
                   45685:      * @param false private recursion variable
                   45686:      * @param false private recursion variable
                   45687:      * @deprecated in favor of PEAR_Downloader
                   45688:      */
                   45689:     function download($packages, $options, &$config, &$installpackages,
                   45690:                       &$errors, $installed = false, $willinstall = false, $state = false)
                   45691:     {
                   45692:         // trickiness: initialize here
                   45693:         parent::PEAR_Downloader($this->ui, $options, $config);
                   45694:         $ret             = parent::download($packages);
                   45695:         $errors          = $this->getErrorMsgs();
                   45696:         $installpackages = $this->getDownloadedPackages();
                   45697:         trigger_error("PEAR Warning: PEAR_Installer::download() is deprecated " .
                   45698:                       "in favor of PEAR_Downloader class", E_USER_WARNING);
                   45699:         return $ret;
                   45700:     }
                   45701: 
                   45702:     // }}}
                   45703:     // {{{ _parsePackageXml()
                   45704: 
                   45705:     function _parsePackageXml(&$descfile)
                   45706:     {
                   45707:         // Parse xml file -----------------------------------------------
                   45708:         $pkg = new PEAR_PackageFile($this->config, $this->debug);
                   45709:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   45710:         $p = &$pkg->fromAnyFile($descfile, PEAR_VALIDATE_INSTALLING);
                   45711:         PEAR::staticPopErrorHandling();
                   45712:         if (PEAR::isError($p)) {
                   45713:             if (is_array($p->getUserInfo())) {
                   45714:                 foreach ($p->getUserInfo() as $err) {
                   45715:                     $loglevel = $err['level'] == 'error' ? 0 : 1;
                   45716:                     if (!isset($this->_options['soft'])) {
                   45717:                         $this->log($loglevel, ucfirst($err['level']) . ': ' . $err['message']);
                   45718:                     }
                   45719:                 }
                   45720:             }
                   45721:             return $this->raiseError('Installation failed: invalid package file');
                   45722:         }
                   45723: 
                   45724:         $descfile = $p->getPackageFile();
                   45725:         return $p;
                   45726:     }
                   45727: 
                   45728:     // }}}
                   45729:     /**
                   45730:      * Set the list of PEAR_Downloader_Package objects to allow more sane
                   45731:      * dependency validation
                   45732:      * @param array
                   45733:      */
                   45734:     function setDownloadedPackages(&$pkgs)
                   45735:     {
                   45736:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   45737:         $err = $this->analyzeDependencies($pkgs);
                   45738:         PEAR::popErrorHandling();
                   45739:         if (PEAR::isError($err)) {
                   45740:             return $err;
                   45741:         }
                   45742:         $this->_downloadedPackages = &$pkgs;
                   45743:     }
                   45744: 
                   45745:     /**
                   45746:      * Set the list of PEAR_Downloader_Package objects to allow more sane
                   45747:      * dependency validation
                   45748:      * @param array
                   45749:      */
                   45750:     function setUninstallPackages(&$pkgs)
                   45751:     {
                   45752:         $this->_downloadedPackages = &$pkgs;
                   45753:     }
                   45754: 
                   45755:     function getInstallPackages()
                   45756:     {
                   45757:         return $this->_downloadedPackages;
                   45758:     }
                   45759: 
                   45760:     // {{{ install()
                   45761: 
                   45762:     /**
                   45763:      * Installs the files within the package file specified.
                   45764:      *
                   45765:      * @param string|PEAR_Downloader_Package $pkgfile path to the package file,
                   45766:      *        or a pre-initialized packagefile object
                   45767:      * @param array $options
                   45768:      * recognized options:
                   45769:      * - installroot   : optional prefix directory for installation
                   45770:      * - force         : force installation
                   45771:      * - register-only : update registry but don't install files
                   45772:      * - upgrade       : upgrade existing install
                   45773:      * - soft          : fail silently
                   45774:      * - nodeps        : ignore dependency conflicts/missing dependencies
                   45775:      * - alldeps       : install all dependencies
                   45776:      * - onlyreqdeps   : install only required dependencies
                   45777:      *
                   45778:      * @return array|PEAR_Error package info if successful
                   45779:      */
                   45780:     function install($pkgfile, $options = array())
                   45781:     {
                   45782:         $this->_options = $options;
                   45783:         $this->_registry = &$this->config->getRegistry();
                   45784:         if (is_object($pkgfile)) {
                   45785:             $dlpkg    = &$pkgfile;
                   45786:             $pkg      = $pkgfile->getPackageFile();
                   45787:             $pkgfile  = $pkg->getArchiveFile();
                   45788:             $descfile = $pkg->getPackageFile();
                   45789:         } else {
                   45790:             $descfile = $pkgfile;
                   45791:             $pkg      = $this->_parsePackageXml($descfile);
                   45792:             if (PEAR::isError($pkg)) {
                   45793:                 return $pkg;
                   45794:             }
                   45795:         }
                   45796: 
                   45797:         $tmpdir = dirname($descfile);
                   45798:         if (realpath($descfile) != realpath($pkgfile)) {
                   45799:             // Use the temp_dir since $descfile can contain the download dir path
                   45800:             $tmpdir = $this->config->get('temp_dir', null, 'pear.php.net');
                   45801:             $tmpdir = System::mktemp('-d -t "' . $tmpdir . '"');
                   45802: 
                   45803:             $tar = new Archive_Tar($pkgfile);
                   45804:             if (!$tar->extract($tmpdir)) {
                   45805:                 return $this->raiseError("unable to unpack $pkgfile");
                   45806:             }
                   45807:         }
                   45808: 
                   45809:         $pkgname = $pkg->getName();
                   45810:         $channel = $pkg->getChannel();
                   45811:         if (isset($this->_options['packagingroot'])) {
                   45812:             $regdir = $this->_prependPath(
                   45813:                 $this->config->get('php_dir', null, 'pear.php.net'),
                   45814:                 $this->_options['packagingroot']);
                   45815: 
                   45816:             $packrootphp_dir = $this->_prependPath(
                   45817:                 $this->config->get('php_dir', null, $channel),
                   45818:                 $this->_options['packagingroot']);
                   45819:         }
                   45820: 
                   45821:         if (isset($options['installroot'])) {
                   45822:             $this->config->setInstallRoot($options['installroot']);
                   45823:             $this->_registry = &$this->config->getRegistry();
                   45824:             $installregistry = &$this->_registry;
                   45825:             $this->installroot = ''; // all done automagically now
                   45826:             $php_dir = $this->config->get('php_dir', null, $channel);
                   45827:         } else {
                   45828:             $this->config->setInstallRoot(false);
                   45829:             $this->_registry = &$this->config->getRegistry();
                   45830:             if (isset($this->_options['packagingroot'])) {
                   45831:                 $installregistry = &new PEAR_Registry($regdir);
                   45832:                 if (!$installregistry->channelExists($channel, true)) {
                   45833:                     // we need to fake a channel-discover of this channel
                   45834:                     $chanobj = $this->_registry->getChannel($channel, true);
                   45835:                     $installregistry->addChannel($chanobj);
                   45836:                 }
                   45837:                 $php_dir = $packrootphp_dir;
                   45838:             } else {
                   45839:                 $installregistry = &$this->_registry;
                   45840:                 $php_dir = $this->config->get('php_dir', null, $channel);
                   45841:             }
                   45842:             $this->installroot = '';
                   45843:         }
                   45844: 
                   45845:         // {{{ checks to do when not in "force" mode
                   45846:         if (empty($options['force']) &&
                   45847:               (file_exists($this->config->get('php_dir')) &&
                   45848:                is_dir($this->config->get('php_dir')))) {
                   45849:             $testp = $channel == 'pear.php.net' ? $pkgname : array($channel, $pkgname);
                   45850:             $instfilelist = $pkg->getInstallationFileList(true);
                   45851:             if (PEAR::isError($instfilelist)) {
                   45852:                 return $instfilelist;
                   45853:             }
                   45854: 
                   45855:             // ensure we have the most accurate registry
                   45856:             $installregistry->flushFileMap();
                   45857:             $test = $installregistry->checkFileMap($instfilelist, $testp, '1.1');
                   45858:             if (PEAR::isError($test)) {
                   45859:                 return $test;
                   45860:             }
                   45861: 
                   45862:             if (sizeof($test)) {
                   45863:                 $pkgs = $this->getInstallPackages();
                   45864:                 $found = false;
                   45865:                 foreach ($pkgs as $param) {
                   45866:                     if ($pkg->isSubpackageOf($param)) {
                   45867:                         $found = true;
                   45868:                         break;
                   45869:                     }
                   45870:                 }
                   45871: 
                   45872:                 if ($found) {
                   45873:                     // subpackages can conflict with earlier versions of parent packages
                   45874:                     $parentreg = $installregistry->packageInfo($param->getPackage(), null, $param->getChannel());
                   45875:                     $tmp = $test;
                   45876:                     foreach ($tmp as $file => $info) {
                   45877:                         if (is_array($info)) {
                   45878:                             if (strtolower($info[1]) == strtolower($param->getPackage()) &&
                   45879:                                   strtolower($info[0]) == strtolower($param->getChannel())
                   45880:                             ) {
                   45881:                                 if (isset($parentreg['filelist'][$file])) {
                   45882:                                     unset($parentreg['filelist'][$file]);
                   45883:                                 } else{
                   45884:                                     $pos     = strpos($file, '/');
                   45885:                                     $basedir = substr($file, 0, $pos);
                   45886:                                     $file2   = substr($file, $pos + 1);
                   45887:                                     if (isset($parentreg['filelist'][$file2]['baseinstalldir'])
                   45888:                                         && $parentreg['filelist'][$file2]['baseinstalldir'] === $basedir
                   45889:                                     ) {
                   45890:                                         unset($parentreg['filelist'][$file2]);
                   45891:                                     }
                   45892:                                 }
                   45893: 
                   45894:                                 unset($test[$file]);
                   45895:                             }
                   45896:                         } else {
                   45897:                             if (strtolower($param->getChannel()) != 'pear.php.net') {
                   45898:                                 continue;
                   45899:                             }
                   45900: 
                   45901:                             if (strtolower($info) == strtolower($param->getPackage())) {
                   45902:                                 if (isset($parentreg['filelist'][$file])) {
                   45903:                                     unset($parentreg['filelist'][$file]);
                   45904:                                 } else{
                   45905:                                     $pos     = strpos($file, '/');
                   45906:                                     $basedir = substr($file, 0, $pos);
                   45907:                                     $file2   = substr($file, $pos + 1);
                   45908:                                     if (isset($parentreg['filelist'][$file2]['baseinstalldir'])
                   45909:                                         && $parentreg['filelist'][$file2]['baseinstalldir'] === $basedir
                   45910:                                     ) {
                   45911:                                         unset($parentreg['filelist'][$file2]);
                   45912:                                     }
                   45913:                                 }
                   45914: 
                   45915:                                 unset($test[$file]);
                   45916:                             }
                   45917:                         }
                   45918:                     }
                   45919: 
                   45920:                     $pfk = &new PEAR_PackageFile($this->config);
                   45921:                     $parentpkg = &$pfk->fromArray($parentreg);
                   45922:                     $installregistry->updatePackage2($parentpkg);
                   45923:                 }
                   45924: 
                   45925:                 if ($param->getChannel() == 'pecl.php.net' && isset($options['upgrade'])) {
                   45926:                     $tmp = $test;
                   45927:                     foreach ($tmp as $file => $info) {
                   45928:                         if (is_string($info)) {
                   45929:                             // pear.php.net packages are always stored as strings
                   45930:                             if (strtolower($info) == strtolower($param->getPackage())) {
                   45931:                                 // upgrading existing package
                   45932:                                 unset($test[$file]);
                   45933:                             }
                   45934:                         }
                   45935:                     }
                   45936:                 }
                   45937: 
                   45938:                 if (count($test)) {
                   45939:                     $msg = "$channel/$pkgname: conflicting files found:\n";
                   45940:                     $longest = max(array_map("strlen", array_keys($test)));
                   45941:                     $fmt = "%${longest}s (%s)\n";
                   45942:                     foreach ($test as $file => $info) {
                   45943:                         if (!is_array($info)) {
                   45944:                             $info = array('pear.php.net', $info);
                   45945:                         }
                   45946:                         $info = $info[0] . '/' . $info[1];
                   45947:                         $msg .= sprintf($fmt, $file, $info);
                   45948:                     }
                   45949: 
                   45950:                     if (!isset($options['ignore-errors'])) {
                   45951:                         return $this->raiseError($msg);
                   45952:                     }
                   45953: 
                   45954:                     if (!isset($options['soft'])) {
                   45955:                         $this->log(0, "WARNING: $msg");
                   45956:                     }
                   45957:                 }
                   45958:             }
                   45959:         }
                   45960:         // }}}
                   45961: 
                   45962:         $this->startFileTransaction();
                   45963: 
                   45964:         $usechannel = $channel;
                   45965:         if ($channel == 'pecl.php.net') {
                   45966:             $test = $installregistry->packageExists($pkgname, $channel);
                   45967:             if (!$test) {
                   45968:                 $test = $installregistry->packageExists($pkgname, 'pear.php.net');
                   45969:                 $usechannel = 'pear.php.net';
                   45970:             }
                   45971:         } else {
                   45972:             $test = $installregistry->packageExists($pkgname, $channel);
                   45973:         }
                   45974: 
                   45975:         if (empty($options['upgrade']) && empty($options['soft'])) {
                   45976:             // checks to do only when installing new packages
                   45977:             if (empty($options['force']) && $test) {
                   45978:                 return $this->raiseError("$channel/$pkgname is already installed");
                   45979:             }
                   45980:         } else {
                   45981:             // Upgrade
                   45982:             if ($test) {
                   45983:                 $v1 = $installregistry->packageInfo($pkgname, 'version', $usechannel);
                   45984:                 $v2 = $pkg->getVersion();
                   45985:                 $cmp = version_compare("$v1", "$v2", 'gt');
                   45986:                 if (empty($options['force']) && !version_compare("$v2", "$v1", 'gt')) {
                   45987:                     return $this->raiseError("upgrade to a newer version ($v2 is not newer than $v1)");
                   45988:                 }
                   45989:             }
                   45990:         }
                   45991: 
                   45992:         // Do cleanups for upgrade and install, remove old release's files first
                   45993:         if ($test && empty($options['register-only'])) {
                   45994:             // when upgrading, remove old release's files first:
                   45995:             if (PEAR::isError($err = $this->_deletePackageFiles($pkgname, $usechannel,
                   45996:                   true))) {
                   45997:                 if (!isset($options['ignore-errors'])) {
                   45998:                     return $this->raiseError($err);
                   45999:                 }
                   46000: 
                   46001:                 if (!isset($options['soft'])) {
                   46002:                     $this->log(0, 'WARNING: ' . $err->getMessage());
                   46003:                 }
                   46004:             } else {
                   46005:                 $backedup = $err;
                   46006:             }
                   46007:         }
                   46008: 
                   46009:         // {{{ Copy files to dest dir ---------------------------------------
                   46010: 
                   46011:         // info from the package it self we want to access from _installFile
                   46012:         $this->pkginfo = &$pkg;
                   46013:         // used to determine whether we should build any C code
                   46014:         $this->source_files = 0;
                   46015: 
                   46016:         $savechannel = $this->config->get('default_channel');
                   46017:         if (empty($options['register-only']) && !is_dir($php_dir)) {
                   46018:             if (PEAR::isError(System::mkdir(array('-p'), $php_dir))) {
                   46019:                 return $this->raiseError("no installation destination directory '$php_dir'\n");
                   46020:             }
                   46021:         }
                   46022: 
                   46023:         if (substr($pkgfile, -4) != '.xml') {
                   46024:             $tmpdir .= DIRECTORY_SEPARATOR . $pkgname . '-' . $pkg->getVersion();
                   46025:         }
                   46026: 
                   46027:         $this->configSet('default_channel', $channel);
                   46028:         // {{{ install files
                   46029: 
                   46030:         $ver = $pkg->getPackagexmlVersion();
                   46031:         if (version_compare($ver, '2.0', '>=')) {
                   46032:             $filelist = $pkg->getInstallationFilelist();
                   46033:         } else {
                   46034:             $filelist = $pkg->getFileList();
                   46035:         }
                   46036: 
                   46037:         if (PEAR::isError($filelist)) {
                   46038:             return $filelist;
                   46039:         }
                   46040: 
                   46041:         $p = &$installregistry->getPackage($pkgname, $channel);
                   46042:         $dirtree = (empty($options['register-only']) && $p) ? $p->getDirTree() : false;
                   46043: 
                   46044:         $pkg->resetFilelist();
                   46045:         $pkg->setLastInstalledVersion($installregistry->packageInfo($pkg->getPackage(),
                   46046:             'version', $pkg->getChannel()));
                   46047:         foreach ($filelist as $file => $atts) {
                   46048:             $this->expectError(PEAR_INSTALLER_FAILED);
                   46049:             if ($pkg->getPackagexmlVersion() == '1.0') {
                   46050:                 $res = $this->_installFile($file, $atts, $tmpdir, $options);
                   46051:             } else {
                   46052:                 $res = $this->_installFile2($pkg, $file, $atts, $tmpdir, $options);
                   46053:             }
                   46054:             $this->popExpect();
                   46055: 
                   46056:             if (PEAR::isError($res)) {
                   46057:                 if (empty($options['ignore-errors'])) {
                   46058:                     $this->rollbackFileTransaction();
                   46059:                     if ($res->getMessage() == "file does not exist") {
                   46060:                         $this->raiseError("file $file in package.xml does not exist");
                   46061:                     }
                   46062: 
                   46063:                     return $this->raiseError($res);
                   46064:                 }
                   46065: 
                   46066:                 if (!isset($options['soft'])) {
                   46067:                     $this->log(0, "Warning: " . $res->getMessage());
                   46068:                 }
                   46069:             }
                   46070: 
                   46071:             $real = isset($atts['attribs']) ? $atts['attribs'] : $atts;
                   46072:             if ($res == PEAR_INSTALLER_OK && $real['role'] != 'src') {
                   46073:                 // Register files that were installed
                   46074:                 $pkg->installedFile($file, $atts);
                   46075:             }
                   46076:         }
                   46077:         // }}}
                   46078: 
                   46079:         // {{{ compile and install source files
                   46080:         if ($this->source_files > 0 && empty($options['nobuild'])) {
                   46081:             if (PEAR::isError($err =
                   46082:                   $this->_compileSourceFiles($savechannel, $pkg))) {
                   46083:                 return $err;
                   46084:             }
                   46085:         }
                   46086:         // }}}
                   46087: 
                   46088:         if (isset($backedup)) {
                   46089:             $this->_removeBackups($backedup);
                   46090:         }
                   46091: 
                   46092:         if (!$this->commitFileTransaction()) {
                   46093:             $this->rollbackFileTransaction();
                   46094:             $this->configSet('default_channel', $savechannel);
                   46095:             return $this->raiseError("commit failed", PEAR_INSTALLER_FAILED);
                   46096:         }
                   46097:         // }}}
                   46098: 
                   46099:         $ret          = false;
                   46100:         $installphase = 'install';
                   46101:         $oldversion   = false;
                   46102:         // {{{ Register that the package is installed -----------------------
                   46103:         if (empty($options['upgrade'])) {
                   46104:             // if 'force' is used, replace the info in registry
                   46105:             $usechannel = $channel;
                   46106:             if ($channel == 'pecl.php.net') {
                   46107:                 $test = $installregistry->packageExists($pkgname, $channel);
                   46108:                 if (!$test) {
                   46109:                     $test = $installregistry->packageExists($pkgname, 'pear.php.net');
                   46110:                     $usechannel = 'pear.php.net';
                   46111:                 }
                   46112:             } else {
                   46113:                 $test = $installregistry->packageExists($pkgname, $channel);
                   46114:             }
                   46115: 
                   46116:             if (!empty($options['force']) && $test) {
                   46117:                 $oldversion = $installregistry->packageInfo($pkgname, 'version', $usechannel);
                   46118:                 $installregistry->deletePackage($pkgname, $usechannel);
                   46119:             }
                   46120:             $ret = $installregistry->addPackage2($pkg);
                   46121:         } else {
                   46122:             if ($dirtree) {
                   46123:                 $this->startFileTransaction();
                   46124:                 // attempt to delete empty directories
                   46125:                 uksort($dirtree, array($this, '_sortDirs'));
                   46126:                 foreach($dirtree as $dir => $notused) {
                   46127:                     $this->addFileOperation('rmdir', array($dir));
                   46128:                 }
                   46129:                 $this->commitFileTransaction();
                   46130:             }
                   46131: 
                   46132:             $usechannel = $channel;
                   46133:             if ($channel == 'pecl.php.net') {
                   46134:                 $test = $installregistry->packageExists($pkgname, $channel);
                   46135:                 if (!$test) {
                   46136:                     $test = $installregistry->packageExists($pkgname, 'pear.php.net');
                   46137:                     $usechannel = 'pear.php.net';
                   46138:                 }
                   46139:             } else {
                   46140:                 $test = $installregistry->packageExists($pkgname, $channel);
                   46141:             }
                   46142: 
                   46143:             // new: upgrade installs a package if it isn't installed
                   46144:             if (!$test) {
                   46145:                 $ret = $installregistry->addPackage2($pkg);
                   46146:             } else {
                   46147:                 if ($usechannel != $channel) {
                   46148:                     $installregistry->deletePackage($pkgname, $usechannel);
                   46149:                     $ret = $installregistry->addPackage2($pkg);
                   46150:                 } else {
                   46151:                     $ret = $installregistry->updatePackage2($pkg);
                   46152:                 }
                   46153:                 $installphase = 'upgrade';
                   46154:             }
                   46155:         }
                   46156: 
                   46157:         if (!$ret) {
                   46158:             $this->configSet('default_channel', $savechannel);
                   46159:             return $this->raiseError("Adding package $channel/$pkgname to registry failed");
                   46160:         }
                   46161:         // }}}
                   46162: 
                   46163:         $this->configSet('default_channel', $savechannel);
                   46164:         if (class_exists('PEAR_Task_Common')) { // this is auto-included if any tasks exist
                   46165:             if (PEAR_Task_Common::hasPostinstallTasks()) {
                   46166:                 PEAR_Task_Common::runPostinstallTasks($installphase);
                   46167:             }
                   46168:         }
                   46169: 
                   46170:         return $pkg->toArray(true);
                   46171:     }
                   46172: 
                   46173:     // }}}
                   46174: 
                   46175:     // {{{ _compileSourceFiles()
                   46176:     /**
                   46177:      * @param string
                   46178:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   46179:      */
                   46180:     function _compileSourceFiles($savechannel, &$filelist)
                   46181:     {
                   46182:         require_once 'PEAR/Builder.php';
                   46183:         $this->log(1, "$this->source_files source files, building");
                   46184:         $bob = &new PEAR_Builder($this->ui);
                   46185:         $bob->debug = $this->debug;
                   46186:         $built = $bob->build($filelist, array(&$this, '_buildCallback'));
                   46187:         if (PEAR::isError($built)) {
                   46188:             $this->rollbackFileTransaction();
                   46189:             $this->configSet('default_channel', $savechannel);
                   46190:             return $built;
                   46191:         }
                   46192: 
                   46193:         $this->log(1, "\nBuild process completed successfully");
                   46194:         foreach ($built as $ext) {
                   46195:             $bn = basename($ext['file']);
                   46196:             list($_ext_name, $_ext_suff) = explode('.', $bn);
                   46197:             if ($_ext_suff == '.so' || $_ext_suff == '.dll') {
                   46198:                 if (extension_loaded($_ext_name)) {
                   46199:                     $this->raiseError("Extension '$_ext_name' already loaded. " .
                   46200:                                       'Please unload it in your php.ini file ' .
                   46201:                                       'prior to install or upgrade');
                   46202:                 }
                   46203:                 $role = 'ext';
                   46204:             } else {
                   46205:                 $role = 'src';
                   46206:             }
                   46207: 
                   46208:             $dest = $ext['dest'];
                   46209:             $packagingroot = '';
                   46210:             if (isset($this->_options['packagingroot'])) {
                   46211:                 $packagingroot = $this->_options['packagingroot'];
                   46212:             }
                   46213: 
                   46214:             $copyto = $this->_prependPath($dest, $packagingroot);
                   46215:             $extra  = $copyto != $dest ? " as '$copyto'" : '';
                   46216:             $this->log(1, "Installing '$dest'$extra");
                   46217: 
                   46218:             $copydir = dirname($copyto);
                   46219:             // pretty much nothing happens if we are only registering the install
                   46220:             if (empty($this->_options['register-only'])) {
                   46221:                 if (!file_exists($copydir) || !is_dir($copydir)) {
                   46222:                     if (!$this->mkDirHier($copydir)) {
                   46223:                         return $this->raiseError("failed to mkdir $copydir",
                   46224:                             PEAR_INSTALLER_FAILED);
                   46225:                     }
                   46226: 
                   46227:                     $this->log(3, "+ mkdir $copydir");
                   46228:                 }
                   46229: 
                   46230:                 if (!@copy($ext['file'], $copyto)) {
                   46231:                     return $this->raiseError("failed to write $copyto ($php_errormsg)", PEAR_INSTALLER_FAILED);
                   46232:                 }
                   46233: 
                   46234:                 $this->log(3, "+ cp $ext[file] $copyto");
                   46235:                 $this->addFileOperation('rename', array($ext['file'], $copyto));
                   46236:                 if (!OS_WINDOWS) {
                   46237:                     $mode = 0666 & ~(int)octdec($this->config->get('umask'));
                   46238:                     $this->addFileOperation('chmod', array($mode, $copyto));
                   46239:                     if (!@chmod($copyto, $mode)) {
                   46240:                         $this->log(0, "failed to change mode of $copyto ($php_errormsg)");
                   46241:                     }
                   46242:                 }
                   46243:             }
                   46244: 
                   46245: 
                   46246:             $data = array(
                   46247:                 'role'         => $role,
                   46248:                 'name'         => $bn,
                   46249:                 'installed_as' => $dest,
                   46250:                 'php_api'      => $ext['php_api'],
                   46251:                 'zend_mod_api' => $ext['zend_mod_api'],
                   46252:                 'zend_ext_api' => $ext['zend_ext_api'],
                   46253:             );
                   46254: 
                   46255:             if ($filelist->getPackageXmlVersion() == '1.0') {
                   46256:                 $filelist->installedFile($bn, $data);
                   46257:             } else {
                   46258:                 $filelist->installedFile($bn, array('attribs' => $data));
                   46259:             }
                   46260:         }
                   46261:     }
                   46262: 
                   46263:     // }}}
                   46264:     function &getUninstallPackages()
                   46265:     {
                   46266:         return $this->_downloadedPackages;
                   46267:     }
                   46268:     // {{{ uninstall()
                   46269: 
                   46270:     /**
                   46271:      * Uninstall a package
                   46272:      *
                   46273:      * This method removes all files installed by the application, and then
                   46274:      * removes any empty directories.
                   46275:      * @param string package name
                   46276:      * @param array Command-line options.  Possibilities include:
                   46277:      *
                   46278:      *              - installroot: base installation dir, if not the default
                   46279:      *              - register-only : update registry but don't remove files
                   46280:      *              - nodeps: do not process dependencies of other packages to ensure
                   46281:      *                        uninstallation does not break things
                   46282:      */
                   46283:     function uninstall($package, $options = array())
                   46284:     {
                   46285:         $installRoot = isset($options['installroot']) ? $options['installroot'] : '';
                   46286:         $this->config->setInstallRoot($installRoot);
                   46287: 
                   46288:         $this->installroot = '';
                   46289:         $this->_registry = &$this->config->getRegistry();
                   46290:         if (is_object($package)) {
                   46291:             $channel = $package->getChannel();
                   46292:             $pkg     = $package;
                   46293:             $package = $pkg->getPackage();
                   46294:         } else {
                   46295:             $pkg = false;
                   46296:             $info = $this->_registry->parsePackageName($package,
                   46297:                 $this->config->get('default_channel'));
                   46298:             $channel = $info['channel'];
                   46299:             $package = $info['package'];
                   46300:         }
                   46301: 
                   46302:         $savechannel = $this->config->get('default_channel');
                   46303:         $this->configSet('default_channel', $channel);
                   46304:         if (!is_object($pkg)) {
                   46305:             $pkg = $this->_registry->getPackage($package, $channel);
                   46306:         }
                   46307: 
                   46308:         if (!$pkg) {
                   46309:             $this->configSet('default_channel', $savechannel);
                   46310:             return $this->raiseError($this->_registry->parsedPackageNameToString(
                   46311:                 array(
                   46312:                     'channel' => $channel,
                   46313:                     'package' => $package
                   46314:                 ), true) . ' not installed');
                   46315:         }
                   46316: 
                   46317:         if ($pkg->getInstalledBinary()) {
                   46318:             // this is just an alias for a binary package
                   46319:             return $this->_registry->deletePackage($package, $channel);
                   46320:         }
                   46321: 
                   46322:         $filelist = $pkg->getFilelist();
                   46323:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   46324:         if (!class_exists('PEAR_Dependency2')) {
                   46325:             require_once 'PEAR/Dependency2.php';
                   46326:         }
                   46327: 
                   46328:         $depchecker = &new PEAR_Dependency2($this->config, $options,
                   46329:             array('channel' => $channel, 'package' => $package),
                   46330:             PEAR_VALIDATE_UNINSTALLING);
                   46331:         $e = $depchecker->validatePackageUninstall($this);
                   46332:         PEAR::staticPopErrorHandling();
                   46333:         if (PEAR::isError($e)) {
                   46334:             if (!isset($options['ignore-errors'])) {
                   46335:                 return $this->raiseError($e);
                   46336:             }
                   46337: 
                   46338:             if (!isset($options['soft'])) {
                   46339:                 $this->log(0, 'WARNING: ' . $e->getMessage());
                   46340:             }
                   46341:         } elseif (is_array($e)) {
                   46342:             if (!isset($options['soft'])) {
                   46343:                 $this->log(0, $e[0]);
                   46344:             }
                   46345:         }
                   46346: 
                   46347:         $this->pkginfo = &$pkg;
                   46348:         // pretty much nothing happens if we are only registering the uninstall
                   46349:         if (empty($options['register-only'])) {
                   46350:             // {{{ Delete the files
                   46351:             $this->startFileTransaction();
                   46352:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   46353:             if (PEAR::isError($err = $this->_deletePackageFiles($package, $channel))) {
                   46354:                 PEAR::popErrorHandling();
                   46355:                 $this->rollbackFileTransaction();
                   46356:                 $this->configSet('default_channel', $savechannel);
                   46357:                 if (!isset($options['ignore-errors'])) {
                   46358:                     return $this->raiseError($err);
                   46359:                 }
                   46360: 
                   46361:                 if (!isset($options['soft'])) {
                   46362:                     $this->log(0, 'WARNING: ' . $err->getMessage());
                   46363:                 }
                   46364:             } else {
                   46365:                 PEAR::popErrorHandling();
                   46366:             }
                   46367: 
                   46368:             if (!$this->commitFileTransaction()) {
                   46369:                 $this->rollbackFileTransaction();
                   46370:                 if (!isset($options['ignore-errors'])) {
                   46371:                     return $this->raiseError("uninstall failed");
                   46372:                 }
                   46373: 
                   46374:                 if (!isset($options['soft'])) {
                   46375:                     $this->log(0, 'WARNING: uninstall failed');
                   46376:                 }
                   46377:             } else {
                   46378:                 $this->startFileTransaction();
                   46379:                 $dirtree = $pkg->getDirTree();
                   46380:                 if ($dirtree === false) {
                   46381:                     $this->configSet('default_channel', $savechannel);
                   46382:                     return $this->_registry->deletePackage($package, $channel);
                   46383:                 }
                   46384: 
                   46385:                 // attempt to delete empty directories
                   46386:                 uksort($dirtree, array($this, '_sortDirs'));
                   46387:                 foreach($dirtree as $dir => $notused) {
                   46388:                     $this->addFileOperation('rmdir', array($dir));
                   46389:                 }
                   46390: 
                   46391:                 if (!$this->commitFileTransaction()) {
                   46392:                     $this->rollbackFileTransaction();
                   46393:                     if (!isset($options['ignore-errors'])) {
                   46394:                         return $this->raiseError("uninstall failed");
                   46395:                     }
                   46396: 
                   46397:                     if (!isset($options['soft'])) {
                   46398:                         $this->log(0, 'WARNING: uninstall failed');
                   46399:                     }
                   46400:                 }
                   46401:             }
                   46402:             // }}}
                   46403:         }
                   46404: 
                   46405:         $this->configSet('default_channel', $savechannel);
                   46406:         // Register that the package is no longer installed
                   46407:         return $this->_registry->deletePackage($package, $channel);
                   46408:     }
                   46409: 
                   46410:     /**
                   46411:      * Sort a list of arrays of array(downloaded packagefilename) by dependency.
                   46412:      *
                   46413:      * It also removes duplicate dependencies
                   46414:      * @param array an array of PEAR_PackageFile_v[1/2] objects
                   46415:      * @return array|PEAR_Error array of array(packagefilename, package.xml contents)
                   46416:      */
                   46417:     function sortPackagesForUninstall(&$packages)
                   46418:     {
                   46419:         $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->config);
                   46420:         if (PEAR::isError($this->_dependencyDB)) {
                   46421:             return $this->_dependencyDB;
                   46422:         }
                   46423:         usort($packages, array(&$this, '_sortUninstall'));
                   46424:     }
                   46425: 
                   46426:     function _sortUninstall($a, $b)
                   46427:     {
                   46428:         if (!$a->getDeps() && !$b->getDeps()) {
                   46429:             return 0; // neither package has dependencies, order is insignificant
                   46430:         }
                   46431:         if ($a->getDeps() && !$b->getDeps()) {
                   46432:             return -1; // $a must be installed after $b because $a has dependencies
                   46433:         }
                   46434:         if (!$a->getDeps() && $b->getDeps()) {
                   46435:             return 1; // $b must be installed after $a because $b has dependencies
                   46436:         }
                   46437:         // both packages have dependencies
                   46438:         if ($this->_dependencyDB->dependsOn($a, $b)) {
                   46439:             return -1;
                   46440:         }
                   46441:         if ($this->_dependencyDB->dependsOn($b, $a)) {
                   46442:             return 1;
                   46443:         }
                   46444:         return 0;
                   46445:     }
                   46446: 
                   46447:     // }}}
                   46448:     // {{{ _sortDirs()
                   46449:     function _sortDirs($a, $b)
                   46450:     {
                   46451:         if (strnatcmp($a, $b) == -1) return 1;
                   46452:         if (strnatcmp($a, $b) == 1) return -1;
                   46453:         return 0;
                   46454:     }
                   46455: 
                   46456:     // }}}
                   46457: 
                   46458:     // {{{ _buildCallback()
                   46459: 
                   46460:     function _buildCallback($what, $data)
                   46461:     {
                   46462:         if (($what == 'cmdoutput' && $this->debug > 1) ||
                   46463:             ($what == 'output' && $this->debug > 0)) {
                   46464:             $this->ui->outputData(rtrim($data), 'build');
                   46465:         }
                   46466:     }
                   46467: 
                   46468:     // }}}
1.1.1.2 ! misho    46469: }PEAR-1.9.4/PEAR/PackageFile.php0000644000076500000240000003705511605156614014641 0ustar  helgistaff<?php
1.1       misho    46470: /**
                   46471:  * PEAR_PackageFile, package.xml parsing utility class
                   46472:  *
                   46473:  * PHP versions 4 and 5
                   46474:  *
                   46475:  * @category   pear
                   46476:  * @package    PEAR
                   46477:  * @author     Greg Beaver <cellog@php.net>
                   46478:  * @copyright  1997-2009 The Authors
                   46479:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   46480:  * @version    CVS: $Id: PackageFile.php 313024 2011-07-06 19:51:24Z dufuz $
                   46481:  * @link       http://pear.php.net/package/PEAR
                   46482:  * @since      File available since Release 1.4.0a1
                   46483:  */
                   46484: 
                   46485: /**
                   46486:  * needed for PEAR_VALIDATE_* constants
                   46487:  */
                   46488: require_once 'PEAR/Validate.php';
                   46489: /**
                   46490:  * Error code if the package.xml <package> tag does not contain a valid version
                   46491:  */
                   46492: define('PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION', 1);
                   46493: /**
                   46494:  * Error code if the package.xml <package> tag version is not supported (version 1.0 and 1.1 are the only supported versions,
                   46495:  * currently
                   46496:  */
                   46497: define('PEAR_PACKAGEFILE_ERROR_INVALID_PACKAGEVERSION', 2);
                   46498: /**
                   46499:  * Abstraction for the package.xml package description file
                   46500:  *
                   46501:  * @category   pear
                   46502:  * @package    PEAR
                   46503:  * @author     Greg Beaver <cellog@php.net>
                   46504:  * @copyright  1997-2009 The Authors
                   46505:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   46506:  * @version    Release: 1.9.4
                   46507:  * @link       http://pear.php.net/package/PEAR
                   46508:  * @since      Class available since Release 1.4.0a1
                   46509:  */
                   46510: class PEAR_PackageFile
                   46511: {
                   46512:     /**
                   46513:      * @var PEAR_Config
                   46514:      */
                   46515:     var $_config;
                   46516:     var $_debug;
                   46517: 
                   46518:     var $_logger = false;
                   46519:     /**
                   46520:      * @var boolean
                   46521:      */
                   46522:     var $_rawReturn = false;
                   46523: 
                   46524:     /**
                   46525:      * helper for extracting Archive_Tar errors
                   46526:      * @var array
                   46527:      * @access private
                   46528:      */
                   46529:     var $_extractErrors = array();
                   46530: 
                   46531:     /**
                   46532:      *
                   46533:      * @param   PEAR_Config $config
                   46534:      * @param   ?   $debug
                   46535:      * @param   string @tmpdir Optional temporary directory for uncompressing
                   46536:      *          files
                   46537:      */
                   46538:     function PEAR_PackageFile(&$config, $debug = false)
                   46539:     {
                   46540:         $this->_config = $config;
                   46541:         $this->_debug = $debug;
                   46542:     }
                   46543: 
                   46544:     /**
                   46545:      * Turn off validation - return a parsed package.xml without checking it
                   46546:      *
                   46547:      * This is used by the package-validate command
                   46548:      */
                   46549:     function rawReturn()
                   46550:     {
                   46551:         $this->_rawReturn = true;
                   46552:     }
                   46553: 
                   46554:     function setLogger(&$l)
                   46555:     {
                   46556:         $this->_logger = &$l;
                   46557:     }
                   46558: 
                   46559:     /**
                   46560:      * Create a PEAR_PackageFile_Parser_v* of a given version.
                   46561:      * @param   int $version
                   46562:      * @return  PEAR_PackageFile_Parser_v1|PEAR_PackageFile_Parser_v1
                   46563:      */
                   46564:     function &parserFactory($version)
                   46565:     {
                   46566:         if (!in_array($version{0}, array('1', '2'))) {
                   46567:             $a = false;
                   46568:             return $a;
                   46569:         }
                   46570: 
                   46571:         include_once 'PEAR/PackageFile/Parser/v' . $version{0} . '.php';
                   46572:         $version = $version{0};
                   46573:         $class = "PEAR_PackageFile_Parser_v$version";
                   46574:         $a = new $class;
                   46575:         return $a;
                   46576:     }
                   46577: 
                   46578:     /**
                   46579:      * For simpler unit-testing
                   46580:      * @return string
                   46581:      */
                   46582:     function getClassPrefix()
                   46583:     {
                   46584:         return 'PEAR_PackageFile_v';
                   46585:     }
                   46586: 
                   46587:     /**
                   46588:      * Create a PEAR_PackageFile_v* of a given version.
                   46589:      * @param   int $version
                   46590:      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v1
                   46591:      */
                   46592:     function &factory($version)
                   46593:     {
                   46594:         if (!in_array($version{0}, array('1', '2'))) {
                   46595:             $a = false;
                   46596:             return $a;
                   46597:         }
                   46598: 
                   46599:         include_once 'PEAR/PackageFile/v' . $version{0} . '.php';
                   46600:         $version = $version{0};
                   46601:         $class = $this->getClassPrefix() . $version;
                   46602:         $a = new $class;
                   46603:         return $a;
                   46604:     }
                   46605: 
                   46606:     /**
                   46607:      * Create a PEAR_PackageFile_v* from its toArray() method
                   46608:      *
                   46609:      * WARNING: no validation is performed, the array is assumed to be valid,
                   46610:      * always parse from xml if you want validation.
                   46611:      * @param   array $arr
                   46612:      * @return PEAR_PackageFileManager_v1|PEAR_PackageFileManager_v2
                   46613:      * @uses    factory() to construct the returned object.
                   46614:      */
                   46615:     function &fromArray($arr)
                   46616:     {
                   46617:         if (isset($arr['xsdversion'])) {
                   46618:             $obj = &$this->factory($arr['xsdversion']);
                   46619:             if ($this->_logger) {
                   46620:                 $obj->setLogger($this->_logger);
                   46621:             }
                   46622: 
                   46623:             $obj->setConfig($this->_config);
                   46624:             $obj->fromArray($arr);
                   46625:             return $obj;
                   46626:         }
                   46627: 
                   46628:         if (isset($arr['package']['attribs']['version'])) {
                   46629:             $obj = &$this->factory($arr['package']['attribs']['version']);
                   46630:         } else {
                   46631:             $obj = &$this->factory('1.0');
                   46632:         }
                   46633: 
                   46634:         if ($this->_logger) {
                   46635:             $obj->setLogger($this->_logger);
                   46636:         }
                   46637: 
                   46638:         $obj->setConfig($this->_config);
                   46639:         $obj->fromArray($arr);
                   46640:         return $obj;
                   46641:     }
                   46642: 
                   46643:     /**
                   46644:      * Create a PEAR_PackageFile_v* from an XML string.
                   46645:      * @access  public
                   46646:      * @param   string $data contents of package.xml file
                   46647:      * @param   int $state package state (one of PEAR_VALIDATE_* constants)
                   46648:      * @param   string $file full path to the package.xml file (and the files
                   46649:      *          it references)
                   46650:      * @param   string $archive optional name of the archive that the XML was
                   46651:      *          extracted from, if any
                   46652:      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   46653:      * @uses    parserFactory() to construct a parser to load the package.
                   46654:      */
                   46655:     function &fromXmlString($data, $state, $file, $archive = false)
                   46656:     {
                   46657:         if (preg_match('/<package[^>]+version=[\'"]([0-9]+\.[0-9]+)[\'"]/', $data, $packageversion)) {
                   46658:             if (!in_array($packageversion[1], array('1.0', '2.0', '2.1'))) {
                   46659:                 return PEAR::raiseError('package.xml version "' . $packageversion[1] .
                   46660:                     '" is not supported, only 1.0, 2.0, and 2.1 are supported.');
                   46661:             }
                   46662: 
                   46663:             $object = &$this->parserFactory($packageversion[1]);
                   46664:             if ($this->_logger) {
                   46665:                 $object->setLogger($this->_logger);
                   46666:             }
                   46667: 
                   46668:             $object->setConfig($this->_config);
                   46669:             $pf = $object->parse($data, $file, $archive);
                   46670:             if (PEAR::isError($pf)) {
                   46671:                 return $pf;
                   46672:             }
                   46673: 
                   46674:             if ($this->_rawReturn) {
                   46675:                 return $pf;
                   46676:             }
                   46677: 
                   46678:             if (!$pf->validate($state)) {;
                   46679:                 if ($this->_config->get('verbose') > 0
                   46680:                     && $this->_logger && $pf->getValidationWarnings(false)
                   46681:                 ) {
                   46682:                     foreach ($pf->getValidationWarnings(false) as $warning) {
                   46683:                         $this->_logger->log(0, 'ERROR: ' . $warning['message']);
                   46684:                     }
                   46685:                 }
                   46686: 
                   46687:                 $a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed',
                   46688:                     2, null, null, $pf->getValidationWarnings());
                   46689:                 return $a;
                   46690:             }
                   46691: 
                   46692:             if ($this->_logger && $pf->getValidationWarnings(false)) {
                   46693:                 foreach ($pf->getValidationWarnings() as $warning) {
                   46694:                     $this->_logger->log(0, 'WARNING: ' . $warning['message']);
                   46695:                 }
                   46696:             }
                   46697: 
                   46698:             if (method_exists($pf, 'flattenFilelist')) {
                   46699:                 $pf->flattenFilelist(); // for v2
                   46700:             }
                   46701: 
                   46702:             return $pf;
                   46703:         } elseif (preg_match('/<package[^>]+version=[\'"]([^"\']+)[\'"]/', $data, $packageversion)) {
                   46704:             $a = PEAR::raiseError('package.xml file "' . $file .
                   46705:                 '" has unsupported package.xml <package> version "' . $packageversion[1] . '"');
                   46706:             return $a;
                   46707:         } else {
                   46708:             if (!class_exists('PEAR_ErrorStack')) {
                   46709:                 require_once 'PEAR/ErrorStack.php';
                   46710:             }
                   46711: 
                   46712:             PEAR_ErrorStack::staticPush('PEAR_PackageFile',
                   46713:                 PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION,
                   46714:                 'warning', array('xml' => $data), 'package.xml "' . $file .
                   46715:                     '" has no package.xml <package> version');
                   46716:             $object = &$this->parserFactory('1.0');
                   46717:             $object->setConfig($this->_config);
                   46718:             $pf = $object->parse($data, $file, $archive);
                   46719:             if (PEAR::isError($pf)) {
                   46720:                 return $pf;
                   46721:             }
                   46722: 
                   46723:             if ($this->_rawReturn) {
                   46724:                 return $pf;
                   46725:             }
                   46726: 
                   46727:             if (!$pf->validate($state)) {
                   46728:                 $a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed',
                   46729:                     2, null, null, $pf->getValidationWarnings());
                   46730:                 return $a;
                   46731:             }
                   46732: 
                   46733:             if ($this->_logger && $pf->getValidationWarnings(false)) {
                   46734:                 foreach ($pf->getValidationWarnings() as $warning) {
                   46735:                     $this->_logger->log(0, 'WARNING: ' . $warning['message']);
                   46736:                 }
                   46737:             }
                   46738: 
                   46739:             if (method_exists($pf, 'flattenFilelist')) {
                   46740:                 $pf->flattenFilelist(); // for v2
                   46741:             }
                   46742: 
                   46743:             return $pf;
                   46744:         }
                   46745:     }
                   46746: 
                   46747:     /**
                   46748:      * Register a temporary file or directory.  When the destructor is
                   46749:      * executed, all registered temporary files and directories are
                   46750:      * removed.
                   46751:      *
                   46752:      * @param string  $file  name of file or directory
                   46753:      * @return  void
                   46754:      */
                   46755:     function addTempFile($file)
                   46756:     {
                   46757:         $GLOBALS['_PEAR_Common_tempfiles'][] = $file;
                   46758:     }
                   46759: 
                   46760:     /**
                   46761:      * Create a PEAR_PackageFile_v* from a compresed Tar or Tgz file.
                   46762:      * @access  public
                   46763:      * @param string contents of package.xml file
                   46764:      * @param int package state (one of PEAR_VALIDATE_* constants)
                   46765:      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   46766:      * @using   Archive_Tar to extract the files
                   46767:      * @using   fromPackageFile() to load the package after the package.xml
                   46768:      *          file is extracted.
                   46769:      */
                   46770:     function &fromTgzFile($file, $state)
                   46771:     {
                   46772:         if (!class_exists('Archive_Tar')) {
                   46773:             require_once 'Archive/Tar.php';
                   46774:         }
                   46775: 
                   46776:         $tar = new Archive_Tar($file);
                   46777:         if ($this->_debug <= 1) {
                   46778:             $tar->pushErrorHandling(PEAR_ERROR_RETURN);
                   46779:         }
                   46780: 
                   46781:         $content = $tar->listContent();
                   46782:         if ($this->_debug <= 1) {
                   46783:             $tar->popErrorHandling();
                   46784:         }
                   46785: 
                   46786:         if (!is_array($content)) {
                   46787:             if (is_string($file) && strlen($file < 255) &&
                   46788:                   (!file_exists($file) || !@is_file($file))) {
                   46789:                 $ret = PEAR::raiseError("could not open file \"$file\"");
                   46790:                 return $ret;
                   46791:             }
                   46792: 
                   46793:             $file = realpath($file);
                   46794:             $ret = PEAR::raiseError("Could not get contents of package \"$file\"".
                   46795:                                      '. Invalid tgz file.');
                   46796:             return $ret;
                   46797:         }
                   46798: 
                   46799:         if (!count($content) && !@is_file($file)) {
                   46800:             $ret = PEAR::raiseError("could not open file \"$file\"");
                   46801:             return $ret;
                   46802:         }
                   46803: 
                   46804:         $xml      = null;
                   46805:         $origfile = $file;
                   46806:         foreach ($content as $file) {
                   46807:             $name = $file['filename'];
                   46808:             if ($name == 'package2.xml') { // allow a .tgz to distribute both versions
                   46809:                 $xml = $name;
                   46810:                 break;
                   46811:             }
                   46812: 
                   46813:             if ($name == 'package.xml') {
                   46814:                 $xml = $name;
                   46815:                 break;
                   46816:             } elseif (preg_match('/package.xml$/', $name, $match)) {
                   46817:                 $xml = $name;
                   46818:                 break;
                   46819:             }
                   46820:         }
                   46821: 
                   46822:         $tmpdir = System::mktemp('-t "' . $this->_config->get('temp_dir') . '" -d pear');
                   46823:         if ($tmpdir === false) {
                   46824:             $ret = PEAR::raiseError("there was a problem with getting the configured temp directory");
                   46825:             return $ret;
                   46826:         }
                   46827: 
                   46828:         PEAR_PackageFile::addTempFile($tmpdir);
                   46829: 
                   46830:         $this->_extractErrors();
                   46831:         PEAR::staticPushErrorHandling(PEAR_ERROR_CALLBACK, array($this, '_extractErrors'));
                   46832: 
                   46833:         if (!$xml || !$tar->extractList(array($xml), $tmpdir)) {
                   46834:             $extra = implode("\n", $this->_extractErrors());
                   46835:             if ($extra) {
                   46836:                 $extra = ' ' . $extra;
                   46837:             }
                   46838: 
                   46839:             PEAR::staticPopErrorHandling();
                   46840:             $ret = PEAR::raiseError('could not extract the package.xml file from "' .
                   46841:                 $origfile . '"' . $extra);
                   46842:             return $ret;
                   46843:         }
                   46844: 
                   46845:         PEAR::staticPopErrorHandling();
                   46846:         $ret = &PEAR_PackageFile::fromPackageFile("$tmpdir/$xml", $state, $origfile);
                   46847:         return $ret;
                   46848:     }
                   46849: 
                   46850:     /**
                   46851:      * helper callback for extracting Archive_Tar errors
                   46852:      *
                   46853:      * @param PEAR_Error|null $err
                   46854:      * @return array
                   46855:      * @access private
                   46856:      */
                   46857:     function _extractErrors($err = null)
                   46858:     {
                   46859:         static $errors = array();
                   46860:         if ($err === null) {
                   46861:             $e = $errors;
                   46862:             $errors = array();
                   46863:             return $e;
                   46864:         }
                   46865:         $errors[] = $err->getMessage();
                   46866:     }
                   46867: 
                   46868:     /**
                   46869:      * Create a PEAR_PackageFile_v* from a package.xml file.
                   46870:      *
                   46871:      * @access public
                   46872:      * @param   string  $descfile  name of package xml file
                   46873:      * @param   int     $state package state (one of PEAR_VALIDATE_* constants)
                   46874:      * @param   string|false $archive name of the archive this package.xml came
                   46875:      *          from, if any
                   46876:      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   46877:      * @uses    PEAR_PackageFile::fromXmlString to create the oject after the
                   46878:      *          XML is loaded from the package.xml file.
                   46879:      */
                   46880:     function &fromPackageFile($descfile, $state, $archive = false)
                   46881:     {
                   46882:         $fp = false;
                   46883:         if (is_string($descfile) && strlen($descfile) < 255 &&
                   46884:              (
                   46885:               !file_exists($descfile) || !is_file($descfile) || !is_readable($descfile)
                   46886:               || (!$fp = @fopen($descfile, 'r'))
                   46887:              )
                   46888:         ) {
                   46889:             $a = PEAR::raiseError("Unable to open $descfile");
                   46890:             return $a;
                   46891:         }
                   46892: 
                   46893:         // read the whole thing so we only get one cdata callback
                   46894:         // for each block of cdata
                   46895:         fclose($fp);
                   46896:         $data = file_get_contents($descfile);
                   46897:         $ret = &PEAR_PackageFile::fromXmlString($data, $state, $descfile, $archive);
                   46898:         return $ret;
                   46899:     }
                   46900: 
                   46901:     /**
                   46902:      * Create a PEAR_PackageFile_v* from a .tgz archive or package.xml file.
                   46903:      *
                   46904:      * This method is able to extract information about a package from a .tgz
                   46905:      * archive or from a XML package definition file.
                   46906:      *
                   46907:      * @access public
                   46908:      * @param   string  $info file name
                   46909:      * @param   int     $state package state (one of PEAR_VALIDATE_* constants)
                   46910:      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   46911:      * @uses    fromPackageFile() if the file appears to be XML
                   46912:      * @uses    fromTgzFile() to load all non-XML files
                   46913:      */
                   46914:     function &fromAnyFile($info, $state)
                   46915:     {
                   46916:         if (is_dir($info)) {
                   46917:             $dir_name = realpath($info);
                   46918:             if (file_exists($dir_name . '/package.xml')) {
                   46919:                 $info = PEAR_PackageFile::fromPackageFile($dir_name .  '/package.xml', $state);
                   46920:             } elseif (file_exists($dir_name .  '/package2.xml')) {
                   46921:                 $info = PEAR_PackageFile::fromPackageFile($dir_name .  '/package2.xml', $state);
                   46922:             } else {
                   46923:                 $info = PEAR::raiseError("No package definition found in '$info' directory");
                   46924:             }
                   46925: 
                   46926:             return $info;
                   46927:         }
                   46928: 
                   46929:         $fp = false;
                   46930:         if (is_string($info) && strlen($info) < 255 &&
                   46931:              (file_exists($info) || ($fp = @fopen($info, 'r')))
                   46932:         ) {
                   46933: 
                   46934:             if ($fp) {
                   46935:                 fclose($fp);
                   46936:             }
                   46937: 
                   46938:             $tmp = substr($info, -4);
                   46939:             if ($tmp == '.xml') {
                   46940:                 $info = &PEAR_PackageFile::fromPackageFile($info, $state);
                   46941:             } elseif ($tmp == '.tar' || $tmp == '.tgz') {
                   46942:                 $info = &PEAR_PackageFile::fromTgzFile($info, $state);
                   46943:             } else {
                   46944:                 $fp   = fopen($info, 'r');
                   46945:                 $test = fread($fp, 5);
                   46946:                 fclose($fp);
                   46947:                 if ($test == '<?xml') {
                   46948:                     $info = &PEAR_PackageFile::fromPackageFile($info, $state);
                   46949:                 } else {
                   46950:                     $info = &PEAR_PackageFile::fromTgzFile($info, $state);
                   46951:                 }
                   46952:             }
                   46953: 
                   46954:             return $info;
                   46955:         }
                   46956: 
                   46957:         $info = PEAR::raiseError("Cannot open '$info' for parsing");
                   46958:         return $info;
                   46959:     }
1.1.1.2 ! misho    46960: }PEAR-1.9.4/PEAR/Packager.php0000644000076500000240000001715111605156614014216 0ustar  helgistaff<?php
1.1       misho    46961: /**
                   46962:  * PEAR_Packager for generating releases
                   46963:  *
                   46964:  * PHP versions 4 and 5
                   46965:  *
                   46966:  * @category   pear
                   46967:  * @package    PEAR
                   46968:  * @author     Stig Bakken <ssb@php.net>
                   46969:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   46970:  * @author     Greg Beaver <cellog@php.net>
                   46971:  * @copyright  1997-2009 The Authors
                   46972:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   46973:  * @version    CVS: $Id: Packager.php 313023 2011-07-06 19:17:11Z dufuz $
                   46974:  * @link       http://pear.php.net/package/PEAR
                   46975:  * @since      File available since Release 0.1
                   46976:  */
                   46977: 
                   46978: /**
                   46979:  * base class
                   46980:  */
                   46981: require_once 'PEAR/Common.php';
                   46982: require_once 'PEAR/PackageFile.php';
                   46983: require_once 'System.php';
                   46984: 
                   46985: /**
                   46986:  * Administration class used to make a PEAR release tarball.
                   46987:  *
                   46988:  * @category   pear
                   46989:  * @package    PEAR
                   46990:  * @author     Greg Beaver <cellog@php.net>
                   46991:  * @copyright  1997-2009 The Authors
                   46992:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   46993:  * @version    Release: 1.9.4
                   46994:  * @link       http://pear.php.net/package/PEAR
                   46995:  * @since      Class available since Release 0.1
                   46996:  */
                   46997: class PEAR_Packager extends PEAR_Common
                   46998: {
                   46999:     /**
                   47000:      * @var PEAR_Registry
                   47001:      */
                   47002:     var $_registry;
                   47003: 
                   47004:     function package($pkgfile = null, $compress = true, $pkg2 = null)
                   47005:     {
                   47006:         // {{{ validate supplied package.xml file
                   47007:         if (empty($pkgfile)) {
                   47008:             $pkgfile = 'package.xml';
                   47009:         }
                   47010: 
                   47011:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   47012:         $pkg  = &new PEAR_PackageFile($this->config, $this->debug);
                   47013:         $pf   = &$pkg->fromPackageFile($pkgfile, PEAR_VALIDATE_NORMAL);
                   47014:         $main = &$pf;
                   47015:         PEAR::staticPopErrorHandling();
                   47016:         if (PEAR::isError($pf)) {
                   47017:             if (is_array($pf->getUserInfo())) {
                   47018:                 foreach ($pf->getUserInfo() as $error) {
                   47019:                     $this->log(0, 'Error: ' . $error['message']);
                   47020:                 }
                   47021:             }
                   47022: 
                   47023:             $this->log(0, $pf->getMessage());
                   47024:             return $this->raiseError("Cannot package, errors in package file");
                   47025:         }
                   47026: 
                   47027:         foreach ($pf->getValidationWarnings() as $warning) {
                   47028:             $this->log(1, 'Warning: ' . $warning['message']);
                   47029:         }
                   47030: 
                   47031:         // }}}
                   47032:         if ($pkg2) {
                   47033:             $this->log(0, 'Attempting to process the second package file');
                   47034:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
                   47035:             $pf2 = &$pkg->fromPackageFile($pkg2, PEAR_VALIDATE_NORMAL);
                   47036:             PEAR::staticPopErrorHandling();
                   47037:             if (PEAR::isError($pf2)) {
                   47038:                 if (is_array($pf2->getUserInfo())) {
                   47039:                     foreach ($pf2->getUserInfo() as $error) {
                   47040:                         $this->log(0, 'Error: ' . $error['message']);
                   47041:                     }
                   47042:                 }
                   47043:                 $this->log(0, $pf2->getMessage());
                   47044:                 return $this->raiseError("Cannot package, errors in second package file");
                   47045:             }
                   47046: 
                   47047:             foreach ($pf2->getValidationWarnings() as $warning) {
                   47048:                 $this->log(1, 'Warning: ' . $warning['message']);
                   47049:             }
                   47050: 
                   47051:             if ($pf2->getPackagexmlVersion() == '2.0' ||
                   47052:                   $pf2->getPackagexmlVersion() == '2.1'
                   47053:             ) {
                   47054:                 $main  = &$pf2;
                   47055:                 $other = &$pf;
                   47056:             } else {
                   47057:                 $main  = &$pf;
                   47058:                 $other = &$pf2;
                   47059:             }
                   47060: 
                   47061:             if ($main->getPackagexmlVersion() != '2.0' &&
                   47062:                   $main->getPackagexmlVersion() != '2.1') {
                   47063:                 return PEAR::raiseError('Error: cannot package two package.xml version 1.0, can ' .
                   47064:                     'only package together a package.xml 1.0 and package.xml 2.0');
                   47065:             }
                   47066: 
                   47067:             if ($other->getPackagexmlVersion() != '1.0') {
                   47068:                 return PEAR::raiseError('Error: cannot package two package.xml version 2.0, can ' .
                   47069:                     'only package together a package.xml 1.0 and package.xml 2.0');
                   47070:             }
                   47071:         }
                   47072: 
                   47073:         $main->setLogger($this);
                   47074:         if (!$main->validate(PEAR_VALIDATE_PACKAGING)) {
                   47075:             foreach ($main->getValidationWarnings() as $warning) {
                   47076:                 $this->log(0, 'Error: ' . $warning['message']);
                   47077:             }
                   47078:             return $this->raiseError("Cannot package, errors in package");
                   47079:         }
                   47080: 
                   47081:         foreach ($main->getValidationWarnings() as $warning) {
                   47082:             $this->log(1, 'Warning: ' . $warning['message']);
                   47083:         }
                   47084: 
                   47085:         if ($pkg2) {
                   47086:             $other->setLogger($this);
                   47087:             $a = false;
                   47088:             if (!$other->validate(PEAR_VALIDATE_NORMAL) || $a = !$main->isEquivalent($other)) {
                   47089:                 foreach ($other->getValidationWarnings() as $warning) {
                   47090:                     $this->log(0, 'Error: ' . $warning['message']);
                   47091:                 }
                   47092: 
                   47093:                 foreach ($main->getValidationWarnings() as $warning) {
                   47094:                     $this->log(0, 'Error: ' . $warning['message']);
                   47095:                 }
                   47096: 
                   47097:                 if ($a) {
                   47098:                     return $this->raiseError('The two package.xml files are not equivalent!');
                   47099:                 }
                   47100: 
                   47101:                 return $this->raiseError("Cannot package, errors in package");
                   47102:             }
                   47103: 
                   47104:             foreach ($other->getValidationWarnings() as $warning) {
                   47105:                 $this->log(1, 'Warning: ' . $warning['message']);
                   47106:             }
                   47107: 
                   47108:             $gen = &$main->getDefaultGenerator();
                   47109:             $tgzfile = $gen->toTgz2($this, $other, $compress);
                   47110:             if (PEAR::isError($tgzfile)) {
                   47111:                 return $tgzfile;
                   47112:             }
                   47113: 
                   47114:             $dest_package = basename($tgzfile);
                   47115:             $pkgdir       = dirname($pkgfile);
                   47116: 
                   47117:             // TAR the Package -------------------------------------------
                   47118:             $this->log(1, "Package $dest_package done");
                   47119:             if (file_exists("$pkgdir/CVS/Root")) {
                   47120:                 $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pf->getVersion());
                   47121:                 $cvstag = "RELEASE_$cvsversion";
                   47122:                 $this->log(1, 'Tag the released code with "pear cvstag ' .
                   47123:                     $main->getPackageFile() . '"');
                   47124:                 $this->log(1, "(or set the CVS tag $cvstag by hand)");
                   47125:             } elseif (file_exists("$pkgdir/.svn")) {
                   47126:                 $svnversion = preg_replace('/[^a-z0-9]/i', '.', $pf->getVersion());
                   47127:                 $svntag = $pf->getName() . "-$svnversion";
                   47128:                 $this->log(1, 'Tag the released code with "pear svntag ' .
                   47129:                     $main->getPackageFile() . '"');
                   47130:                 $this->log(1, "(or set the SVN tag $svntag by hand)");
                   47131:             }
                   47132:         } else { // this branch is executed for single packagefile packaging
                   47133:             $gen = &$pf->getDefaultGenerator();
                   47134:             $tgzfile = $gen->toTgz($this, $compress);
                   47135:             if (PEAR::isError($tgzfile)) {
                   47136:                 $this->log(0, $tgzfile->getMessage());
                   47137:                 return $this->raiseError("Cannot package, errors in package");
                   47138:             }
                   47139: 
                   47140:             $dest_package = basename($tgzfile);
                   47141:             $pkgdir       = dirname($pkgfile);
                   47142: 
                   47143:             // TAR the Package -------------------------------------------
                   47144:             $this->log(1, "Package $dest_package done");
                   47145:             if (file_exists("$pkgdir/CVS/Root")) {
                   47146:                 $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pf->getVersion());
                   47147:                 $cvstag = "RELEASE_$cvsversion";
                   47148:                 $this->log(1, "Tag the released code with `pear cvstag $pkgfile'");
                   47149:                 $this->log(1, "(or set the CVS tag $cvstag by hand)");
                   47150:             } elseif (file_exists("$pkgdir/.svn")) {
                   47151:                 $svnversion = preg_replace('/[^a-z0-9]/i', '.', $pf->getVersion());
                   47152:                 $svntag = $pf->getName() . "-$svnversion";
                   47153:                 $this->log(1, "Tag the released code with `pear svntag $pkgfile'");
                   47154:                 $this->log(1, "(or set the SVN tag $svntag by hand)");
                   47155:             }
                   47156:         }
                   47157: 
                   47158:         return $dest_package;
                   47159:     }
1.1.1.2 ! misho    47160: }PEAR-1.9.4/PEAR/Registry.php0000644000076500000240000022412411605156614014311 0ustar  helgistaff<?php
1.1       misho    47161: /**
                   47162:  * PEAR_Registry
                   47163:  *
                   47164:  * PHP versions 4 and 5
                   47165:  *
                   47166:  * @category   pear
                   47167:  * @package    PEAR
                   47168:  * @author     Stig Bakken <ssb@php.net>
                   47169:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   47170:  * @author     Greg Beaver <cellog@php.net>
                   47171:  * @copyright  1997-2009 The Authors
                   47172:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   47173:  * @version    CVS: $Id: Registry.php 313023 2011-07-06 19:17:11Z dufuz $
                   47174:  * @link       http://pear.php.net/package/PEAR
                   47175:  * @since      File available since Release 0.1
                   47176:  */
                   47177: 
                   47178: /**
                   47179:  * for PEAR_Error
                   47180:  */
                   47181: require_once 'PEAR.php';
                   47182: require_once 'PEAR/DependencyDB.php';
                   47183: 
                   47184: define('PEAR_REGISTRY_ERROR_LOCK',         -2);
                   47185: define('PEAR_REGISTRY_ERROR_FORMAT',       -3);
                   47186: define('PEAR_REGISTRY_ERROR_FILE',         -4);
                   47187: define('PEAR_REGISTRY_ERROR_CONFLICT',     -5);
                   47188: define('PEAR_REGISTRY_ERROR_CHANNEL_FILE', -6);
                   47189: 
                   47190: /**
                   47191:  * Administration class used to maintain the installed package database.
                   47192:  * @category   pear
                   47193:  * @package    PEAR
                   47194:  * @author     Stig Bakken <ssb@php.net>
                   47195:  * @author     Tomas V. V. Cox <cox@idecnet.com>
                   47196:  * @author     Greg Beaver <cellog@php.net>
                   47197:  * @copyright  1997-2009 The Authors
                   47198:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   47199:  * @version    Release: 1.9.4
                   47200:  * @link       http://pear.php.net/package/PEAR
                   47201:  * @since      Class available since Release 1.4.0a1
                   47202:  */
                   47203: class PEAR_Registry extends PEAR
                   47204: {
                   47205:     /**
                   47206:      * File containing all channel information.
                   47207:      * @var string
                   47208:      */
                   47209:     var $channels = '';
                   47210: 
                   47211:     /** Directory where registry files are stored.
                   47212:      * @var string
                   47213:      */
                   47214:     var $statedir = '';
                   47215: 
                   47216:     /** File where the file map is stored
                   47217:      * @var string
                   47218:      */
                   47219:     var $filemap = '';
                   47220: 
                   47221:     /** Directory where registry files for channels are stored.
                   47222:      * @var string
                   47223:      */
                   47224:     var $channelsdir = '';
                   47225: 
                   47226:     /** Name of file used for locking the registry
                   47227:      * @var string
                   47228:      */
                   47229:     var $lockfile = '';
                   47230: 
                   47231:     /** File descriptor used during locking
                   47232:      * @var resource
                   47233:      */
                   47234:     var $lock_fp = null;
                   47235: 
                   47236:     /** Mode used during locking
                   47237:      * @var int
                   47238:      */
                   47239:     var $lock_mode = 0; // XXX UNUSED
                   47240: 
                   47241:     /** Cache of package information.  Structure:
                   47242:      * array(
                   47243:      *   'package' => array('id' => ... ),
                   47244:      *   ... )
                   47245:      * @var array
                   47246:      */
                   47247:     var $pkginfo_cache = array();
                   47248: 
                   47249:     /** Cache of file map.  Structure:
                   47250:      * array( '/path/to/file' => 'package', ... )
                   47251:      * @var array
                   47252:      */
                   47253:     var $filemap_cache = array();
                   47254: 
                   47255:     /**
                   47256:      * @var false|PEAR_ChannelFile
                   47257:      */
                   47258:     var $_pearChannel;
                   47259: 
                   47260:     /**
                   47261:      * @var false|PEAR_ChannelFile
                   47262:      */
                   47263:     var $_peclChannel;
                   47264: 
                   47265:     /**
                   47266:      * @var false|PEAR_ChannelFile
                   47267:      */
                   47268:     var $_docChannel;
                   47269: 
                   47270:     /**
                   47271:      * @var PEAR_DependencyDB
                   47272:      */
                   47273:     var $_dependencyDB;
                   47274: 
                   47275:     /**
                   47276:      * @var PEAR_Config
                   47277:      */
                   47278:     var $_config;
                   47279: 
                   47280:     /**
                   47281:      * PEAR_Registry constructor.
                   47282:      *
                   47283:      * @param string (optional) PEAR install directory (for .php files)
                   47284:      * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PEAR channel, if
                   47285:      *        default values are not desired.  Only used the very first time a PEAR
                   47286:      *        repository is initialized
                   47287:      * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PECL channel, if
                   47288:      *        default values are not desired.  Only used the very first time a PEAR
                   47289:      *        repository is initialized
                   47290:      *
                   47291:      * @access public
                   47292:      */
                   47293:     function PEAR_Registry($pear_install_dir = PEAR_INSTALL_DIR, $pear_channel = false,
                   47294:                            $pecl_channel = false)
                   47295:     {
                   47296:         parent::PEAR();
                   47297:         $this->setInstallDir($pear_install_dir);
                   47298:         $this->_pearChannel = $pear_channel;
                   47299:         $this->_peclChannel = $pecl_channel;
                   47300:         $this->_config      = false;
                   47301:     }
                   47302: 
                   47303:     function setInstallDir($pear_install_dir = PEAR_INSTALL_DIR)
                   47304:     {
                   47305:         $ds = DIRECTORY_SEPARATOR;
                   47306:         $this->install_dir = $pear_install_dir;
                   47307:         $this->channelsdir = $pear_install_dir.$ds.'.channels';
                   47308:         $this->statedir    = $pear_install_dir.$ds.'.registry';
                   47309:         $this->filemap     = $pear_install_dir.$ds.'.filemap';
                   47310:         $this->lockfile    = $pear_install_dir.$ds.'.lock';
                   47311:     }
                   47312: 
                   47313:     function hasWriteAccess()
                   47314:     {
                   47315:         if (!file_exists($this->install_dir)) {
                   47316:             $dir = $this->install_dir;
                   47317:             while ($dir && $dir != '.') {
                   47318:                 $olddir = $dir;
                   47319:                 $dir    = dirname($dir);
                   47320:                 if ($dir != '.' && file_exists($dir)) {
                   47321:                     if (is_writeable($dir)) {
                   47322:                         return true;
                   47323:                     }
                   47324: 
                   47325:                     return false;
                   47326:                 }
                   47327: 
                   47328:                 if ($dir == $olddir) { // this can happen in safe mode
                   47329:                     return @is_writable($dir);
                   47330:                 }
                   47331:             }
                   47332: 
                   47333:             return false;
                   47334:         }
                   47335: 
                   47336:         return is_writeable($this->install_dir);
                   47337:     }
                   47338: 
                   47339:     function setConfig(&$config, $resetInstallDir = true)
                   47340:     {
                   47341:         $this->_config = &$config;
                   47342:         if ($resetInstallDir) {
                   47343:             $this->setInstallDir($config->get('php_dir'));
                   47344:         }
                   47345:     }
                   47346: 
                   47347:     function _initializeChannelDirs()
                   47348:     {
                   47349:         static $running = false;
                   47350:         if (!$running) {
                   47351:             $running = true;
                   47352:             $ds = DIRECTORY_SEPARATOR;
                   47353:             if (!is_dir($this->channelsdir) ||
                   47354:                   !file_exists($this->channelsdir . $ds . 'pear.php.net.reg') ||
                   47355:                   !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') ||
                   47356:                   !file_exists($this->channelsdir . $ds . 'doc.php.net.reg') ||
                   47357:                   !file_exists($this->channelsdir . $ds . '__uri.reg')) {
                   47358:                 if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
                   47359:                     $pear_channel = $this->_pearChannel;
                   47360:                     if (!is_a($pear_channel, 'PEAR_ChannelFile') || !$pear_channel->validate()) {
                   47361:                         if (!class_exists('PEAR_ChannelFile')) {
                   47362:                             require_once 'PEAR/ChannelFile.php';
                   47363:                         }
                   47364: 
                   47365:                         $pear_channel = new PEAR_ChannelFile;
                   47366:                         $pear_channel->setAlias('pear');
                   47367:                         $pear_channel->setServer('pear.php.net');
                   47368:                         $pear_channel->setSummary('PHP Extension and Application Repository');
                   47369:                         $pear_channel->setDefaultPEARProtocols();
                   47370:                         $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/');
                   47371:                         $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/');
                   47372:                         $pear_channel->setBaseURL('REST1.3', 'http://pear.php.net/rest/');
                   47373:                         //$pear_channel->setBaseURL('REST1.4', 'http://pear.php.net/rest/');
                   47374:                     } else {
                   47375:                         $pear_channel->setServer('pear.php.net');
                   47376:                         $pear_channel->setAlias('pear');
                   47377:                     }
                   47378: 
                   47379:                     $pear_channel->validate();
                   47380:                     $this->_addChannel($pear_channel);
                   47381:                 }
                   47382: 
                   47383:                 if (!file_exists($this->channelsdir . $ds . 'pecl.php.net.reg')) {
                   47384:                     $pecl_channel = $this->_peclChannel;
                   47385:                     if (!is_a($pecl_channel, 'PEAR_ChannelFile') || !$pecl_channel->validate()) {
                   47386:                         if (!class_exists('PEAR_ChannelFile')) {
                   47387:                             require_once 'PEAR/ChannelFile.php';
                   47388:                         }
                   47389: 
                   47390:                         $pecl_channel = new PEAR_ChannelFile;
                   47391:                         $pecl_channel->setAlias('pecl');
                   47392:                         $pecl_channel->setServer('pecl.php.net');
                   47393:                         $pecl_channel->setSummary('PHP Extension Community Library');
                   47394:                         $pecl_channel->setDefaultPEARProtocols();
                   47395:                         $pecl_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/');
                   47396:                         $pecl_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/');
                   47397:                         $pecl_channel->setValidationPackage('PEAR_Validator_PECL', '1.0');
                   47398:                     } else {
                   47399:                         $pecl_channel->setServer('pecl.php.net');
                   47400:                         $pecl_channel->setAlias('pecl');
                   47401:                     }
                   47402: 
                   47403:                     $pecl_channel->validate();
                   47404:                     $this->_addChannel($pecl_channel);
                   47405:                 }
                   47406: 
                   47407:                 if (!file_exists($this->channelsdir . $ds . 'doc.php.net.reg')) {
                   47408:                     $doc_channel = $this->_docChannel;
                   47409:                     if (!is_a($doc_channel, 'PEAR_ChannelFile') || !$doc_channel->validate()) {
                   47410:                         if (!class_exists('PEAR_ChannelFile')) {
                   47411:                             require_once 'PEAR/ChannelFile.php';
                   47412:                         }
                   47413: 
                   47414:                         $doc_channel = new PEAR_ChannelFile;
                   47415:                         $doc_channel->setAlias('phpdocs');
                   47416:                         $doc_channel->setServer('doc.php.net');
                   47417:                         $doc_channel->setSummary('PHP Documentation Team');
                   47418:                         $doc_channel->setDefaultPEARProtocols();
                   47419:                         $doc_channel->setBaseURL('REST1.0', 'http://doc.php.net/rest/');
                   47420:                         $doc_channel->setBaseURL('REST1.1', 'http://doc.php.net/rest/');
                   47421:                         $doc_channel->setBaseURL('REST1.3', 'http://doc.php.net/rest/');
                   47422:                     } else {
                   47423:                         $doc_channel->setServer('doc.php.net');
                   47424:                         $doc_channel->setAlias('doc');
                   47425:                     }
                   47426: 
                   47427:                     $doc_channel->validate();
                   47428:                     $this->_addChannel($doc_channel);
                   47429:                 }
                   47430: 
                   47431:                 if (!file_exists($this->channelsdir . $ds . '__uri.reg')) {
                   47432:                     if (!class_exists('PEAR_ChannelFile')) {
                   47433:                         require_once 'PEAR/ChannelFile.php';
                   47434:                     }
                   47435: 
                   47436:                     $private = new PEAR_ChannelFile;
                   47437:                     $private->setName('__uri');
                   47438:                     $private->setDefaultPEARProtocols();
                   47439:                     $private->setBaseURL('REST1.0', '****');
                   47440:                     $private->setSummary('Pseudo-channel for static packages');
                   47441:                     $this->_addChannel($private);
                   47442:                 }
                   47443:                 $this->_rebuildFileMap();
                   47444:             }
                   47445: 
                   47446:             $running = false;
                   47447:         }
                   47448:     }
                   47449: 
                   47450:     function _initializeDirs()
                   47451:     {
                   47452:         $ds = DIRECTORY_SEPARATOR;
                   47453:         // XXX Compatibility code should be removed in the future
                   47454:         // rename all registry files if any to lowercase
                   47455:         if (!OS_WINDOWS && file_exists($this->statedir) && is_dir($this->statedir) &&
                   47456:               $handle = opendir($this->statedir)) {
                   47457:             $dest = $this->statedir . $ds;
                   47458:             while (false !== ($file = readdir($handle))) {
                   47459:                 if (preg_match('/^.*[A-Z].*\.reg\\z/', $file)) {
                   47460:                     rename($dest . $file, $dest . strtolower($file));
                   47461:                 }
                   47462:             }
                   47463:             closedir($handle);
                   47464:         }
                   47465: 
                   47466:         $this->_initializeChannelDirs();
                   47467:         if (!file_exists($this->filemap)) {
                   47468:             $this->_rebuildFileMap();
                   47469:         }
                   47470:         $this->_initializeDepDB();
                   47471:     }
                   47472: 
                   47473:     function _initializeDepDB()
                   47474:     {
                   47475:         if (!isset($this->_dependencyDB)) {
                   47476:             static $initializing = false;
                   47477:             if (!$initializing) {
                   47478:                 $initializing = true;
                   47479:                 if (!$this->_config) { // never used?
                   47480:                     $file = OS_WINDOWS ? 'pear.ini' : '.pearrc';
                   47481:                     $this->_config = &new PEAR_Config($this->statedir . DIRECTORY_SEPARATOR .
                   47482:                         $file);
                   47483:                     $this->_config->setRegistry($this);
                   47484:                     $this->_config->set('php_dir', $this->install_dir);
                   47485:                 }
                   47486: 
                   47487:                 $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config);
                   47488:                 if (PEAR::isError($this->_dependencyDB)) {
                   47489:                     // attempt to recover by removing the dep db
                   47490:                     if (file_exists($this->_config->get('php_dir', null, 'pear.php.net') .
                   47491:                         DIRECTORY_SEPARATOR . '.depdb')) {
                   47492:                         @unlink($this->_config->get('php_dir', null, 'pear.php.net') .
                   47493:                             DIRECTORY_SEPARATOR . '.depdb');
                   47494:                     }
                   47495: 
                   47496:                     $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config);
                   47497:                     if (PEAR::isError($this->_dependencyDB)) {
                   47498:                         echo $this->_dependencyDB->getMessage();
                   47499:                         echo 'Unrecoverable error';
                   47500:                         exit(1);
                   47501:                     }
                   47502:                 }
                   47503: 
                   47504:                 $initializing = false;
                   47505:             }
                   47506:         }
                   47507:     }
                   47508: 
                   47509:     /**
                   47510:      * PEAR_Registry destructor.  Makes sure no locks are forgotten.
                   47511:      *
                   47512:      * @access private
                   47513:      */
                   47514:     function _PEAR_Registry()
                   47515:     {
                   47516:         parent::_PEAR();
                   47517:         if (is_resource($this->lock_fp)) {
                   47518:             $this->_unlock();
                   47519:         }
                   47520:     }
                   47521: 
                   47522:     /**
                   47523:      * Make sure the directory where we keep registry files exists.
                   47524:      *
                   47525:      * @return bool TRUE if directory exists, FALSE if it could not be
                   47526:      * created
                   47527:      *
                   47528:      * @access private
                   47529:      */
                   47530:     function _assertStateDir($channel = false)
                   47531:     {
                   47532:         if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
                   47533:             return $this->_assertChannelStateDir($channel);
                   47534:         }
                   47535: 
                   47536:         static $init = false;
                   47537:         if (!file_exists($this->statedir)) {
                   47538:             if (!$this->hasWriteAccess()) {
                   47539:                 return false;
                   47540:             }
                   47541: 
                   47542:             require_once 'System.php';
                   47543:             if (!System::mkdir(array('-p', $this->statedir))) {
                   47544:                 return $this->raiseError("could not create directory '{$this->statedir}'");
                   47545:             }
                   47546:             $init = true;
                   47547:         } elseif (!is_dir($this->statedir)) {
                   47548:             return $this->raiseError('Cannot create directory ' . $this->statedir . ', ' .
                   47549:                 'it already exists and is not a directory');
                   47550:         }
                   47551: 
                   47552:         $ds = DIRECTORY_SEPARATOR;
                   47553:         if (!file_exists($this->channelsdir)) {
                   47554:             if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg') ||
                   47555:                   !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') ||
                   47556:                   !file_exists($this->channelsdir . $ds . 'doc.php.net.reg') ||
                   47557:                   !file_exists($this->channelsdir . $ds . '__uri.reg')) {
                   47558:                 $init = true;
                   47559:             }
                   47560:         } elseif (!is_dir($this->channelsdir)) {
                   47561:             return $this->raiseError('Cannot create directory ' . $this->channelsdir . ', ' .
                   47562:                 'it already exists and is not a directory');
                   47563:         }
                   47564: 
                   47565:         if ($init) {
                   47566:             static $running = false;
                   47567:             if (!$running) {
                   47568:                 $running = true;
                   47569:                 $this->_initializeDirs();
                   47570:                 $running = false;
                   47571:                 $init = false;
                   47572:             }
                   47573:         } else {
                   47574:             $this->_initializeDepDB();
                   47575:         }
                   47576: 
                   47577:         return true;
                   47578:     }
                   47579: 
                   47580:     /**
                   47581:      * Make sure the directory where we keep registry files exists for a non-standard channel.
                   47582:      *
                   47583:      * @param string channel name
                   47584:      * @return bool TRUE if directory exists, FALSE if it could not be
                   47585:      * created
                   47586:      *
                   47587:      * @access private
                   47588:      */
                   47589:     function _assertChannelStateDir($channel)
                   47590:     {
                   47591:         $ds = DIRECTORY_SEPARATOR;
                   47592:         if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
                   47593:             if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
                   47594:                 $this->_initializeChannelDirs();
                   47595:             }
                   47596:             return $this->_assertStateDir($channel);
                   47597:         }
                   47598: 
                   47599:         $channelDir = $this->_channelDirectoryName($channel);
                   47600:         if (!is_dir($this->channelsdir) ||
                   47601:               !file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
                   47602:             $this->_initializeChannelDirs();
                   47603:         }
                   47604: 
                   47605:         if (!file_exists($channelDir)) {
                   47606:             if (!$this->hasWriteAccess()) {
                   47607:                 return false;
                   47608:             }
                   47609: 
                   47610:             require_once 'System.php';
                   47611:             if (!System::mkdir(array('-p', $channelDir))) {
                   47612:                 return $this->raiseError("could not create directory '" . $channelDir .
                   47613:                     "'");
                   47614:             }
                   47615:         } elseif (!is_dir($channelDir)) {
                   47616:             return $this->raiseError("could not create directory '" . $channelDir .
                   47617:                 "', already exists and is not a directory");
                   47618:         }
                   47619: 
                   47620:         return true;
                   47621:     }
                   47622: 
                   47623:     /**
                   47624:      * Make sure the directory where we keep registry files for channels exists
                   47625:      *
                   47626:      * @return bool TRUE if directory exists, FALSE if it could not be
                   47627:      * created
                   47628:      *
                   47629:      * @access private
                   47630:      */
                   47631:     function _assertChannelDir()
                   47632:     {
                   47633:         if (!file_exists($this->channelsdir)) {
                   47634:             if (!$this->hasWriteAccess()) {
                   47635:                 return false;
                   47636:             }
                   47637: 
                   47638:             require_once 'System.php';
                   47639:             if (!System::mkdir(array('-p', $this->channelsdir))) {
                   47640:                 return $this->raiseError("could not create directory '{$this->channelsdir}'");
                   47641:             }
                   47642:         } elseif (!is_dir($this->channelsdir)) {
                   47643:             return $this->raiseError("could not create directory '{$this->channelsdir}" .
                   47644:                 "', it already exists and is not a directory");
                   47645:         }
                   47646: 
                   47647:         if (!file_exists($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) {
                   47648:             if (!$this->hasWriteAccess()) {
                   47649:                 return false;
                   47650:             }
                   47651: 
                   47652:             require_once 'System.php';
                   47653:             if (!System::mkdir(array('-p', $this->channelsdir . DIRECTORY_SEPARATOR . '.alias'))) {
                   47654:                 return $this->raiseError("could not create directory '{$this->channelsdir}/.alias'");
                   47655:             }
                   47656:         } elseif (!is_dir($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) {
                   47657:             return $this->raiseError("could not create directory '{$this->channelsdir}" .
                   47658:                 "/.alias', it already exists and is not a directory");
                   47659:         }
                   47660: 
                   47661:         return true;
                   47662:     }
                   47663: 
                   47664:     /**
                   47665:      * Get the name of the file where data for a given package is stored.
                   47666:      *
                   47667:      * @param string channel name, or false if this is a PEAR package
                   47668:      * @param string package name
                   47669:      *
                   47670:      * @return string registry file name
                   47671:      *
                   47672:      * @access public
                   47673:      */
                   47674:     function _packageFileName($package, $channel = false)
                   47675:     {
                   47676:         if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
                   47677:             return $this->_channelDirectoryName($channel) . DIRECTORY_SEPARATOR .
                   47678:                 strtolower($package) . '.reg';
                   47679:         }
                   47680: 
                   47681:         return $this->statedir . DIRECTORY_SEPARATOR . strtolower($package) . '.reg';
                   47682:     }
                   47683: 
                   47684:     /**
                   47685:      * Get the name of the file where data for a given channel is stored.
                   47686:      * @param string channel name
                   47687:      * @return string registry file name
                   47688:      */
                   47689:     function _channelFileName($channel, $noaliases = false)
                   47690:     {
                   47691:         if (!$noaliases) {
                   47692:             if (file_exists($this->_getChannelAliasFileName($channel))) {
                   47693:                 $channel = implode('', file($this->_getChannelAliasFileName($channel)));
                   47694:             }
                   47695:         }
                   47696:         return $this->channelsdir . DIRECTORY_SEPARATOR . str_replace('/', '_',
                   47697:             strtolower($channel)) . '.reg';
                   47698:     }
                   47699: 
                   47700:     /**
                   47701:      * @param string
                   47702:      * @return string
                   47703:      */
                   47704:     function _getChannelAliasFileName($alias)
                   47705:     {
                   47706:         return $this->channelsdir . DIRECTORY_SEPARATOR . '.alias' .
                   47707:               DIRECTORY_SEPARATOR . str_replace('/', '_', strtolower($alias)) . '.txt';
                   47708:     }
                   47709: 
                   47710:     /**
                   47711:      * Get the name of a channel from its alias
                   47712:      */
                   47713:     function _getChannelFromAlias($channel)
                   47714:     {
                   47715:         if (!$this->_channelExists($channel)) {
                   47716:             if ($channel == 'pear.php.net') {
                   47717:                 return 'pear.php.net';
                   47718:             }
                   47719: 
                   47720:             if ($channel == 'pecl.php.net') {
                   47721:                 return 'pecl.php.net';
                   47722:             }
                   47723: 
                   47724:             if ($channel == 'doc.php.net') {
                   47725:                 return 'doc.php.net';
                   47726:             }
                   47727: 
                   47728:             if ($channel == '__uri') {
                   47729:                 return '__uri';
                   47730:             }
                   47731: 
                   47732:             return false;
                   47733:         }
                   47734: 
                   47735:         $channel = strtolower($channel);
                   47736:         if (file_exists($this->_getChannelAliasFileName($channel))) {
                   47737:             // translate an alias to an actual channel
                   47738:             return implode('', file($this->_getChannelAliasFileName($channel)));
                   47739:         }
                   47740: 
                   47741:         return $channel;
                   47742:     }
                   47743: 
                   47744:     /**
                   47745:      * Get the alias of a channel from its alias or its name
                   47746:      */
                   47747:     function _getAlias($channel)
                   47748:     {
                   47749:         if (!$this->_channelExists($channel)) {
                   47750:             if ($channel == 'pear.php.net') {
                   47751:                 return 'pear';
                   47752:             }
                   47753: 
                   47754:             if ($channel == 'pecl.php.net') {
                   47755:                 return 'pecl';
                   47756:             }
                   47757: 
                   47758:             if ($channel == 'doc.php.net') {
                   47759:                 return 'phpdocs';
                   47760:             }
                   47761: 
                   47762:             return false;
                   47763:         }
                   47764: 
                   47765:         $channel = $this->_getChannel($channel);
                   47766:         if (PEAR::isError($channel)) {
                   47767:             return $channel;
                   47768:         }
                   47769: 
                   47770:         return $channel->getAlias();
                   47771:     }
                   47772: 
                   47773:     /**
                   47774:      * Get the name of the file where data for a given package is stored.
                   47775:      *
                   47776:      * @param string channel name, or false if this is a PEAR package
                   47777:      * @param string package name
                   47778:      *
                   47779:      * @return string registry file name
                   47780:      *
                   47781:      * @access public
                   47782:      */
                   47783:     function _channelDirectoryName($channel)
                   47784:     {
                   47785:         if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
                   47786:             return $this->statedir;
                   47787:         }
                   47788: 
                   47789:         $ch = $this->_getChannelFromAlias($channel);
                   47790:         if (!$ch) {
                   47791:             $ch = $channel;
                   47792:         }
                   47793: 
                   47794:         return $this->statedir . DIRECTORY_SEPARATOR . strtolower('.channel.' .
                   47795:             str_replace('/', '_', $ch));
                   47796:     }
                   47797: 
                   47798:     function _openPackageFile($package, $mode, $channel = false)
                   47799:     {
                   47800:         if (!$this->_assertStateDir($channel)) {
                   47801:             return null;
                   47802:         }
                   47803: 
                   47804:         if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) {
                   47805:             return null;
                   47806:         }
                   47807: 
                   47808:         $file = $this->_packageFileName($package, $channel);
                   47809:         if (!file_exists($file) && $mode == 'r' || $mode == 'rb') {
                   47810:             return null;
                   47811:         }
                   47812: 
                   47813:         $fp = @fopen($file, $mode);
                   47814:         if (!$fp) {
                   47815:             return null;
                   47816:         }
                   47817: 
                   47818:         return $fp;
                   47819:     }
                   47820: 
                   47821:     function _closePackageFile($fp)
                   47822:     {
                   47823:         fclose($fp);
                   47824:     }
                   47825: 
                   47826:     function _openChannelFile($channel, $mode)
                   47827:     {
                   47828:         if (!$this->_assertChannelDir()) {
                   47829:             return null;
                   47830:         }
                   47831: 
                   47832:         if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) {
                   47833:             return null;
                   47834:         }
                   47835: 
                   47836:         $file = $this->_channelFileName($channel);
                   47837:         if (!file_exists($file) && $mode == 'r' || $mode == 'rb') {
                   47838:             return null;
                   47839:         }
                   47840: 
                   47841:         $fp = @fopen($file, $mode);
                   47842:         if (!$fp) {
                   47843:             return null;
                   47844:         }
                   47845: 
                   47846:         return $fp;
                   47847:     }
                   47848: 
                   47849:     function _closeChannelFile($fp)
                   47850:     {
                   47851:         fclose($fp);
                   47852:     }
                   47853: 
                   47854:     function _rebuildFileMap()
                   47855:     {
                   47856:         if (!class_exists('PEAR_Installer_Role')) {
                   47857:             require_once 'PEAR/Installer/Role.php';
                   47858:         }
                   47859: 
                   47860:         $channels = $this->_listAllPackages();
                   47861:         $files = array();
                   47862:         foreach ($channels as $channel => $packages) {
                   47863:             foreach ($packages as $package) {
                   47864:                 $version = $this->_packageInfo($package, 'version', $channel);
                   47865:                 $filelist = $this->_packageInfo($package, 'filelist', $channel);
                   47866:                 if (!is_array($filelist)) {
                   47867:                     continue;
                   47868:                 }
                   47869: 
                   47870:                 foreach ($filelist as $name => $attrs) {
                   47871:                     if (isset($attrs['attribs'])) {
                   47872:                         $attrs = $attrs['attribs'];
                   47873:                     }
                   47874: 
                   47875:                     // it is possible for conflicting packages in different channels to
                   47876:                     // conflict with data files/doc files
                   47877:                     if ($name == 'dirtree') {
                   47878:                         continue;
                   47879:                     }
                   47880: 
                   47881:                     if (isset($attrs['role']) && !in_array($attrs['role'],
                   47882:                           PEAR_Installer_Role::getInstallableRoles())) {
                   47883:                         // these are not installed
                   47884:                         continue;
                   47885:                     }
                   47886: 
                   47887:                     if (isset($attrs['role']) && !in_array($attrs['role'],
                   47888:                           PEAR_Installer_Role::getBaseinstallRoles())) {
                   47889:                         $attrs['baseinstalldir'] = $package;
                   47890:                     }
                   47891: 
                   47892:                     if (isset($attrs['baseinstalldir'])) {
                   47893:                         $file = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name;
                   47894:                     } else {
                   47895:                         $file = $name;
                   47896:                     }
                   47897: 
                   47898:                     $file = preg_replace(',^/+,', '', $file);
                   47899:                     if ($channel != 'pear.php.net') {
                   47900:                         if (!isset($files[$attrs['role']])) {
                   47901:                             $files[$attrs['role']] = array();
                   47902:                         }
                   47903:                         $files[$attrs['role']][$file] = array(strtolower($channel),
                   47904:                             strtolower($package));
                   47905:                     } else {
                   47906:                         if (!isset($files[$attrs['role']])) {
                   47907:                             $files[$attrs['role']] = array();
                   47908:                         }
                   47909:                         $files[$attrs['role']][$file] = strtolower($package);
                   47910:                     }
                   47911:                 }
                   47912:             }
                   47913:         }
                   47914: 
                   47915: 
                   47916:         $this->_assertStateDir();
                   47917:         if (!$this->hasWriteAccess()) {
                   47918:             return false;
                   47919:         }
                   47920: 
                   47921:         $fp = @fopen($this->filemap, 'wb');
                   47922:         if (!$fp) {
                   47923:             return false;
                   47924:         }
                   47925: 
                   47926:         $this->filemap_cache = $files;
                   47927:         fwrite($fp, serialize($files));
                   47928:         fclose($fp);
                   47929:         return true;
                   47930:     }
                   47931: 
                   47932:     function _readFileMap()
                   47933:     {
                   47934:         if (!file_exists($this->filemap)) {
                   47935:             return array();
                   47936:         }
                   47937: 
                   47938:         $fp = @fopen($this->filemap, 'r');
                   47939:         if (!$fp) {
                   47940:             return $this->raiseError('PEAR_Registry: could not open filemap "' . $this->filemap . '"', PEAR_REGISTRY_ERROR_FILE, null, null, $php_errormsg);
                   47941:         }
                   47942: 
                   47943:         clearstatcache();
                   47944:         $rt = get_magic_quotes_runtime();
                   47945:         set_magic_quotes_runtime(0);
                   47946:         $fsize = filesize($this->filemap);
                   47947:         fclose($fp);
                   47948:         $data = file_get_contents($this->filemap);
                   47949:         set_magic_quotes_runtime($rt);
                   47950:         $tmp = unserialize($data);
                   47951:         if (!$tmp && $fsize > 7) {
                   47952:             return $this->raiseError('PEAR_Registry: invalid filemap data', PEAR_REGISTRY_ERROR_FORMAT, null, null, $data);
                   47953:         }
                   47954: 
                   47955:         $this->filemap_cache = $tmp;
                   47956:         return true;
                   47957:     }
                   47958: 
                   47959:     /**
                   47960:      * Lock the registry.
                   47961:      *
                   47962:      * @param integer lock mode, one of LOCK_EX, LOCK_SH or LOCK_UN.
                   47963:      *                See flock manual for more information.
                   47964:      *
                   47965:      * @return bool TRUE on success, FALSE if locking failed, or a
                   47966:      *              PEAR error if some other error occurs (such as the
                   47967:      *              lock file not being writable).
                   47968:      *
                   47969:      * @access private
                   47970:      */
                   47971:     function _lock($mode = LOCK_EX)
                   47972:     {
                   47973:         if (stristr(php_uname(), 'Windows 9')) {
                   47974:             return true;
                   47975:         }
                   47976: 
                   47977:         if ($mode != LOCK_UN && is_resource($this->lock_fp)) {
                   47978:             // XXX does not check type of lock (LOCK_SH/LOCK_EX)
                   47979:             return true;
                   47980:         }
                   47981: 
                   47982:         if (!$this->_assertStateDir()) {
                   47983:             if ($mode == LOCK_EX) {
                   47984:                 return $this->raiseError('Registry directory is not writeable by the current user');
                   47985:             }
                   47986: 
                   47987:             return true;
                   47988:         }
                   47989: 
                   47990:         $open_mode = 'w';
                   47991:         // XXX People reported problems with LOCK_SH and 'w'
                   47992:         if ($mode === LOCK_SH || $mode === LOCK_UN) {
                   47993:             if (!file_exists($this->lockfile)) {
                   47994:                 touch($this->lockfile);
                   47995:             }
                   47996:             $open_mode = 'r';
                   47997:         }
                   47998: 
                   47999:         if (!is_resource($this->lock_fp)) {
                   48000:             $this->lock_fp = @fopen($this->lockfile, $open_mode);
                   48001:         }
                   48002: 
                   48003:         if (!is_resource($this->lock_fp)) {
                   48004:             $this->lock_fp = null;
                   48005:             return $this->raiseError("could not create lock file" .
                   48006:                                      (isset($php_errormsg) ? ": " . $php_errormsg : ""));
                   48007:         }
                   48008: 
                   48009:         if (!(int)flock($this->lock_fp, $mode)) {
                   48010:             switch ($mode) {
                   48011:                 case LOCK_SH: $str = 'shared';    break;
                   48012:                 case LOCK_EX: $str = 'exclusive'; break;
                   48013:                 case LOCK_UN: $str = 'unlock';    break;
                   48014:                 default:      $str = 'unknown';   break;
                   48015:             }
                   48016: 
                   48017:             //is resource at this point, close it on error.
                   48018:             fclose($this->lock_fp);
                   48019:             $this->lock_fp = null;
                   48020:             return $this->raiseError("could not acquire $str lock ($this->lockfile)",
                   48021:                                      PEAR_REGISTRY_ERROR_LOCK);
                   48022:         }
                   48023: 
                   48024:         return true;
                   48025:     }
                   48026: 
                   48027:     function _unlock()
                   48028:     {
                   48029:         $ret = $this->_lock(LOCK_UN);
                   48030:         if (is_resource($this->lock_fp)) {
                   48031:             fclose($this->lock_fp);
                   48032:         }
                   48033: 
                   48034:         $this->lock_fp = null;
                   48035:         return $ret;
                   48036:     }
                   48037: 
                   48038:     function _packageExists($package, $channel = false)
                   48039:     {
                   48040:         return file_exists($this->_packageFileName($package, $channel));
                   48041:     }
                   48042: 
                   48043:     /**
                   48044:      * Determine whether a channel exists in the registry
                   48045:      *
                   48046:      * @param string Channel name
                   48047:      * @param bool if true, then aliases will be ignored
                   48048:      * @return boolean
                   48049:      */
                   48050:     function _channelExists($channel, $noaliases = false)
                   48051:     {
                   48052:         $a = file_exists($this->_channelFileName($channel, $noaliases));
                   48053:         if (!$a && $channel == 'pear.php.net') {
                   48054:             return true;
                   48055:         }
                   48056: 
                   48057:         if (!$a && $channel == 'pecl.php.net') {
                   48058:             return true;
                   48059:         }
                   48060: 
                   48061:         if (!$a && $channel == 'doc.php.net') {
                   48062:             return true;
                   48063:         }
                   48064: 
                   48065:         return $a;
                   48066:     }
                   48067: 
                   48068:     /**
                   48069:      * Determine whether a mirror exists within the deafult channel in the registry
                   48070:      *
                   48071:      * @param string Channel name
                   48072:      * @param string Mirror name
                   48073:      *
                   48074:      * @return boolean
                   48075:      */
                   48076:     function _mirrorExists($channel, $mirror)
                   48077:     {
                   48078:         $data = $this->_channelInfo($channel);
                   48079:         if (!isset($data['servers']['mirror'])) {
                   48080:             return false;
                   48081:         }
                   48082: 
                   48083:         foreach ($data['servers']['mirror'] as $m) {
                   48084:             if ($m['attribs']['host'] == $mirror) {
                   48085:                 return true;
                   48086:             }
                   48087:         }
                   48088: 
                   48089:         return false;
                   48090:     }
                   48091: 
                   48092:     /**
                   48093:      * @param PEAR_ChannelFile Channel object
                   48094:      * @param donotuse
                   48095:      * @param string Last-Modified HTTP tag from remote request
                   48096:      * @return boolean|PEAR_Error True on creation, false if it already exists
                   48097:      */
                   48098:     function _addChannel($channel, $update = false, $lastmodified = false)
                   48099:     {
                   48100:         if (!is_a($channel, 'PEAR_ChannelFile')) {
                   48101:             return false;
                   48102:         }
                   48103: 
                   48104:         if (!$channel->validate()) {
                   48105:             return false;
                   48106:         }
                   48107: 
                   48108:         if (file_exists($this->_channelFileName($channel->getName()))) {
                   48109:             if (!$update) {
                   48110:                 return false;
                   48111:             }
                   48112: 
                   48113:             $checker = $this->_getChannel($channel->getName());
                   48114:             if (PEAR::isError($checker)) {
                   48115:                 return $checker;
                   48116:             }
                   48117: 
                   48118:             if ($channel->getAlias() != $checker->getAlias()) {
                   48119:                 if (file_exists($this->_getChannelAliasFileName($checker->getAlias()))) {
                   48120:                     @unlink($this->_getChannelAliasFileName($checker->getAlias()));
                   48121:                 }
                   48122:             }
                   48123:         } else {
                   48124:             if ($update && !in_array($channel->getName(), array('pear.php.net', 'pecl.php.net', 'doc.php.net'))) {
                   48125:                 return false;
                   48126:             }
                   48127:         }
                   48128: 
                   48129:         $ret = $this->_assertChannelDir();
                   48130:         if (PEAR::isError($ret)) {
                   48131:             return $ret;
                   48132:         }
                   48133: 
                   48134:         $ret = $this->_assertChannelStateDir($channel->getName());
                   48135:         if (PEAR::isError($ret)) {
                   48136:             return $ret;
                   48137:         }
                   48138: 
                   48139:         if ($channel->getAlias() != $channel->getName()) {
                   48140:             if (file_exists($this->_getChannelAliasFileName($channel->getAlias())) &&
                   48141:                   $this->_getChannelFromAlias($channel->getAlias()) != $channel->getName()) {
                   48142:                 $channel->setAlias($channel->getName());
                   48143:             }
                   48144: 
                   48145:             if (!$this->hasWriteAccess()) {
                   48146:                 return false;
                   48147:             }
                   48148: 
                   48149:             $fp = @fopen($this->_getChannelAliasFileName($channel->getAlias()), 'w');
                   48150:             if (!$fp) {
                   48151:                 return false;
                   48152:             }
                   48153: 
                   48154:             fwrite($fp, $channel->getName());
                   48155:             fclose($fp);
                   48156:         }
                   48157: 
                   48158:         if (!$this->hasWriteAccess()) {
                   48159:             return false;
                   48160:         }
                   48161: 
                   48162:         $fp = @fopen($this->_channelFileName($channel->getName()), 'wb');
                   48163:         if (!$fp) {
                   48164:             return false;
                   48165:         }
                   48166: 
                   48167:         $info = $channel->toArray();
                   48168:         if ($lastmodified) {
                   48169:             $info['_lastmodified'] = $lastmodified;
                   48170:         } else {
                   48171:             $info['_lastmodified'] = date('r');
                   48172:         }
                   48173: 
                   48174:         fwrite($fp, serialize($info));
                   48175:         fclose($fp);
                   48176:         return true;
                   48177:     }
                   48178: 
                   48179:     /**
                   48180:      * Deletion fails if there are any packages installed from the channel
                   48181:      * @param string|PEAR_ChannelFile channel name
                   48182:      * @return boolean|PEAR_Error True on deletion, false if it doesn't exist
                   48183:      */
                   48184:     function _deleteChannel($channel)
                   48185:     {
                   48186:         if (!is_string($channel)) {
                   48187:             if (!is_a($channel, 'PEAR_ChannelFile')) {
                   48188:                 return false;
                   48189:             }
                   48190: 
                   48191:             if (!$channel->validate()) {
                   48192:                 return false;
                   48193:             }
                   48194:             $channel = $channel->getName();
                   48195:         }
                   48196: 
                   48197:         if ($this->_getChannelFromAlias($channel) == '__uri') {
                   48198:             return false;
                   48199:         }
                   48200: 
                   48201:         if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') {
                   48202:             return false;
                   48203:         }
                   48204: 
                   48205:         if ($this->_getChannelFromAlias($channel) == 'doc.php.net') {
                   48206:             return false;
                   48207:         }
                   48208: 
                   48209:         if (!$this->_channelExists($channel)) {
                   48210:             return false;
                   48211:         }
                   48212: 
                   48213:         if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
                   48214:             return false;
                   48215:         }
                   48216: 
                   48217:         $channel = $this->_getChannelFromAlias($channel);
                   48218:         if ($channel == 'pear.php.net') {
                   48219:             return false;
                   48220:         }
                   48221: 
                   48222:         $test = $this->_listChannelPackages($channel);
                   48223:         if (count($test)) {
                   48224:             return false;
                   48225:         }
                   48226: 
                   48227:         $test = @rmdir($this->_channelDirectoryName($channel));
                   48228:         if (!$test) {
                   48229:             return false;
                   48230:         }
                   48231: 
                   48232:         $file = $this->_getChannelAliasFileName($this->_getAlias($channel));
                   48233:         if (file_exists($file)) {
                   48234:             $test = @unlink($file);
                   48235:             if (!$test) {
                   48236:                 return false;
                   48237:             }
                   48238:         }
                   48239: 
                   48240:         $file = $this->_channelFileName($channel);
                   48241:         $ret = true;
                   48242:         if (file_exists($file)) {
                   48243:             $ret = @unlink($file);
                   48244:         }
                   48245: 
                   48246:         return $ret;
                   48247:     }
                   48248: 
                   48249:     /**
                   48250:      * Determine whether a channel exists in the registry
                   48251:      * @param string Channel Alias
                   48252:      * @return boolean
                   48253:      */
                   48254:     function _isChannelAlias($alias)
                   48255:     {
                   48256:         return file_exists($this->_getChannelAliasFileName($alias));
                   48257:     }
                   48258: 
                   48259:     /**
                   48260:      * @param string|null
                   48261:      * @param string|null
                   48262:      * @param string|null
                   48263:      * @return array|null
                   48264:      * @access private
                   48265:      */
                   48266:     function _packageInfo($package = null, $key = null, $channel = 'pear.php.net')
                   48267:     {
                   48268:         if ($package === null) {
                   48269:             if ($channel === null) {
                   48270:                 $channels = $this->_listChannels();
                   48271:                 $ret = array();
                   48272:                 foreach ($channels as $channel) {
                   48273:                     $channel = strtolower($channel);
                   48274:                     $ret[$channel] = array();
                   48275:                     $packages = $this->_listPackages($channel);
                   48276:                     foreach ($packages as $package) {
                   48277:                         $ret[$channel][] = $this->_packageInfo($package, null, $channel);
                   48278:                     }
                   48279:                 }
                   48280: 
                   48281:                 return $ret;
                   48282:             }
                   48283: 
                   48284:             $ps = $this->_listPackages($channel);
                   48285:             if (!count($ps)) {
                   48286:                 return array();
                   48287:             }
                   48288:             return array_map(array(&$this, '_packageInfo'),
                   48289:                              $ps, array_fill(0, count($ps), null),
                   48290:                              array_fill(0, count($ps), $channel));
                   48291:         }
                   48292: 
                   48293:         $fp = $this->_openPackageFile($package, 'r', $channel);
                   48294:         if ($fp === null) {
                   48295:             return null;
                   48296:         }
                   48297: 
                   48298:         $rt = get_magic_quotes_runtime();
                   48299:         set_magic_quotes_runtime(0);
                   48300:         clearstatcache();
                   48301:         $this->_closePackageFile($fp);
                   48302:         $data = file_get_contents($this->_packageFileName($package, $channel));
                   48303:         set_magic_quotes_runtime($rt);
                   48304:         $data = unserialize($data);
                   48305:         if ($key === null) {
                   48306:             return $data;
                   48307:         }
                   48308: 
                   48309:         // compatibility for package.xml version 2.0
                   48310:         if (isset($data['old'][$key])) {
                   48311:             return $data['old'][$key];
                   48312:         }
                   48313: 
                   48314:         if (isset($data[$key])) {
                   48315:             return $data[$key];
                   48316:         }
                   48317: 
                   48318:         return null;
                   48319:     }
                   48320: 
                   48321:     /**
                   48322:      * @param string Channel name
                   48323:      * @param bool whether to strictly retrieve info of channels, not just aliases
                   48324:      * @return array|null
                   48325:      */
                   48326:     function _channelInfo($channel, $noaliases = false)
                   48327:     {
                   48328:         if (!$this->_channelExists($channel, $noaliases)) {
                   48329:             return null;
                   48330:         }
                   48331: 
                   48332:         $fp = $this->_openChannelFile($channel, 'r');
                   48333:         if ($fp === null) {
                   48334:             return null;
                   48335:         }
                   48336: 
                   48337:         $rt = get_magic_quotes_runtime();
                   48338:         set_magic_quotes_runtime(0);
                   48339:         clearstatcache();
                   48340:         $this->_closeChannelFile($fp);
                   48341:         $data = file_get_contents($this->_channelFileName($channel));
                   48342:         set_magic_quotes_runtime($rt);
                   48343:         $data = unserialize($data);
                   48344:         return $data;
                   48345:     }
                   48346: 
                   48347:     function _listChannels()
                   48348:     {
                   48349:         $channellist = array();
                   48350:         if (!file_exists($this->channelsdir) || !is_dir($this->channelsdir)) {
                   48351:             return array('pear.php.net', 'pecl.php.net', 'doc.php.net', '__uri');
                   48352:         }
                   48353: 
                   48354:         $dp = opendir($this->channelsdir);
                   48355:         while ($ent = readdir($dp)) {
                   48356:             if ($ent{0} == '.' || substr($ent, -4) != '.reg') {
                   48357:                 continue;
                   48358:             }
                   48359: 
                   48360:             if ($ent == '__uri.reg') {
                   48361:                 $channellist[] = '__uri';
                   48362:                 continue;
                   48363:             }
                   48364: 
                   48365:             $channellist[] = str_replace('_', '/', substr($ent, 0, -4));
                   48366:         }
                   48367: 
                   48368:         closedir($dp);
                   48369:         if (!in_array('pear.php.net', $channellist)) {
                   48370:             $channellist[] = 'pear.php.net';
                   48371:         }
                   48372: 
                   48373:         if (!in_array('pecl.php.net', $channellist)) {
                   48374:             $channellist[] = 'pecl.php.net';
                   48375:         }
                   48376: 
                   48377:         if (!in_array('doc.php.net', $channellist)) {
                   48378:             $channellist[] = 'doc.php.net';
                   48379:         }
                   48380: 
                   48381: 
                   48382:         if (!in_array('__uri', $channellist)) {
                   48383:             $channellist[] = '__uri';
                   48384:         }
                   48385: 
                   48386:         natsort($channellist);
                   48387:         return $channellist;
                   48388:     }
                   48389: 
                   48390:     function _listPackages($channel = false)
                   48391:     {
                   48392:         if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
                   48393:             return $this->_listChannelPackages($channel);
                   48394:         }
                   48395: 
                   48396:         if (!file_exists($this->statedir) || !is_dir($this->statedir)) {
                   48397:             return array();
                   48398:         }
                   48399: 
                   48400:         $pkglist = array();
                   48401:         $dp = opendir($this->statedir);
                   48402:         if (!$dp) {
                   48403:             return $pkglist;
                   48404:         }
                   48405: 
                   48406:         while ($ent = readdir($dp)) {
                   48407:             if ($ent{0} == '.' || substr($ent, -4) != '.reg') {
                   48408:                 continue;
                   48409:             }
                   48410: 
                   48411:             $pkglist[] = substr($ent, 0, -4);
                   48412:         }
                   48413:         closedir($dp);
                   48414:         return $pkglist;
                   48415:     }
                   48416: 
                   48417:     function _listChannelPackages($channel)
                   48418:     {
                   48419:         $pkglist = array();
                   48420:         if (!file_exists($this->_channelDirectoryName($channel)) ||
                   48421:               !is_dir($this->_channelDirectoryName($channel))) {
                   48422:             return array();
                   48423:         }
                   48424: 
                   48425:         $dp = opendir($this->_channelDirectoryName($channel));
                   48426:         if (!$dp) {
                   48427:             return $pkglist;
                   48428:         }
                   48429: 
                   48430:         while ($ent = readdir($dp)) {
                   48431:             if ($ent{0} == '.' || substr($ent, -4) != '.reg') {
                   48432:                 continue;
                   48433:             }
                   48434:             $pkglist[] = substr($ent, 0, -4);
                   48435:         }
                   48436: 
                   48437:         closedir($dp);
                   48438:         return $pkglist;
                   48439:     }
                   48440: 
                   48441:     function _listAllPackages()
                   48442:     {
                   48443:         $ret = array();
                   48444:         foreach ($this->_listChannels() as $channel) {
                   48445:             $ret[$channel] = $this->_listPackages($channel);
                   48446:         }
                   48447: 
                   48448:         return $ret;
                   48449:     }
                   48450: 
                   48451:     /**
                   48452:      * Add an installed package to the registry
                   48453:      * @param string package name
                   48454:      * @param array package info (parsed by PEAR_Common::infoFrom*() methods)
                   48455:      * @return bool success of saving
                   48456:      * @access private
                   48457:      */
                   48458:     function _addPackage($package, $info)
                   48459:     {
                   48460:         if ($this->_packageExists($package)) {
                   48461:             return false;
                   48462:         }
                   48463: 
                   48464:         $fp = $this->_openPackageFile($package, 'wb');
                   48465:         if ($fp === null) {
                   48466:             return false;
                   48467:         }
                   48468: 
                   48469:         $info['_lastmodified'] = time();
                   48470:         fwrite($fp, serialize($info));
                   48471:         $this->_closePackageFile($fp);
                   48472:         if (isset($info['filelist'])) {
                   48473:             $this->_rebuildFileMap();
                   48474:         }
                   48475: 
                   48476:         return true;
                   48477:     }
                   48478: 
                   48479:     /**
                   48480:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   48481:      * @return bool
                   48482:      * @access private
                   48483:      */
                   48484:     function _addPackage2($info)
                   48485:     {
                   48486:         if (!is_a($info, 'PEAR_PackageFile_v1') && !is_a($info, 'PEAR_PackageFile_v2')) {
                   48487:             return false;
                   48488:         }
                   48489: 
                   48490:         if (!$info->validate()) {
                   48491:             if (class_exists('PEAR_Common')) {
                   48492:                 $ui = PEAR_Frontend::singleton();
                   48493:                 if ($ui) {
                   48494:                     foreach ($info->getValidationWarnings() as $err) {
                   48495:                         $ui->log($err['message'], true);
                   48496:                     }
                   48497:                 }
                   48498:             }
                   48499:             return false;
                   48500:         }
                   48501: 
                   48502:         $channel = $info->getChannel();
                   48503:         $package = $info->getPackage();
                   48504:         $save = $info;
                   48505:         if ($this->_packageExists($package, $channel)) {
                   48506:             return false;
                   48507:         }
                   48508: 
                   48509:         if (!$this->_channelExists($channel, true)) {
                   48510:             return false;
                   48511:         }
                   48512: 
                   48513:         $info = $info->toArray(true);
                   48514:         if (!$info) {
                   48515:             return false;
                   48516:         }
                   48517: 
                   48518:         $fp = $this->_openPackageFile($package, 'wb', $channel);
                   48519:         if ($fp === null) {
                   48520:             return false;
                   48521:         }
                   48522: 
                   48523:         $info['_lastmodified'] = time();
                   48524:         fwrite($fp, serialize($info));
                   48525:         $this->_closePackageFile($fp);
                   48526:         $this->_rebuildFileMap();
                   48527:         return true;
                   48528:     }
                   48529: 
                   48530:     /**
                   48531:      * @param string Package name
                   48532:      * @param array parsed package.xml 1.0
                   48533:      * @param bool this parameter is only here for BC.  Don't use it.
                   48534:      * @access private
                   48535:      */
                   48536:     function _updatePackage($package, $info, $merge = true)
                   48537:     {
                   48538:         $oldinfo = $this->_packageInfo($package);
                   48539:         if (empty($oldinfo)) {
                   48540:             return false;
                   48541:         }
                   48542: 
                   48543:         $fp = $this->_openPackageFile($package, 'w');
                   48544:         if ($fp === null) {
                   48545:             return false;
                   48546:         }
                   48547: 
                   48548:         if (is_object($info)) {
                   48549:             $info = $info->toArray();
                   48550:         }
                   48551:         $info['_lastmodified'] = time();
                   48552: 
                   48553:         $newinfo = $info;
                   48554:         if ($merge) {
                   48555:             $info = array_merge($oldinfo, $info);
                   48556:         } else {
                   48557:             $diff = $info;
                   48558:         }
                   48559: 
                   48560:         fwrite($fp, serialize($info));
                   48561:         $this->_closePackageFile($fp);
                   48562:         if (isset($newinfo['filelist'])) {
                   48563:             $this->_rebuildFileMap();
                   48564:         }
                   48565: 
                   48566:         return true;
                   48567:     }
                   48568: 
                   48569:     /**
                   48570:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   48571:      * @return bool
                   48572:      * @access private
                   48573:      */
                   48574:     function _updatePackage2($info)
                   48575:     {
                   48576:         if (!$this->_packageExists($info->getPackage(), $info->getChannel())) {
                   48577:             return false;
                   48578:         }
                   48579: 
                   48580:         $fp = $this->_openPackageFile($info->getPackage(), 'w', $info->getChannel());
                   48581:         if ($fp === null) {
                   48582:             return false;
                   48583:         }
                   48584: 
                   48585:         $save = $info;
                   48586:         $info = $save->getArray(true);
                   48587:         $info['_lastmodified'] = time();
                   48588:         fwrite($fp, serialize($info));
                   48589:         $this->_closePackageFile($fp);
                   48590:         $this->_rebuildFileMap();
                   48591:         return true;
                   48592:     }
                   48593: 
                   48594:     /**
                   48595:      * @param string Package name
                   48596:      * @param string Channel name
                   48597:      * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
                   48598:      * @access private
                   48599:      */
                   48600:     function &_getPackage($package, $channel = 'pear.php.net')
                   48601:     {
                   48602:         $info = $this->_packageInfo($package, null, $channel);
                   48603:         if ($info === null) {
                   48604:             return $info;
                   48605:         }
                   48606: 
                   48607:         $a = $this->_config;
                   48608:         if (!$a) {
                   48609:             $this->_config = &new PEAR_Config;
                   48610:             $this->_config->set('php_dir', $this->statedir);
                   48611:         }
                   48612: 
                   48613:         if (!class_exists('PEAR_PackageFile')) {
                   48614:             require_once 'PEAR/PackageFile.php';
                   48615:         }
                   48616: 
                   48617:         $pkg = &new PEAR_PackageFile($this->_config);
                   48618:         $pf = &$pkg->fromArray($info);
                   48619:         return $pf;
                   48620:     }
                   48621: 
                   48622:     /**
                   48623:      * @param string channel name
                   48624:      * @param bool whether to strictly retrieve channel names
                   48625:      * @return PEAR_ChannelFile|PEAR_Error
                   48626:      * @access private
                   48627:      */
                   48628:     function &_getChannel($channel, $noaliases = false)
                   48629:     {
                   48630:         $ch = false;
                   48631:         if ($this->_channelExists($channel, $noaliases)) {
                   48632:             $chinfo = $this->_channelInfo($channel, $noaliases);
                   48633:             if ($chinfo) {
                   48634:                 if (!class_exists('PEAR_ChannelFile')) {
                   48635:                     require_once 'PEAR/ChannelFile.php';
                   48636:                 }
                   48637: 
                   48638:                 $ch = &PEAR_ChannelFile::fromArrayWithErrors($chinfo);
                   48639:             }
                   48640:         }
                   48641: 
                   48642:         if ($ch) {
                   48643:             if ($ch->validate()) {
                   48644:                 return $ch;
                   48645:             }
                   48646: 
                   48647:             foreach ($ch->getErrors(true) as $err) {
                   48648:                 $message = $err['message'] . "\n";
                   48649:             }
                   48650: 
                   48651:             $ch = PEAR::raiseError($message);
                   48652:             return $ch;
                   48653:         }
                   48654: 
                   48655:         if ($this->_getChannelFromAlias($channel) == 'pear.php.net') {
                   48656:             // the registry is not properly set up, so use defaults
                   48657:             if (!class_exists('PEAR_ChannelFile')) {
                   48658:                 require_once 'PEAR/ChannelFile.php';
                   48659:             }
                   48660: 
                   48661:             $pear_channel = new PEAR_ChannelFile;
                   48662:             $pear_channel->setServer('pear.php.net');
                   48663:             $pear_channel->setAlias('pear');
                   48664:             $pear_channel->setSummary('PHP Extension and Application Repository');
                   48665:             $pear_channel->setDefaultPEARProtocols();
                   48666:             $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/');
                   48667:             $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/');
                   48668:             $pear_channel->setBaseURL('REST1.3', 'http://pear.php.net/rest/');
                   48669:             return $pear_channel;
                   48670:         }
                   48671: 
                   48672:         if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') {
                   48673:             // the registry is not properly set up, so use defaults
                   48674:             if (!class_exists('PEAR_ChannelFile')) {
                   48675:                 require_once 'PEAR/ChannelFile.php';
                   48676:             }
                   48677:             $pear_channel = new PEAR_ChannelFile;
                   48678:             $pear_channel->setServer('pecl.php.net');
                   48679:             $pear_channel->setAlias('pecl');
                   48680:             $pear_channel->setSummary('PHP Extension Community Library');
                   48681:             $pear_channel->setDefaultPEARProtocols();
                   48682:             $pear_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/');
                   48683:             $pear_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/');
                   48684:             $pear_channel->setValidationPackage('PEAR_Validator_PECL', '1.0');
                   48685:             return $pear_channel;
                   48686:         }
                   48687: 
                   48688:         if ($this->_getChannelFromAlias($channel) == 'doc.php.net') {
                   48689:             // the registry is not properly set up, so use defaults
                   48690:             if (!class_exists('PEAR_ChannelFile')) {
                   48691:                 require_once 'PEAR/ChannelFile.php';
                   48692:             }
                   48693: 
                   48694:             $doc_channel = new PEAR_ChannelFile;
                   48695:             $doc_channel->setServer('doc.php.net');
                   48696:             $doc_channel->setAlias('phpdocs');
                   48697:             $doc_channel->setSummary('PHP Documentation Team');
                   48698:             $doc_channel->setDefaultPEARProtocols();
                   48699:             $doc_channel->setBaseURL('REST1.0', 'http://doc.php.net/rest/');
                   48700:             $doc_channel->setBaseURL('REST1.1', 'http://doc.php.net/rest/');
                   48701:             $doc_channel->setBaseURL('REST1.3', 'http://doc.php.net/rest/');
                   48702:             return $doc_channel;
                   48703:         }
                   48704: 
                   48705: 
                   48706:         if ($this->_getChannelFromAlias($channel) == '__uri') {
                   48707:             // the registry is not properly set up, so use defaults
                   48708:             if (!class_exists('PEAR_ChannelFile')) {
                   48709:                 require_once 'PEAR/ChannelFile.php';
                   48710:             }
                   48711: 
                   48712:             $private = new PEAR_ChannelFile;
                   48713:             $private->setName('__uri');
                   48714:             $private->setDefaultPEARProtocols();
                   48715:             $private->setBaseURL('REST1.0', '****');
                   48716:             $private->setSummary('Pseudo-channel for static packages');
                   48717:             return $private;
                   48718:         }
                   48719: 
                   48720:         return $ch;
                   48721:     }
                   48722: 
                   48723:     /**
                   48724:      * @param string Package name
                   48725:      * @param string Channel name
                   48726:      * @return bool
                   48727:      */
                   48728:     function packageExists($package, $channel = 'pear.php.net')
                   48729:     {
                   48730:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48731:             return $e;
                   48732:         }
                   48733:         $ret = $this->_packageExists($package, $channel);
                   48734:         $this->_unlock();
                   48735:         return $ret;
                   48736:     }
                   48737: 
                   48738:     // }}}
                   48739: 
                   48740:     // {{{ channelExists()
                   48741: 
                   48742:     /**
                   48743:      * @param string channel name
                   48744:      * @param bool if true, then aliases will be ignored
                   48745:      * @return bool
                   48746:      */
                   48747:     function channelExists($channel, $noaliases = false)
                   48748:     {
                   48749:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48750:             return $e;
                   48751:         }
                   48752:         $ret = $this->_channelExists($channel, $noaliases);
                   48753:         $this->_unlock();
                   48754:         return $ret;
                   48755:     }
                   48756: 
                   48757:     // }}}
                   48758: 
                   48759:     /**
                   48760:      * @param string channel name mirror is in
                   48761:      * @param string mirror name
                   48762:      *
                   48763:      * @return bool
                   48764:      */
                   48765:     function mirrorExists($channel, $mirror)
                   48766:     {
                   48767:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48768:             return $e;
                   48769:         }
                   48770: 
                   48771:         $ret = $this->_mirrorExists($channel, $mirror);
                   48772:         $this->_unlock();
                   48773:         return $ret;
                   48774:     }
                   48775: 
                   48776:     // {{{ isAlias()
                   48777: 
                   48778:     /**
                   48779:      * Determines whether the parameter is an alias of a channel
                   48780:      * @param string
                   48781:      * @return bool
                   48782:      */
                   48783:     function isAlias($alias)
                   48784:     {
                   48785:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48786:             return $e;
                   48787:         }
                   48788:         $ret = $this->_isChannelAlias($alias);
                   48789:         $this->_unlock();
                   48790:         return $ret;
                   48791:     }
                   48792: 
                   48793:     // }}}
                   48794:     // {{{ packageInfo()
                   48795: 
                   48796:     /**
                   48797:      * @param string|null
                   48798:      * @param string|null
                   48799:      * @param string
                   48800:      * @return array|null
                   48801:      */
                   48802:     function packageInfo($package = null, $key = null, $channel = 'pear.php.net')
                   48803:     {
                   48804:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48805:             return $e;
                   48806:         }
                   48807:         $ret = $this->_packageInfo($package, $key, $channel);
                   48808:         $this->_unlock();
                   48809:         return $ret;
                   48810:     }
                   48811: 
                   48812:     // }}}
                   48813:     // {{{ channelInfo()
                   48814: 
                   48815:     /**
                   48816:      * Retrieve a raw array of channel data.
                   48817:      *
                   48818:      * Do not use this, instead use {@link getChannel()} for normal
                   48819:      * operations.  Array structure is undefined in this method
                   48820:      * @param string channel name
                   48821:      * @param bool whether to strictly retrieve information only on non-aliases
                   48822:      * @return array|null|PEAR_Error
                   48823:      */
                   48824:     function channelInfo($channel = null, $noaliases = false)
                   48825:     {
                   48826:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48827:             return $e;
                   48828:         }
                   48829:         $ret = $this->_channelInfo($channel, $noaliases);
                   48830:         $this->_unlock();
                   48831:         return $ret;
                   48832:     }
                   48833: 
                   48834:     // }}}
                   48835: 
                   48836:     /**
                   48837:      * @param string
                   48838:      */
                   48839:     function channelName($channel)
                   48840:     {
                   48841:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48842:             return $e;
                   48843:         }
                   48844:         $ret = $this->_getChannelFromAlias($channel);
                   48845:         $this->_unlock();
                   48846:         return $ret;
                   48847:     }
                   48848: 
                   48849:     /**
                   48850:      * @param string
                   48851:      */
                   48852:     function channelAlias($channel)
                   48853:     {
                   48854:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48855:             return $e;
                   48856:         }
                   48857:         $ret = $this->_getAlias($channel);
                   48858:         $this->_unlock();
                   48859:         return $ret;
                   48860:     }
                   48861:     // {{{ listPackages()
                   48862: 
                   48863:     function listPackages($channel = false)
                   48864:     {
                   48865:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48866:             return $e;
                   48867:         }
                   48868:         $ret = $this->_listPackages($channel);
                   48869:         $this->_unlock();
                   48870:         return $ret;
                   48871:     }
                   48872: 
                   48873:     // }}}
                   48874:     // {{{ listAllPackages()
                   48875: 
                   48876:     function listAllPackages()
                   48877:     {
                   48878:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48879:             return $e;
                   48880:         }
                   48881:         $ret = $this->_listAllPackages();
                   48882:         $this->_unlock();
                   48883:         return $ret;
                   48884:     }
                   48885: 
                   48886:     // }}}
                   48887:     // {{{ listChannel()
                   48888: 
                   48889:     function listChannels()
                   48890:     {
                   48891:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   48892:             return $e;
                   48893:         }
                   48894:         $ret = $this->_listChannels();
                   48895:         $this->_unlock();
                   48896:         return $ret;
                   48897:     }
                   48898: 
                   48899:     // }}}
                   48900:     // {{{ addPackage()
                   48901: 
                   48902:     /**
                   48903:      * Add an installed package to the registry
                   48904:      * @param string|PEAR_PackageFile_v1|PEAR_PackageFile_v2 package name or object
                   48905:      *               that will be passed to {@link addPackage2()}
                   48906:      * @param array package info (parsed by PEAR_Common::infoFrom*() methods)
                   48907:      * @return bool success of saving
                   48908:      */
                   48909:     function addPackage($package, $info)
                   48910:     {
                   48911:         if (is_object($info)) {
                   48912:             return $this->addPackage2($info);
                   48913:         }
                   48914:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   48915:             return $e;
                   48916:         }
                   48917:         $ret = $this->_addPackage($package, $info);
                   48918:         $this->_unlock();
                   48919:         if ($ret) {
                   48920:             if (!class_exists('PEAR_PackageFile_v1')) {
                   48921:                 require_once 'PEAR/PackageFile/v1.php';
                   48922:             }
                   48923:             $pf = new PEAR_PackageFile_v1;
                   48924:             $pf->setConfig($this->_config);
                   48925:             $pf->fromArray($info);
                   48926:             $this->_dependencyDB->uninstallPackage($pf);
                   48927:             $this->_dependencyDB->installPackage($pf);
                   48928:         }
                   48929:         return $ret;
                   48930:     }
                   48931: 
                   48932:     // }}}
                   48933:     // {{{ addPackage2()
                   48934: 
                   48935:     function addPackage2($info)
                   48936:     {
                   48937:         if (!is_object($info)) {
                   48938:             return $this->addPackage($info['package'], $info);
                   48939:         }
                   48940:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   48941:             return $e;
                   48942:         }
                   48943:         $ret = $this->_addPackage2($info);
                   48944:         $this->_unlock();
                   48945:         if ($ret) {
                   48946:             $this->_dependencyDB->uninstallPackage($info);
                   48947:             $this->_dependencyDB->installPackage($info);
                   48948:         }
                   48949:         return $ret;
                   48950:     }
                   48951: 
                   48952:     // }}}
                   48953:     // {{{ updateChannel()
                   48954: 
                   48955:     /**
                   48956:      * For future expandibility purposes, separate this
                   48957:      * @param PEAR_ChannelFile
                   48958:      */
                   48959:     function updateChannel($channel, $lastmodified = null)
                   48960:     {
                   48961:         if ($channel->getName() == '__uri') {
                   48962:             return false;
                   48963:         }
                   48964:         return $this->addChannel($channel, $lastmodified, true);
                   48965:     }
                   48966: 
                   48967:     // }}}
                   48968:     // {{{ deleteChannel()
                   48969: 
                   48970:     /**
                   48971:      * Deletion fails if there are any packages installed from the channel
                   48972:      * @param string|PEAR_ChannelFile channel name
                   48973:      * @return boolean|PEAR_Error True on deletion, false if it doesn't exist
                   48974:      */
                   48975:     function deleteChannel($channel)
                   48976:     {
                   48977:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   48978:             return $e;
                   48979:         }
                   48980: 
                   48981:         $ret = $this->_deleteChannel($channel);
                   48982:         $this->_unlock();
                   48983:         if ($ret && is_a($this->_config, 'PEAR_Config')) {
                   48984:             $this->_config->setChannels($this->listChannels());
                   48985:         }
                   48986: 
                   48987:         return $ret;
                   48988:     }
                   48989: 
                   48990:     // }}}
                   48991:     // {{{ addChannel()
                   48992: 
                   48993:     /**
                   48994:      * @param PEAR_ChannelFile Channel object
                   48995:      * @param string Last-Modified header from HTTP for caching
                   48996:      * @return boolean|PEAR_Error True on creation, false if it already exists
                   48997:      */
                   48998:     function addChannel($channel, $lastmodified = false, $update = false)
                   48999:     {
                   49000:         if (!is_a($channel, 'PEAR_ChannelFile') || !$channel->validate()) {
                   49001:             return false;
                   49002:         }
                   49003: 
                   49004:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   49005:             return $e;
                   49006:         }
                   49007: 
                   49008:         $ret = $this->_addChannel($channel, $update, $lastmodified);
                   49009:         $this->_unlock();
                   49010:         if (!$update && $ret && is_a($this->_config, 'PEAR_Config')) {
                   49011:             $this->_config->setChannels($this->listChannels());
                   49012:         }
                   49013: 
                   49014:         return $ret;
                   49015:     }
                   49016: 
                   49017:     // }}}
                   49018:     // {{{ deletePackage()
                   49019: 
                   49020:     function deletePackage($package, $channel = 'pear.php.net')
                   49021:     {
                   49022:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   49023:             return $e;
                   49024:         }
                   49025: 
                   49026:         $file = $this->_packageFileName($package, $channel);
                   49027:         $ret  = file_exists($file) ? @unlink($file) : false;
                   49028:         $this->_rebuildFileMap();
                   49029:         $this->_unlock();
                   49030:         $p = array('channel' => $channel, 'package' => $package);
                   49031:         $this->_dependencyDB->uninstallPackage($p);
                   49032:         return $ret;
                   49033:     }
                   49034: 
                   49035:     // }}}
                   49036:     // {{{ updatePackage()
                   49037: 
                   49038:     function updatePackage($package, $info, $merge = true)
                   49039:     {
                   49040:         if (is_object($info)) {
                   49041:             return $this->updatePackage2($info, $merge);
                   49042:         }
                   49043:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   49044:             return $e;
                   49045:         }
                   49046:         $ret = $this->_updatePackage($package, $info, $merge);
                   49047:         $this->_unlock();
                   49048:         if ($ret) {
                   49049:             if (!class_exists('PEAR_PackageFile_v1')) {
                   49050:                 require_once 'PEAR/PackageFile/v1.php';
                   49051:             }
                   49052:             $pf = new PEAR_PackageFile_v1;
                   49053:             $pf->setConfig($this->_config);
                   49054:             $pf->fromArray($this->packageInfo($package));
                   49055:             $this->_dependencyDB->uninstallPackage($pf);
                   49056:             $this->_dependencyDB->installPackage($pf);
                   49057:         }
                   49058:         return $ret;
                   49059:     }
                   49060: 
                   49061:     // }}}
                   49062:     // {{{ updatePackage2()
                   49063: 
                   49064:     function updatePackage2($info)
                   49065:     {
                   49066: 
                   49067:         if (!is_object($info)) {
                   49068:             return $this->updatePackage($info['package'], $info, $merge);
                   49069:         }
                   49070: 
                   49071:         if (!$info->validate(PEAR_VALIDATE_DOWNLOADING)) {
                   49072:             return false;
                   49073:         }
                   49074: 
                   49075:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
                   49076:             return $e;
                   49077:         }
                   49078: 
                   49079:         $ret = $this->_updatePackage2($info);
                   49080:         $this->_unlock();
                   49081:         if ($ret) {
                   49082:             $this->_dependencyDB->uninstallPackage($info);
                   49083:             $this->_dependencyDB->installPackage($info);
                   49084:         }
                   49085: 
                   49086:         return $ret;
                   49087:     }
                   49088: 
                   49089:     // }}}
                   49090:     // {{{ getChannel()
                   49091:     /**
                   49092:      * @param string channel name
                   49093:      * @param bool whether to strictly return raw channels (no aliases)
                   49094:      * @return PEAR_ChannelFile|PEAR_Error
                   49095:      */
                   49096:     function &getChannel($channel, $noaliases = false)
                   49097:     {
                   49098:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   49099:             return $e;
                   49100:         }
                   49101:         $ret = &$this->_getChannel($channel, $noaliases);
                   49102:         $this->_unlock();
                   49103:         if (!$ret) {
                   49104:             return PEAR::raiseError('Unknown channel: ' . $channel);
                   49105:         }
                   49106:         return $ret;
                   49107:     }
                   49108: 
                   49109:     // }}}
                   49110:     // {{{ getPackage()
                   49111:     /**
                   49112:      * @param string package name
                   49113:      * @param string channel name
                   49114:      * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
                   49115:      */
                   49116:     function &getPackage($package, $channel = 'pear.php.net')
                   49117:     {
                   49118:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   49119:             return $e;
                   49120:         }
                   49121:         $pf = &$this->_getPackage($package, $channel);
                   49122:         $this->_unlock();
                   49123:         return $pf;
                   49124:     }
                   49125: 
                   49126:     // }}}
                   49127: 
                   49128:     /**
                   49129:      * Get PEAR_PackageFile_v[1/2] objects representing the contents of
                   49130:      * a dependency group that are installed.
                   49131:      *
                   49132:      * This is used at uninstall-time
                   49133:      * @param array
                   49134:      * @return array|false
                   49135:      */
                   49136:     function getInstalledGroup($group)
                   49137:     {
                   49138:         $ret = array();
                   49139:         if (isset($group['package'])) {
                   49140:             if (!isset($group['package'][0])) {
                   49141:                 $group['package'] = array($group['package']);
                   49142:             }
                   49143:             foreach ($group['package'] as $package) {
                   49144:                 $depchannel = isset($package['channel']) ? $package['channel'] : '__uri';
                   49145:                 $p = &$this->getPackage($package['name'], $depchannel);
                   49146:                 if ($p) {
                   49147:                     $save = &$p;
                   49148:                     $ret[] = &$save;
                   49149:                 }
                   49150:             }
                   49151:         }
                   49152:         if (isset($group['subpackage'])) {
                   49153:             if (!isset($group['subpackage'][0])) {
                   49154:                 $group['subpackage'] = array($group['subpackage']);
                   49155:             }
                   49156:             foreach ($group['subpackage'] as $package) {
                   49157:                 $depchannel = isset($package['channel']) ? $package['channel'] : '__uri';
                   49158:                 $p = &$this->getPackage($package['name'], $depchannel);
                   49159:                 if ($p) {
                   49160:                     $save = &$p;
                   49161:                     $ret[] = &$save;
                   49162:                 }
                   49163:             }
                   49164:         }
                   49165:         if (!count($ret)) {
                   49166:             return false;
                   49167:         }
                   49168:         return $ret;
                   49169:     }
                   49170: 
                   49171:     // {{{ getChannelValidator()
                   49172:     /**
                   49173:      * @param string channel name
                   49174:      * @return PEAR_Validate|false
                   49175:      */
                   49176:     function &getChannelValidator($channel)
                   49177:     {
                   49178:         $chan = $this->getChannel($channel);
                   49179:         if (PEAR::isError($chan)) {
                   49180:             return $chan;
                   49181:         }
                   49182:         $val = $chan->getValidationObject();
                   49183:         return $val;
                   49184:     }
                   49185:     // }}}
                   49186:     // {{{ getChannels()
                   49187:     /**
                   49188:      * @param string channel name
                   49189:      * @return array an array of PEAR_ChannelFile objects representing every installed channel
                   49190:      */
                   49191:     function &getChannels()
                   49192:     {
                   49193:         $ret = array();
                   49194:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   49195:             return $e;
                   49196:         }
                   49197:         foreach ($this->_listChannels() as $channel) {
                   49198:             $e = &$this->_getChannel($channel);
                   49199:             if (!$e || PEAR::isError($e)) {
                   49200:                 continue;
                   49201:             }
                   49202:             $ret[] = $e;
                   49203:         }
                   49204:         $this->_unlock();
                   49205:         return $ret;
                   49206:     }
                   49207: 
                   49208:     // }}}
                   49209:     // {{{ checkFileMap()
                   49210: 
                   49211:     /**
                   49212:      * Test whether a file or set of files belongs to a package.
                   49213:      *
                   49214:      * If an array is passed in
                   49215:      * @param string|array file path, absolute or relative to the pear
                   49216:      *                     install dir
                   49217:      * @param string|array name of PEAR package or array('package' => name, 'channel' =>
                   49218:      *                     channel) of a package that will be ignored
                   49219:      * @param string API version - 1.1 will exclude any files belonging to a package
                   49220:      * @param array private recursion variable
                   49221:      * @return array|false which package and channel the file belongs to, or an empty
                   49222:      *                     string if the file does not belong to an installed package,
                   49223:      *                     or belongs to the second parameter's package
                   49224:      */
                   49225:     function checkFileMap($path, $package = false, $api = '1.0', $attrs = false)
                   49226:     {
                   49227:         if (is_array($path)) {
                   49228:             static $notempty;
                   49229:             if (empty($notempty)) {
                   49230:                 if (!class_exists('PEAR_Installer_Role')) {
                   49231:                     require_once 'PEAR/Installer/Role.php';
                   49232:                 }
                   49233:                 $notempty = create_function('$a','return !empty($a);');
                   49234:             }
                   49235:             $package = is_array($package) ? array(strtolower($package[0]), strtolower($package[1]))
                   49236:                 : strtolower($package);
                   49237:             $pkgs = array();
                   49238:             foreach ($path as $name => $attrs) {
                   49239:                 if (is_array($attrs)) {
                   49240:                     if (isset($attrs['install-as'])) {
                   49241:                         $name = $attrs['install-as'];
                   49242:                     }
                   49243:                     if (!in_array($attrs['role'], PEAR_Installer_Role::getInstallableRoles())) {
                   49244:                         // these are not installed
                   49245:                         continue;
                   49246:                     }
                   49247:                     if (!in_array($attrs['role'], PEAR_Installer_Role::getBaseinstallRoles())) {
                   49248:                         $attrs['baseinstalldir'] = is_array($package) ? $package[1] : $package;
                   49249:                     }
                   49250:                     if (isset($attrs['baseinstalldir'])) {
                   49251:                         $name = $attrs['baseinstalldir'] . DIRECTORY_SEPARATOR . $name;
                   49252:                     }
                   49253:                 }
                   49254:                 $pkgs[$name] = $this->checkFileMap($name, $package, $api, $attrs);
                   49255:                 if (PEAR::isError($pkgs[$name])) {
                   49256:                     return $pkgs[$name];
                   49257:                 }
                   49258:             }
                   49259:             return array_filter($pkgs, $notempty);
                   49260:         }
                   49261:         if (empty($this->filemap_cache)) {
                   49262:             if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
                   49263:                 return $e;
                   49264:             }
                   49265:             $err = $this->_readFileMap();
                   49266:             $this->_unlock();
                   49267:             if (PEAR::isError($err)) {
                   49268:                 return $err;
                   49269:             }
                   49270:         }
                   49271:         if (!$attrs) {
                   49272:             $attrs = array('role' => 'php'); // any old call would be for PHP role only
                   49273:         }
                   49274:         if (isset($this->filemap_cache[$attrs['role']][$path])) {
                   49275:             if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) {
                   49276:                 return false;
                   49277:             }
                   49278:             return $this->filemap_cache[$attrs['role']][$path];
                   49279:         }
                   49280:         $l = strlen($this->install_dir);
                   49281:         if (substr($path, 0, $l) == $this->install_dir) {
                   49282:             $path = preg_replace('!^'.DIRECTORY_SEPARATOR.'+!', '', substr($path, $l));
                   49283:         }
                   49284:         if (isset($this->filemap_cache[$attrs['role']][$path])) {
                   49285:             if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) {
                   49286:                 return false;
                   49287:             }
                   49288:             return $this->filemap_cache[$attrs['role']][$path];
                   49289:         }
                   49290:         return false;
                   49291:     }
                   49292: 
                   49293:     // }}}
                   49294:     // {{{ flush()
                   49295:     /**
                   49296:      * Force a reload of the filemap
                   49297:      * @since 1.5.0RC3
                   49298:      */
                   49299:     function flushFileMap()
                   49300:     {
                   49301:         $this->filemap_cache = null;
                   49302:         clearstatcache(); // ensure that the next read gets the full, current filemap
                   49303:     }
                   49304: 
                   49305:     // }}}
                   49306:     // {{{ apiVersion()
                   49307:     /**
                   49308:      * Get the expected API version.  Channels API is version 1.1, as it is backwards
                   49309:      * compatible with 1.0
                   49310:      * @return string
                   49311:      */
                   49312:     function apiVersion()
                   49313:     {
                   49314:         return '1.1';
                   49315:     }
                   49316:     // }}}
                   49317: 
                   49318: 
                   49319:     /**
                   49320:      * Parse a package name, or validate a parsed package name array
                   49321:      * @param string|array pass in an array of format
                   49322:      *                     array(
                   49323:      *                      'package' => 'pname',
                   49324:      *                     ['channel' => 'channame',]
                   49325:      *                     ['version' => 'version',]
                   49326:      *                     ['state' => 'state',]
                   49327:      *                     ['group' => 'groupname'])
                   49328:      *                     or a string of format
                   49329:      *                     [channel://][channame/]pname[-version|-state][/group=groupname]
                   49330:      * @return array|PEAR_Error
                   49331:      */
                   49332:     function parsePackageName($param, $defaultchannel = 'pear.php.net')
                   49333:     {
                   49334:         $saveparam = $param;
                   49335:         if (is_array($param)) {
                   49336:             // convert to string for error messages
                   49337:             $saveparam = $this->parsedPackageNameToString($param);
                   49338:             // process the array
                   49339:             if (!isset($param['package'])) {
                   49340:                 return PEAR::raiseError('parsePackageName(): array $param ' .
                   49341:                     'must contain a valid package name in index "param"',
                   49342:                     'package', null, null, $param);
                   49343:             }
                   49344:             if (!isset($param['uri'])) {
                   49345:                 if (!isset($param['channel'])) {
                   49346:                     $param['channel'] = $defaultchannel;
                   49347:                 }
                   49348:             } else {
                   49349:                 $param['channel'] = '__uri';
                   49350:             }
                   49351:         } else {
                   49352:             $components = @parse_url((string) $param);
                   49353:             if (isset($components['scheme'])) {
                   49354:                 if ($components['scheme'] == 'http') {
                   49355:                     // uri package
                   49356:                     $param = array('uri' => $param, 'channel' => '__uri');
                   49357:                 } elseif($components['scheme'] != 'channel') {
                   49358:                     return PEAR::raiseError('parsePackageName(): only channel:// uris may ' .
                   49359:                         'be downloaded, not "' . $param . '"', 'invalid', null, null, $param);
                   49360:                 }
                   49361:             }
                   49362:             if (!isset($components['path'])) {
                   49363:                 return PEAR::raiseError('parsePackageName(): array $param ' .
                   49364:                     'must contain a valid package name in "' . $param . '"',
                   49365:                     'package', null, null, $param);
                   49366:             }
                   49367:             if (isset($components['host'])) {
                   49368:                 // remove the leading "/"
                   49369:                 $components['path'] = substr($components['path'], 1);
                   49370:             }
                   49371:             if (!isset($components['scheme'])) {
                   49372:                 if (strpos($components['path'], '/') !== false) {
                   49373:                     if ($components['path']{0} == '/') {
                   49374:                         return PEAR::raiseError('parsePackageName(): this is not ' .
                   49375:                             'a package name, it begins with "/" in "' . $param . '"',
                   49376:                             'invalid', null, null, $param);
                   49377:                     }
                   49378:                     $parts = explode('/', $components['path']);
                   49379:                     $components['host'] = array_shift($parts);
                   49380:                     if (count($parts) > 1) {
                   49381:                         $components['path'] = array_pop($parts);
                   49382:                         $components['host'] .= '/' . implode('/', $parts);
                   49383:                     } else {
                   49384:                         $components['path'] = implode('/', $parts);
                   49385:                     }
                   49386:                 } else {
                   49387:                     $components['host'] = $defaultchannel;
                   49388:                 }
                   49389:             } else {
                   49390:                 if (strpos($components['path'], '/')) {
                   49391:                     $parts = explode('/', $components['path']);
                   49392:                     $components['path'] = array_pop($parts);
                   49393:                     $components['host'] .= '/' . implode('/', $parts);
                   49394:                 }
                   49395:             }
                   49396: 
                   49397:             if (is_array($param)) {
                   49398:                 $param['package'] = $components['path'];
                   49399:             } else {
                   49400:                 $param = array(
                   49401:                     'package' => $components['path']
                   49402:                     );
                   49403:                 if (isset($components['host'])) {
                   49404:                     $param['channel'] = $components['host'];
                   49405:                 }
                   49406:             }
                   49407:             if (isset($components['fragment'])) {
                   49408:                 $param['group'] = $components['fragment'];
                   49409:             }
                   49410:             if (isset($components['user'])) {
                   49411:                 $param['user'] = $components['user'];
                   49412:             }
                   49413:             if (isset($components['pass'])) {
                   49414:                 $param['pass'] = $components['pass'];
                   49415:             }
                   49416:             if (isset($components['query'])) {
                   49417:                 parse_str($components['query'], $param['opts']);
                   49418:             }
                   49419:             // check for extension
                   49420:             $pathinfo = pathinfo($param['package']);
                   49421:             if (isset($pathinfo['extension']) &&
                   49422:                   in_array(strtolower($pathinfo['extension']), array('tgz', 'tar'))) {
                   49423:                 $param['extension'] = $pathinfo['extension'];
                   49424:                 $param['package'] = substr($pathinfo['basename'], 0,
                   49425:                     strlen($pathinfo['basename']) - 4);
                   49426:             }
                   49427:             // check for version
                   49428:             if (strpos($param['package'], '-')) {
                   49429:                 $test = explode('-', $param['package']);
                   49430:                 if (count($test) != 2) {
                   49431:                     return PEAR::raiseError('parsePackageName(): only one version/state ' .
                   49432:                         'delimiter "-" is allowed in "' . $saveparam . '"',
                   49433:                         'version', null, null, $param);
                   49434:                 }
                   49435:                 list($param['package'], $param['version']) = $test;
                   49436:             }
                   49437:         }
                   49438:         // validation
                   49439:         $info = $this->channelExists($param['channel']);
                   49440:         if (PEAR::isError($info)) {
                   49441:             return $info;
                   49442:         }
                   49443:         if (!$info) {
                   49444:             return PEAR::raiseError('unknown channel "' . $param['channel'] .
                   49445:                 '" in "' . $saveparam . '"', 'channel', null, null, $param);
                   49446:         }
                   49447:         $chan = $this->getChannel($param['channel']);
                   49448:         if (PEAR::isError($chan)) {
                   49449:             return $chan;
                   49450:         }
                   49451:         if (!$chan) {
                   49452:             return PEAR::raiseError("Exception: corrupt registry, could not " .
                   49453:                 "retrieve channel " . $param['channel'] . " information",
                   49454:                 'registry', null, null, $param);
                   49455:         }
                   49456:         $param['channel'] = $chan->getName();
                   49457:         $validate = $chan->getValidationObject();
                   49458:         $vpackage = $chan->getValidationPackage();
                   49459:         // validate package name
                   49460:         if (!$validate->validPackageName($param['package'], $vpackage['_content'])) {
                   49461:             return PEAR::raiseError('parsePackageName(): invalid package name "' .
                   49462:                 $param['package'] . '" in "' . $saveparam . '"',
                   49463:                 'package', null, null, $param);
                   49464:         }
                   49465:         if (isset($param['group'])) {
                   49466:             if (!PEAR_Validate::validGroupName($param['group'])) {
                   49467:                 return PEAR::raiseError('parsePackageName(): dependency group "' . $param['group'] .
                   49468:                     '" is not a valid group name in "' . $saveparam . '"', 'group', null, null,
                   49469:                     $param);
                   49470:             }
                   49471:         }
                   49472:         if (isset($param['state'])) {
                   49473:             if (!in_array(strtolower($param['state']), $validate->getValidStates())) {
                   49474:                 return PEAR::raiseError('parsePackageName(): state "' . $param['state']
                   49475:                     . '" is not a valid state in "' . $saveparam . '"',
                   49476:                     'state', null, null, $param);
                   49477:             }
                   49478:         }
                   49479:         if (isset($param['version'])) {
                   49480:             if (isset($param['state'])) {
                   49481:                 return PEAR::raiseError('parsePackageName(): cannot contain both ' .
                   49482:                     'a version and a stability (state) in "' . $saveparam . '"',
                   49483:                     'version/state', null, null, $param);
                   49484:             }
                   49485:             // check whether version is actually a state
                   49486:             if (in_array(strtolower($param['version']), $validate->getValidStates())) {
                   49487:                 $param['state'] = strtolower($param['version']);
                   49488:                 unset($param['version']);
                   49489:             } else {
                   49490:                 if (!$validate->validVersion($param['version'])) {
                   49491:                     return PEAR::raiseError('parsePackageName(): "' . $param['version'] .
                   49492:                         '" is neither a valid version nor a valid state in "' .
                   49493:                         $saveparam . '"', 'version/state', null, null, $param);
                   49494:                 }
                   49495:             }
                   49496:         }
                   49497:         return $param;
                   49498:     }
                   49499: 
                   49500:     /**
                   49501:      * @param array
                   49502:      * @return string
                   49503:      */
                   49504:     function parsedPackageNameToString($parsed, $brief = false)
                   49505:     {
                   49506:         if (is_string($parsed)) {
                   49507:             return $parsed;
                   49508:         }
                   49509:         if (is_object($parsed)) {
                   49510:             $p = $parsed;
                   49511:             $parsed = array(
                   49512:                 'package' => $p->getPackage(),
                   49513:                 'channel' => $p->getChannel(),
                   49514:                 'version' => $p->getVersion(),
                   49515:             );
                   49516:         }
                   49517:         if (isset($parsed['uri'])) {
                   49518:             return $parsed['uri'];
                   49519:         }
                   49520:         if ($brief) {
                   49521:             if ($channel = $this->channelAlias($parsed['channel'])) {
                   49522:                 return $channel . '/' . $parsed['package'];
                   49523:             }
                   49524:         }
                   49525:         $upass = '';
                   49526:         if (isset($parsed['user'])) {
                   49527:             $upass = $parsed['user'];
                   49528:             if (isset($parsed['pass'])) {
                   49529:                 $upass .= ':' . $parsed['pass'];
                   49530:             }
                   49531:             $upass = "$upass@";
                   49532:         }
                   49533:         $ret = 'channel://' . $upass . $parsed['channel'] . '/' . $parsed['package'];
                   49534:         if (isset($parsed['version']) || isset($parsed['state'])) {
                   49535:             $ver = isset($parsed['version']) ? $parsed['version'] : '';
                   49536:             $ver .= isset($parsed['state']) ? $parsed['state'] : '';
                   49537:             $ret .= '-' . $ver;
                   49538:         }
                   49539:         if (isset($parsed['extension'])) {
                   49540:             $ret .= '.' . $parsed['extension'];
                   49541:         }
                   49542:         if (isset($parsed['opts'])) {
                   49543:             $ret .= '?';
                   49544:             foreach ($parsed['opts'] as $name => $value) {
                   49545:                 $parsed['opts'][$name] = "$name=$value";
                   49546:             }
                   49547:             $ret .= implode('&', $parsed['opts']);
                   49548:         }
                   49549:         if (isset($parsed['group'])) {
                   49550:             $ret .= '#' . $parsed['group'];
                   49551:         }
                   49552:         return $ret;
                   49553:     }
1.1.1.2 ! misho    49554: }PEAR-1.9.4/PEAR/REST.php0000644000076500000240000004151711605156614013261 0ustar  helgistaff<?php
1.1       misho    49555: /**
                   49556:  * PEAR_REST
                   49557:  *
                   49558:  * PHP versions 4 and 5
                   49559:  *
                   49560:  * @category   pear
                   49561:  * @package    PEAR
                   49562:  * @author     Greg Beaver <cellog@php.net>
                   49563:  * @copyright  1997-2009 The Authors
                   49564:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   49565:  * @version    CVS: $Id: REST.php 313023 2011-07-06 19:17:11Z dufuz $
                   49566:  * @link       http://pear.php.net/package/PEAR
                   49567:  * @since      File available since Release 1.4.0a1
                   49568:  */
                   49569: 
                   49570: /**
                   49571:  * For downloading xml files
                   49572:  */
                   49573: require_once 'PEAR.php';
                   49574: require_once 'PEAR/XMLParser.php';
                   49575: 
                   49576: /**
                   49577:  * Intelligently retrieve data, following hyperlinks if necessary, and re-directing
                   49578:  * as well
                   49579:  * @category   pear
                   49580:  * @package    PEAR
                   49581:  * @author     Greg Beaver <cellog@php.net>
                   49582:  * @copyright  1997-2009 The Authors
                   49583:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   49584:  * @version    Release: 1.9.4
                   49585:  * @link       http://pear.php.net/package/PEAR
                   49586:  * @since      Class available since Release 1.4.0a1
                   49587:  */
                   49588: class PEAR_REST
                   49589: {
                   49590:     var $config;
                   49591:     var $_options;
                   49592: 
                   49593:     function PEAR_REST(&$config, $options = array())
                   49594:     {
                   49595:         $this->config   = &$config;
                   49596:         $this->_options = $options;
                   49597:     }
                   49598: 
                   49599:     /**
                   49600:      * Retrieve REST data, but always retrieve the local cache if it is available.
                   49601:      *
                   49602:      * This is useful for elements that should never change, such as information on a particular
                   49603:      * release
                   49604:      * @param string full URL to this resource
                   49605:      * @param array|false contents of the accept-encoding header
                   49606:      * @param boolean     if true, xml will be returned as a string, otherwise, xml will be
                   49607:      *                    parsed using PEAR_XMLParser
                   49608:      * @return string|array
                   49609:      */
                   49610:     function retrieveCacheFirst($url, $accept = false, $forcestring = false, $channel = false)
                   49611:     {
                   49612:         $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
                   49613:             md5($url) . 'rest.cachefile';
                   49614: 
                   49615:         if (file_exists($cachefile)) {
                   49616:             return unserialize(implode('', file($cachefile)));
                   49617:         }
                   49618: 
                   49619:         return $this->retrieveData($url, $accept, $forcestring, $channel);
                   49620:     }
                   49621: 
                   49622:     /**
                   49623:      * Retrieve a remote REST resource
                   49624:      * @param string full URL to this resource
                   49625:      * @param array|false contents of the accept-encoding header
                   49626:      * @param boolean     if true, xml will be returned as a string, otherwise, xml will be
                   49627:      *                    parsed using PEAR_XMLParser
                   49628:      * @return string|array
                   49629:      */
                   49630:     function retrieveData($url, $accept = false, $forcestring = false, $channel = false)
                   49631:     {
                   49632:         $cacheId = $this->getCacheId($url);
                   49633:         if ($ret = $this->useLocalCache($url, $cacheId)) {
                   49634:             return $ret;
                   49635:         }
                   49636: 
                   49637:         $file = $trieddownload = false;
                   49638:         if (!isset($this->_options['offline'])) {
                   49639:             $trieddownload = true;
                   49640:             $file = $this->downloadHttp($url, $cacheId ? $cacheId['lastChange'] : false, $accept, $channel);
                   49641:         }
                   49642: 
                   49643:         if (PEAR::isError($file)) {
                   49644:             if ($file->getCode() !== -9276) {
                   49645:                 return $file;
                   49646:             }
                   49647: 
                   49648:             $trieddownload = false;
                   49649:             $file = false; // use local copy if available on socket connect error
                   49650:         }
                   49651: 
                   49652:         if (!$file) {
                   49653:             $ret = $this->getCache($url);
                   49654:             if (!PEAR::isError($ret) && $trieddownload) {
                   49655:                 // reset the age of the cache if the server says it was unmodified
                   49656:                 $result = $this->saveCache($url, $ret, null, true, $cacheId);
                   49657:                 if (PEAR::isError($result)) {
                   49658:                     return PEAR::raiseError($result->getMessage());
                   49659:                 }
                   49660:             }
                   49661: 
                   49662:             return $ret;
                   49663:         }
                   49664: 
                   49665:         if (is_array($file)) {
                   49666:             $headers      = $file[2];
                   49667:             $lastmodified = $file[1];
                   49668:             $content      = $file[0];
                   49669:         } else {
                   49670:             $headers      = array();
                   49671:             $lastmodified = false;
                   49672:             $content      = $file;
                   49673:         }
                   49674: 
                   49675:         if ($forcestring) {
                   49676:             $result = $this->saveCache($url, $content, $lastmodified, false, $cacheId);
                   49677:             if (PEAR::isError($result)) {
                   49678:                 return PEAR::raiseError($result->getMessage());
                   49679:             }
                   49680: 
                   49681:             return $content;
                   49682:         }
                   49683: 
                   49684:         if (isset($headers['content-type'])) {
                   49685:             switch ($headers['content-type']) {
                   49686:                 case 'text/xml' :
                   49687:                 case 'application/xml' :
                   49688:                 case 'text/plain' :
                   49689:                     if ($headers['content-type'] === 'text/plain') {
                   49690:                         $check = substr($content, 0, 5);
                   49691:                         if ($check !== '<?xml') {
                   49692:                             break;
                   49693:                         }
                   49694:                     }
                   49695: 
                   49696:                     $parser = new PEAR_XMLParser;
                   49697:                     PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   49698:                     $err = $parser->parse($content);
                   49699:                     PEAR::popErrorHandling();
                   49700:                     if (PEAR::isError($err)) {
                   49701:                         return PEAR::raiseError('Invalid xml downloaded from "' . $url . '": ' .
                   49702:                             $err->getMessage());
                   49703:                     }
                   49704:                     $content = $parser->getData();
                   49705:                 case 'text/html' :
                   49706:                 default :
                   49707:                     // use it as a string
                   49708:             }
                   49709:         } else {
                   49710:             // assume XML
                   49711:             $parser = new PEAR_XMLParser;
                   49712:             $parser->parse($content);
                   49713:             $content = $parser->getData();
                   49714:         }
                   49715: 
                   49716:         $result = $this->saveCache($url, $content, $lastmodified, false, $cacheId);
                   49717:         if (PEAR::isError($result)) {
                   49718:             return PEAR::raiseError($result->getMessage());
                   49719:         }
                   49720: 
                   49721:         return $content;
                   49722:     }
                   49723: 
                   49724:     function useLocalCache($url, $cacheid = null)
                   49725:     {
                   49726:         if ($cacheid === null) {
                   49727:             $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
                   49728:                 md5($url) . 'rest.cacheid';
                   49729:             if (!file_exists($cacheidfile)) {
                   49730:                 return false;
                   49731:             }
                   49732: 
                   49733:             $cacheid = unserialize(implode('', file($cacheidfile)));
                   49734:         }
                   49735: 
                   49736:         $cachettl = $this->config->get('cache_ttl');
                   49737:         // If cache is newer than $cachettl seconds, we use the cache!
                   49738:         if (time() - $cacheid['age'] < $cachettl) {
                   49739:             return $this->getCache($url);
                   49740:         }
                   49741: 
                   49742:         return false;
                   49743:     }
                   49744: 
                   49745:     function getCacheId($url)
                   49746:     {
                   49747:         $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
                   49748:             md5($url) . 'rest.cacheid';
                   49749: 
                   49750:         if (!file_exists($cacheidfile)) {
                   49751:             return false;
                   49752:         }
                   49753: 
                   49754:         $ret = unserialize(implode('', file($cacheidfile)));
                   49755:         return $ret;
                   49756:     }
                   49757: 
                   49758:     function getCache($url)
                   49759:     {
                   49760:         $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
                   49761:             md5($url) . 'rest.cachefile';
                   49762: 
                   49763:         if (!file_exists($cachefile)) {
                   49764:             return PEAR::raiseError('No cached content available for "' . $url . '"');
                   49765:         }
                   49766: 
                   49767:         return unserialize(implode('', file($cachefile)));
                   49768:     }
                   49769: 
                   49770:     /**
                   49771:      * @param string full URL to REST resource
                   49772:      * @param string original contents of the REST resource
                   49773:      * @param array  HTTP Last-Modified and ETag headers
                   49774:      * @param bool   if true, then the cache id file should be regenerated to
                   49775:      *               trigger a new time-to-live value
                   49776:      */
                   49777:     function saveCache($url, $contents, $lastmodified, $nochange = false, $cacheid = null)
                   49778:     {
                   49779:         $cache_dir   = $this->config->get('cache_dir');
                   49780:         $d           = $cache_dir . DIRECTORY_SEPARATOR . md5($url);
                   49781:         $cacheidfile = $d . 'rest.cacheid';
                   49782:         $cachefile   = $d . 'rest.cachefile';
                   49783: 
                   49784:         if (!is_dir($cache_dir)) {
                   49785:             if (System::mkdir(array('-p', $cache_dir)) === false) {
                   49786:               return PEAR::raiseError("The value of config option cache_dir ($cache_dir) is not a directory and attempts to create the directory failed.");
                   49787:             }
                   49788:         }
                   49789: 
                   49790:         if ($cacheid === null && $nochange) {
                   49791:             $cacheid = unserialize(implode('', file($cacheidfile)));
                   49792:         }
                   49793: 
                   49794:         $idData = serialize(array(
                   49795:             'age'        => time(),
                   49796:             'lastChange' => ($nochange ? $cacheid['lastChange'] : $lastmodified),
                   49797:         ));
                   49798: 
                   49799:         $result = $this->saveCacheFile($cacheidfile, $idData);
                   49800:         if (PEAR::isError($result)) {
                   49801:             return $result;
                   49802:         } elseif ($nochange) {
                   49803:             return true;
                   49804:         }
                   49805: 
                   49806:         $result = $this->saveCacheFile($cachefile, serialize($contents));
                   49807:         if (PEAR::isError($result)) {
                   49808:             if (file_exists($cacheidfile)) {
                   49809:               @unlink($cacheidfile);
                   49810:             }
                   49811: 
                   49812:             return $result;
                   49813:         }
                   49814: 
                   49815:         return true;
                   49816:     }
                   49817: 
                   49818:     function saveCacheFile($file, $contents)
                   49819:     {
                   49820:         $len = strlen($contents);
                   49821: 
                   49822:         $cachefile_fp = @fopen($file, 'xb'); // x is the O_CREAT|O_EXCL mode
                   49823:         if ($cachefile_fp !== false) { // create file
                   49824:             if (fwrite($cachefile_fp, $contents, $len) < $len) {
                   49825:                 fclose($cachefile_fp);
                   49826:                 return PEAR::raiseError("Could not write $file.");
                   49827:             }
                   49828:         } else { // update file
                   49829:             $cachefile_lstat = lstat($file);
                   49830:             $cachefile_fp = @fopen($file, 'wb');
                   49831:             if (!$cachefile_fp) {
                   49832:                 return PEAR::raiseError("Could not open $file for writing.");
                   49833:             }
                   49834: 
                   49835:             $cachefile_fstat = fstat($cachefile_fp);
                   49836:             if (
                   49837:               $cachefile_lstat['mode'] == $cachefile_fstat['mode'] &&
                   49838:               $cachefile_lstat['ino']  == $cachefile_fstat['ino'] &&
                   49839:               $cachefile_lstat['dev']  == $cachefile_fstat['dev'] &&
                   49840:               $cachefile_fstat['nlink'] === 1
                   49841:             ) {
                   49842:                 if (fwrite($cachefile_fp, $contents, $len) < $len) {
                   49843:                     fclose($cachefile_fp);
                   49844:                     return PEAR::raiseError("Could not write $file.");
                   49845:                 }
                   49846:             } else {
                   49847:                 fclose($cachefile_fp);
                   49848:                 $link = function_exists('readlink') ? readlink($file) : $file;
                   49849:                 return PEAR::raiseError('SECURITY ERROR: Will not write to ' . $file . ' as it is symlinked to ' . $link . ' - Possible symlink attack');
                   49850:             }
                   49851:         }
                   49852: 
                   49853:         fclose($cachefile_fp);
                   49854:         return true;
                   49855:     }
                   49856: 
                   49857:     /**
                   49858:      * Efficiently Download a file through HTTP.  Returns downloaded file as a string in-memory
                   49859:      * This is best used for small files
                   49860:      *
                   49861:      * If an HTTP proxy has been configured (http_proxy PEAR_Config
                   49862:      * setting), the proxy will be used.
                   49863:      *
                   49864:      * @param string  $url       the URL to download
                   49865:      * @param string  $save_dir  directory to save file in
                   49866:      * @param false|string|array $lastmodified header values to check against for caching
                   49867:      *                           use false to return the header values from this download
                   49868:      * @param false|array $accept Accept headers to send
                   49869:      * @return string|array  Returns the contents of the downloaded file or a PEAR
                   49870:      *                       error on failure.  If the error is caused by
                   49871:      *                       socket-related errors, the error object will
                   49872:      *                       have the fsockopen error code available through
                   49873:      *                       getCode().  If caching is requested, then return the header
                   49874:      *                       values.
                   49875:      *
                   49876:      * @access public
                   49877:      */
                   49878:     function downloadHttp($url, $lastmodified = null, $accept = false, $channel = false)
                   49879:     {
                   49880:         static $redirect = 0;
                   49881:         // always reset , so we are clean case of error
                   49882:         $wasredirect = $redirect;
                   49883:         $redirect = 0;
                   49884: 
                   49885:         $info = parse_url($url);
                   49886:         if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) {
                   49887:             return PEAR::raiseError('Cannot download non-http URL "' . $url . '"');
                   49888:         }
                   49889: 
                   49890:         if (!isset($info['host'])) {
                   49891:             return PEAR::raiseError('Cannot download from non-URL "' . $url . '"');
                   49892:         }
                   49893: 
                   49894:         $host   = isset($info['host']) ? $info['host'] : null;
                   49895:         $port   = isset($info['port']) ? $info['port'] : null;
                   49896:         $path   = isset($info['path']) ? $info['path'] : null;
                   49897:         $schema = (isset($info['scheme']) && $info['scheme'] == 'https') ? 'https' : 'http';
                   49898: 
                   49899:         $proxy_host = $proxy_port = $proxy_user = $proxy_pass = '';
                   49900:         if ($this->config->get('http_proxy')&&
                   49901:               $proxy = parse_url($this->config->get('http_proxy'))
                   49902:         ) {
                   49903:             $proxy_host = isset($proxy['host']) ? $proxy['host'] : null;
                   49904:             if ($schema === 'https') {
                   49905:                 $proxy_host = 'ssl://' . $proxy_host;
                   49906:             }
                   49907: 
                   49908:             $proxy_port   = isset($proxy['port']) ? $proxy['port'] : 8080;
                   49909:             $proxy_user   = isset($proxy['user']) ? urldecode($proxy['user']) : null;
                   49910:             $proxy_pass   = isset($proxy['pass']) ? urldecode($proxy['pass']) : null;
                   49911:             $proxy_schema = (isset($proxy['scheme']) && $proxy['scheme'] == 'https') ? 'https' : 'http';
                   49912:         }
                   49913: 
                   49914:         if (empty($port)) {
                   49915:             $port = (isset($info['scheme']) && $info['scheme'] == 'https')  ? 443 : 80;
                   49916:         }
                   49917: 
                   49918:         if (isset($proxy['host'])) {
                   49919:             $request = "GET $url HTTP/1.1\r\n";
                   49920:         } else {
                   49921:             $request = "GET $path HTTP/1.1\r\n";
                   49922:         }
                   49923: 
                   49924:         $request .= "Host: $host\r\n";
                   49925:         $ifmodifiedsince = '';
                   49926:         if (is_array($lastmodified)) {
                   49927:             if (isset($lastmodified['Last-Modified'])) {
                   49928:                 $ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n";
                   49929:             }
                   49930: 
                   49931:             if (isset($lastmodified['ETag'])) {
                   49932:                 $ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n";
                   49933:             }
                   49934:         } else {
                   49935:             $ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : '');
                   49936:         }
                   49937: 
                   49938:         $request .= $ifmodifiedsince .
                   49939:             "User-Agent: PEAR/1.9.4/PHP/" . PHP_VERSION . "\r\n";
                   49940: 
                   49941:         $username = $this->config->get('username', null, $channel);
                   49942:         $password = $this->config->get('password', null, $channel);
                   49943: 
                   49944:         if ($username && $password) {
                   49945:             $tmp = base64_encode("$username:$password");
                   49946:             $request .= "Authorization: Basic $tmp\r\n";
                   49947:         }
                   49948: 
                   49949:         if ($proxy_host != '' && $proxy_user != '') {
                   49950:             $request .= 'Proxy-Authorization: Basic ' .
                   49951:                 base64_encode($proxy_user . ':' . $proxy_pass) . "\r\n";
                   49952:         }
                   49953: 
                   49954:         if ($accept) {
                   49955:             $request .= 'Accept: ' . implode(', ', $accept) . "\r\n";
                   49956:         }
                   49957: 
                   49958:         $request .= "Accept-Encoding:\r\n";
                   49959:         $request .= "Connection: close\r\n";
                   49960:         $request .= "\r\n";
                   49961: 
                   49962:         if ($proxy_host != '') {
                   49963:             $fp = @fsockopen($proxy_host, $proxy_port, $errno, $errstr, 15);
                   49964:             if (!$fp) {
                   49965:                 return PEAR::raiseError("Connection to `$proxy_host:$proxy_port' failed: $errstr", -9276);
                   49966:             }
                   49967:         } else {
                   49968:             if ($schema === 'https') {
                   49969:                 $host = 'ssl://' . $host;
                   49970:             }
                   49971: 
                   49972:             $fp = @fsockopen($host, $port, $errno, $errstr);
                   49973:             if (!$fp) {
                   49974:                 return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno);
                   49975:             }
                   49976:         }
                   49977: 
                   49978:         fwrite($fp, $request);
                   49979: 
                   49980:         $headers = array();
                   49981:         $reply   = 0;
                   49982:         while ($line = trim(fgets($fp, 1024))) {
                   49983:             if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) {
                   49984:                 $headers[strtolower($matches[1])] = trim($matches[2]);
                   49985:             } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) {
                   49986:                 $reply = (int)$matches[1];
                   49987:                 if ($reply == 304 && ($lastmodified || ($lastmodified === false))) {
                   49988:                     return false;
                   49989:                 }
                   49990: 
                   49991:                 if (!in_array($reply, array(200, 301, 302, 303, 305, 307))) {
                   49992:                     return PEAR::raiseError("File $schema://$host:$port$path not valid (received: $line)");
                   49993:                 }
                   49994:             }
                   49995:         }
                   49996: 
                   49997:         if ($reply != 200) {
                   49998:             if (!isset($headers['location'])) {
                   49999:                 return PEAR::raiseError("File $schema://$host:$port$path not valid (redirected but no location)");
                   50000:             }
                   50001: 
                   50002:             if ($wasredirect > 4) {
                   50003:                 return PEAR::raiseError("File $schema://$host:$port$path not valid (redirection looped more than 5 times)");
                   50004:             }
                   50005: 
                   50006:             $redirect = $wasredirect + 1;
                   50007:             return $this->downloadHttp($headers['location'], $lastmodified, $accept, $channel);
                   50008:         }
                   50009: 
                   50010:         $length = isset($headers['content-length']) ? $headers['content-length'] : -1;
                   50011: 
                   50012:         $data = '';
                   50013:         while ($chunk = @fread($fp, 8192)) {
                   50014:             $data .= $chunk;
                   50015:         }
                   50016:         fclose($fp);
                   50017: 
                   50018:         if ($lastmodified === false || $lastmodified) {
                   50019:             if (isset($headers['etag'])) {
                   50020:                 $lastmodified = array('ETag' => $headers['etag']);
                   50021:             }
                   50022: 
                   50023:             if (isset($headers['last-modified'])) {
                   50024:                 if (is_array($lastmodified)) {
                   50025:                     $lastmodified['Last-Modified'] = $headers['last-modified'];
                   50026:                 } else {
                   50027:                     $lastmodified = $headers['last-modified'];
                   50028:                 }
                   50029:             }
                   50030: 
                   50031:             return array($data, $lastmodified, $headers);
                   50032:         }
                   50033: 
                   50034:         return $data;
                   50035:     }
1.1.1.2 ! misho    50036: }PEAR-1.9.4/PEAR/RunTest.php0000644000076500000240000010660211605156614014105 0ustar  helgistaff<?php
1.1       misho    50037: /**
                   50038:  * PEAR_RunTest
                   50039:  *
                   50040:  * PHP versions 4 and 5
                   50041:  *
                   50042:  * @category   pear
                   50043:  * @package    PEAR
                   50044:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   50045:  * @author     Greg Beaver <cellog@php.net>
                   50046:  * @copyright  1997-2009 The Authors
                   50047:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   50048:  * @version    CVS: $Id: RunTest.php 313024 2011-07-06 19:51:24Z dufuz $
                   50049:  * @link       http://pear.php.net/package/PEAR
                   50050:  * @since      File available since Release 1.3.3
                   50051:  */
                   50052: 
                   50053: /**
                   50054:  * for error handling
                   50055:  */
                   50056: require_once 'PEAR.php';
                   50057: require_once 'PEAR/Config.php';
                   50058: 
                   50059: define('DETAILED', 1);
                   50060: putenv("PHP_PEAR_RUNTESTS=1");
                   50061: 
                   50062: /**
                   50063:  * Simplified version of PHP's test suite
                   50064:  *
                   50065:  * Try it with:
                   50066:  *
                   50067:  * $ php -r 'include "../PEAR/RunTest.php"; $t=new PEAR_RunTest; $o=$t->run("./pear_system.phpt");print_r($o);'
                   50068:  *
                   50069:  *
                   50070:  * @category   pear
                   50071:  * @package    PEAR
                   50072:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   50073:  * @author     Greg Beaver <cellog@php.net>
                   50074:  * @copyright  1997-2009 The Authors
                   50075:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   50076:  * @version    Release: 1.9.4
                   50077:  * @link       http://pear.php.net/package/PEAR
                   50078:  * @since      Class available since Release 1.3.3
                   50079:  */
                   50080: class PEAR_RunTest
                   50081: {
                   50082:     var $_headers = array();
                   50083:     var $_logger;
                   50084:     var $_options;
                   50085:     var $_php;
                   50086:     var $tests_count;
                   50087:     var $xdebug_loaded;
                   50088:     /**
                   50089:      * Saved value of php executable, used to reset $_php when we
                   50090:      * have a test that uses cgi
                   50091:      *
                   50092:      * @var unknown_type
                   50093:      */
                   50094:     var $_savephp;
                   50095:     var $ini_overwrites = array(
                   50096:         'output_handler=',
                   50097:         'open_basedir=',
                   50098:         'safe_mode=0',
                   50099:         'disable_functions=',
                   50100:         'output_buffering=Off',
                   50101:         'display_errors=1',
                   50102:         'log_errors=0',
                   50103:         'html_errors=0',
                   50104:         'track_errors=1',
                   50105:         'report_memleaks=0',
                   50106:         'report_zend_debug=0',
                   50107:         'docref_root=',
                   50108:         'docref_ext=.html',
                   50109:         'error_prepend_string=',
                   50110:         'error_append_string=',
                   50111:         'auto_prepend_file=',
                   50112:         'auto_append_file=',
                   50113:         'magic_quotes_runtime=0',
                   50114:         'xdebug.default_enable=0',
                   50115:         'allow_url_fopen=1',
                   50116:     );
                   50117: 
                   50118:     /**
                   50119:      * An object that supports the PEAR_Common->log() signature, or null
                   50120:      * @param PEAR_Common|null
                   50121:      */
                   50122:     function PEAR_RunTest($logger = null, $options = array())
                   50123:     {
                   50124:         if (!defined('E_DEPRECATED')) {
                   50125:             define('E_DEPRECATED', 0);
                   50126:         }
                   50127:         if (!defined('E_STRICT')) {
                   50128:             define('E_STRICT', 0);
                   50129:         }
                   50130:         $this->ini_overwrites[] = 'error_reporting=' . (E_ALL & ~(E_DEPRECATED | E_STRICT));
                   50131:         if (is_null($logger)) {
                   50132:             require_once 'PEAR/Common.php';
                   50133:             $logger = new PEAR_Common;
                   50134:         }
                   50135:         $this->_logger  = $logger;
                   50136:         $this->_options = $options;
                   50137: 
                   50138:         $conf = &PEAR_Config::singleton();
                   50139:         $this->_php = $conf->get('php_bin');
                   50140:     }
                   50141: 
                   50142:     /**
                   50143:      * Taken from php-src/run-tests.php
                   50144:      *
                   50145:      * @param string $commandline command name
                   50146:      * @param array $env
                   50147:      * @param string $stdin standard input to pass to the command
                   50148:      * @return unknown
                   50149:      */
                   50150:     function system_with_timeout($commandline, $env = null, $stdin = null)
                   50151:     {
                   50152:         $data = '';
                   50153:         if (version_compare(phpversion(), '5.0.0', '<')) {
                   50154:             $proc = proc_open($commandline, array(
                   50155:                 0 => array('pipe', 'r'),
                   50156:                 1 => array('pipe', 'w'),
                   50157:                 2 => array('pipe', 'w')
                   50158:                 ), $pipes);
                   50159:         } else {
                   50160:             $proc = proc_open($commandline, array(
                   50161:                 0 => array('pipe', 'r'),
                   50162:                 1 => array('pipe', 'w'),
                   50163:                 2 => array('pipe', 'w')
                   50164:                 ), $pipes, null, $env, array('suppress_errors' => true));
                   50165:         }
                   50166: 
                   50167:         if (!$proc) {
                   50168:             return false;
                   50169:         }
                   50170: 
                   50171:         if (is_string($stdin)) {
                   50172:             fwrite($pipes[0], $stdin);
                   50173:         }
                   50174:         fclose($pipes[0]);
                   50175: 
                   50176:         while (true) {
                   50177:             /* hide errors from interrupted syscalls */
                   50178:             $r = $pipes;
                   50179:             $e = $w = null;
                   50180:             $n = @stream_select($r, $w, $e, 60);
                   50181: 
                   50182:             if ($n === 0) {
                   50183:                 /* timed out */
                   50184:                 $data .= "\n ** ERROR: process timed out **\n";
                   50185:                 proc_terminate($proc);
                   50186:                 return array(1234567890, $data);
                   50187:             } else if ($n > 0) {
                   50188:                 $line = fread($pipes[1], 8192);
                   50189:                 if (strlen($line) == 0) {
                   50190:                     /* EOF */
                   50191:                     break;
                   50192:                 }
                   50193:                 $data .= $line;
                   50194:             }
                   50195:         }
                   50196:         if (function_exists('proc_get_status')) {
                   50197:             $stat = proc_get_status($proc);
                   50198:             if ($stat['signaled']) {
                   50199:                 $data .= "\nTermsig=".$stat['stopsig'];
                   50200:             }
                   50201:         }
                   50202:         $code = proc_close($proc);
                   50203:         if (function_exists('proc_get_status')) {
                   50204:             $code = $stat['exitcode'];
                   50205:         }
                   50206:         return array($code, $data);
                   50207:     }
                   50208: 
                   50209:     /**
                   50210:      * Turns a PHP INI string into an array
                   50211:      *
                   50212:      * Turns -d "include_path=/foo/bar" into this:
                   50213:      * array(
                   50214:      *   'include_path' => array(
                   50215:      *          'operator' => '-d',
                   50216:      *          'value'    => '/foo/bar',
                   50217:      *   )
                   50218:      * )
                   50219:      * Works both with quotes and without
                   50220:      *
                   50221:      * @param string an PHP INI string, -d "include_path=/foo/bar"
                   50222:      * @return array
                   50223:      */
                   50224:     function iniString2array($ini_string)
                   50225:     {
                   50226:         if (!$ini_string) {
                   50227:             return array();
                   50228:         }
                   50229:         $split = preg_split('/[\s]|=/', $ini_string, -1, PREG_SPLIT_NO_EMPTY);
                   50230:         $key   = $split[1][0] == '"'                     ? substr($split[1], 1)     : $split[1];
                   50231:         $value = $split[2][strlen($split[2]) - 1] == '"' ? substr($split[2], 0, -1) : $split[2];
                   50232:         // FIXME review if this is really the struct to go with
                   50233:         $array = array($key => array('operator' => $split[0], 'value' => $value));
                   50234:         return $array;
                   50235:     }
                   50236: 
                   50237:     function settings2array($settings, $ini_settings)
                   50238:     {
                   50239:         foreach ($settings as $setting) {
                   50240:             if (strpos($setting, '=') !== false) {
                   50241:                 $setting = explode('=', $setting, 2);
                   50242:                 $name  = trim(strtolower($setting[0]));
                   50243:                 $value = trim($setting[1]);
                   50244:                 $ini_settings[$name] = $value;
                   50245:             }
                   50246:         }
                   50247:         return $ini_settings;
                   50248:     }
                   50249: 
                   50250:     function settings2params($ini_settings)
                   50251:     {
                   50252:         $settings = '';
                   50253:         foreach ($ini_settings as $name => $value) {
                   50254:             if (is_array($value)) {
                   50255:                 $operator = $value['operator'];
                   50256:                 $value    = $value['value'];
                   50257:             } else {
                   50258:                 $operator = '-d';
                   50259:             }
                   50260:             $value = addslashes($value);
                   50261:             $settings .= " $operator \"$name=$value\"";
                   50262:         }
                   50263:         return $settings;
                   50264:     }
                   50265: 
                   50266:     function _preparePhpBin($php, $file, $ini_settings)
                   50267:     {
                   50268:         $file = escapeshellarg($file);
                   50269:         // This was fixed in php 5.3 and is not needed after that
                   50270:         if (OS_WINDOWS && version_compare(PHP_VERSION, '5.3', '<')) {
                   50271:             $cmd = '"'.escapeshellarg($php).' '.$ini_settings.' -f ' . $file .'"';
                   50272:         } else {
                   50273:             $cmd = $php . $ini_settings . ' -f ' . $file;
                   50274:         }
                   50275: 
                   50276:         return $cmd;
                   50277:     }
                   50278: 
                   50279:     function runPHPUnit($file, $ini_settings = '')
                   50280:     {
                   50281:         if (!file_exists($file) && file_exists(getcwd() . DIRECTORY_SEPARATOR . $file)) {
                   50282:             $file = realpath(getcwd() . DIRECTORY_SEPARATOR . $file);
                   50283:         } elseif (file_exists($file)) {
                   50284:             $file = realpath($file);
                   50285:         }
                   50286: 
                   50287:         $cmd = $this->_preparePhpBin($this->_php, $file, $ini_settings);
                   50288:         if (isset($this->_logger)) {
                   50289:             $this->_logger->log(2, 'Running command "' . $cmd . '"');
                   50290:         }
                   50291: 
                   50292:         $savedir = getcwd(); // in case the test moves us around
                   50293:         chdir(dirname($file));
                   50294:         echo `$cmd`;
                   50295:         chdir($savedir);
                   50296:         return 'PASSED'; // we have no way of knowing this information so assume passing
                   50297:     }
                   50298: 
                   50299:     /**
                   50300:      * Runs an individual test case.
                   50301:      *
                   50302:      * @param string       The filename of the test
                   50303:      * @param array|string INI settings to be applied to the test run
                   50304:      * @param integer      Number what the current running test is of the
                   50305:      *                     whole test suite being runned.
                   50306:      *
                   50307:      * @return string|object Returns PASSED, WARNED, FAILED depending on how the
                   50308:      *                       test came out.
                   50309:      *                       PEAR Error when the tester it self fails
                   50310:      */
                   50311:     function run($file, $ini_settings = array(), $test_number = 1)
                   50312:     {
                   50313:         if (isset($this->_savephp)) {
                   50314:             $this->_php = $this->_savephp;
                   50315:             unset($this->_savephp);
                   50316:         }
                   50317:         if (empty($this->_options['cgi'])) {
                   50318:             // try to see if php-cgi is in the path
                   50319:             $res = $this->system_with_timeout('php-cgi -v');
                   50320:             if (false !== $res && !(is_array($res) && in_array($res[0], array(-1, 127)))) {
                   50321:                 $this->_options['cgi'] = 'php-cgi';
                   50322:             }
                   50323:         }
                   50324:         if (1 < $len = strlen($this->tests_count)) {
                   50325:             $test_number = str_pad($test_number, $len, ' ', STR_PAD_LEFT);
                   50326:             $test_nr = "[$test_number/$this->tests_count] ";
                   50327:         } else {
                   50328:             $test_nr = '';
                   50329:         }
                   50330: 
                   50331:         $file = realpath($file);
                   50332:         $section_text = $this->_readFile($file);
                   50333:         if (PEAR::isError($section_text)) {
                   50334:             return $section_text;
                   50335:         }
                   50336: 
                   50337:         if (isset($section_text['POST_RAW']) && isset($section_text['UPLOAD'])) {
                   50338:             return PEAR::raiseError("Cannot contain both POST_RAW and UPLOAD in test file: $file");
                   50339:         }
                   50340: 
                   50341:         $cwd = getcwd();
                   50342: 
                   50343:         $pass_options = '';
                   50344:         if (!empty($this->_options['ini'])) {
                   50345:             $pass_options = $this->_options['ini'];
                   50346:         }
                   50347: 
                   50348:         if (is_string($ini_settings)) {
                   50349:             $ini_settings = $this->iniString2array($ini_settings);
                   50350:         }
                   50351: 
                   50352:         $ini_settings = $this->settings2array($this->ini_overwrites, $ini_settings);
                   50353:         if ($section_text['INI']) {
                   50354:             if (strpos($section_text['INI'], '{PWD}') !== false) {
                   50355:                 $section_text['INI'] = str_replace('{PWD}', dirname($file), $section_text['INI']);
                   50356:             }
                   50357:             $ini = preg_split( "/[\n\r]+/", $section_text['INI']);
                   50358:             $ini_settings = $this->settings2array($ini, $ini_settings);
                   50359:         }
                   50360:         $ini_settings = $this->settings2params($ini_settings);
                   50361:         $shortname = str_replace($cwd . DIRECTORY_SEPARATOR, '', $file);
                   50362: 
                   50363:         $tested = trim($section_text['TEST']);
                   50364:         $tested.= !isset($this->_options['simple']) ? "[$shortname]" : ' ';
                   50365: 
                   50366:         if (!empty($section_text['POST']) || !empty($section_text['POST_RAW']) ||
                   50367:               !empty($section_text['UPLOAD']) || !empty($section_text['GET']) ||
                   50368:               !empty($section_text['COOKIE']) || !empty($section_text['EXPECTHEADERS'])) {
                   50369:             if (empty($this->_options['cgi'])) {
                   50370:                 if (!isset($this->_options['quiet'])) {
                   50371:                     $this->_logger->log(0, "SKIP $test_nr$tested (reason: --cgi option needed for this test, type 'pear help run-tests')");
                   50372:                 }
                   50373:                 if (isset($this->_options['tapoutput'])) {
                   50374:                     return array('ok', ' # skip --cgi option needed for this test, "pear help run-tests" for info');
                   50375:                 }
                   50376:                 return 'SKIPPED';
                   50377:             }
                   50378:             $this->_savephp = $this->_php;
                   50379:             $this->_php = $this->_options['cgi'];
                   50380:         }
                   50381: 
                   50382:         $temp_dir = realpath(dirname($file));
                   50383:         $main_file_name = basename($file, 'phpt');
                   50384:         $diff_filename     = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'diff';
                   50385:         $log_filename      = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'log';
                   50386:         $exp_filename      = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'exp';
                   50387:         $output_filename   = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'out';
                   50388:         $memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'mem';
                   50389:         $temp_file         = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'php';
                   50390:         $temp_skipif       = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'skip.php';
                   50391:         $temp_clean        = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'clean.php';
                   50392:         $tmp_post          = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.');
                   50393: 
                   50394:         // unlink old test results
                   50395:         $this->_cleanupOldFiles($file);
                   50396: 
                   50397:         // Check if test should be skipped.
                   50398:         $res  = $this->_runSkipIf($section_text, $temp_skipif, $tested, $ini_settings);
                   50399:         if (count($res) != 2) {
                   50400:             return $res;
                   50401:         }
                   50402:         $info = $res['info'];
                   50403:         $warn = $res['warn'];
                   50404: 
                   50405:         // We've satisfied the preconditions - run the test!
                   50406:         if (isset($this->_options['coverage']) && $this->xdebug_loaded) {
                   50407:             $xdebug_file = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'xdebug';
                   50408:             $text = "\n" . 'function coverage_shutdown() {' .
                   50409:                     "\n" . '    $xdebug = var_export(xdebug_get_code_coverage(), true);';
                   50410:             if (!function_exists('file_put_contents')) {
                   50411:                 $text .= "\n" . '    $fh = fopen(\'' . $xdebug_file . '\', "wb");' .
                   50412:                         "\n" . '    if ($fh !== false) {' .
                   50413:                         "\n" . '        fwrite($fh, $xdebug);' .
                   50414:                         "\n" . '        fclose($fh);' .
                   50415:                         "\n" . '    }';
                   50416:             } else {
                   50417:                 $text .= "\n" . '    file_put_contents(\'' . $xdebug_file . '\', $xdebug);';
                   50418:             }
                   50419: 
                   50420:             // Workaround for http://pear.php.net/bugs/bug.php?id=17292
                   50421:             $lines             = explode("\n", $section_text['FILE']);
                   50422:             $numLines          = count($lines);
                   50423:             $namespace         = '';
                   50424:             $coverage_shutdown = 'coverage_shutdown';
                   50425: 
                   50426:             if (
                   50427:                 substr($lines[0], 0, 2) == '<?' ||
                   50428:                 substr($lines[0], 0, 5) == '<?php'
                   50429:             ) {
                   50430:                 unset($lines[0]);
                   50431:             }
                   50432: 
                   50433: 
                   50434:             for ($i = 0; $i < $numLines; $i++) {
                   50435:                 if (isset($lines[$i]) && substr($lines[$i], 0, 9) == 'namespace') {
                   50436:                     $namespace         = substr($lines[$i], 10, -1);
                   50437:                     $coverage_shutdown = $namespace . '\\coverage_shutdown';
                   50438:                     $namespace         = "namespace " . $namespace . ";\n";
                   50439: 
                   50440:                     unset($lines[$i]);
                   50441:                     break;
                   50442:                 }
                   50443:             }
                   50444: 
                   50445:             $text .= "\n    xdebug_stop_code_coverage();" .
                   50446:                 "\n" . '} // end coverage_shutdown()' .
                   50447:                 "\n\n" . 'register_shutdown_function("' . $coverage_shutdown . '");';
                   50448:             $text .= "\n" . 'xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);' . "\n";
                   50449: 
                   50450:             $this->save_text($temp_file, "<?php\n" . $namespace . $text  . "\n" . implode("\n", $lines));
                   50451:         } else {
                   50452:             $this->save_text($temp_file, $section_text['FILE']);
                   50453:         }
                   50454: 
                   50455:         $args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : '';
                   50456:         $cmd = $this->_preparePhpBin($this->_php, $temp_file, $ini_settings);
                   50457:         $cmd.= "$args 2>&1";
                   50458:         if (isset($this->_logger)) {
                   50459:             $this->_logger->log(2, 'Running command "' . $cmd . '"');
                   50460:         }
                   50461: 
                   50462:         // Reset environment from any previous test.
                   50463:         $env = $this->_resetEnv($section_text, $temp_file);
                   50464: 
                   50465:         $section_text = $this->_processUpload($section_text, $file);
                   50466:         if (PEAR::isError($section_text)) {
                   50467:             return $section_text;
                   50468:         }
                   50469: 
                   50470:         if (array_key_exists('POST_RAW', $section_text) && !empty($section_text['POST_RAW'])) {
                   50471:             $post = trim($section_text['POST_RAW']);
                   50472:             $raw_lines = explode("\n", $post);
                   50473: 
                   50474:             $request = '';
                   50475:             $started = false;
                   50476:             foreach ($raw_lines as $i => $line) {
                   50477:                 if (empty($env['CONTENT_TYPE']) &&
                   50478:                     preg_match('/^Content-Type:(.*)/i', $line, $res)) {
                   50479:                     $env['CONTENT_TYPE'] = trim(str_replace("\r", '', $res[1]));
                   50480:                     continue;
                   50481:                 }
                   50482:                 if ($started) {
                   50483:                     $request .= "\n";
                   50484:                 }
                   50485:                 $started = true;
                   50486:                 $request .= $line;
                   50487:             }
                   50488: 
                   50489:             $env['CONTENT_LENGTH'] = strlen($request);
                   50490:             $env['REQUEST_METHOD'] = 'POST';
                   50491: 
                   50492:             $this->save_text($tmp_post, $request);
                   50493:             $cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post";
                   50494:         } elseif (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
                   50495:             $post = trim($section_text['POST']);
                   50496:             $this->save_text($tmp_post, $post);
                   50497:             $content_length = strlen($post);
                   50498: 
                   50499:             $env['REQUEST_METHOD'] = 'POST';
                   50500:             $env['CONTENT_TYPE']   = 'application/x-www-form-urlencoded';
                   50501:             $env['CONTENT_LENGTH'] = $content_length;
                   50502: 
                   50503:             $cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post";
                   50504:         } else {
                   50505:             $env['REQUEST_METHOD'] = 'GET';
                   50506:             $env['CONTENT_TYPE']   = '';
                   50507:             $env['CONTENT_LENGTH'] = '';
                   50508:         }
                   50509: 
                   50510:         if (OS_WINDOWS && isset($section_text['RETURNS'])) {
                   50511:             ob_start();
                   50512:             system($cmd, $return_value);
                   50513:             $out = ob_get_contents();
                   50514:             ob_end_clean();
                   50515:             $section_text['RETURNS'] = (int) trim($section_text['RETURNS']);
                   50516:             $returnfail = ($return_value != $section_text['RETURNS']);
                   50517:         } else {
                   50518:             $returnfail = false;
                   50519:             $stdin = isset($section_text['STDIN']) ? $section_text['STDIN'] : null;
                   50520:             $out = $this->system_with_timeout($cmd, $env, $stdin);
                   50521:             $return_value = $out[0];
                   50522:             $out = $out[1];
                   50523:         }
                   50524: 
                   50525:         $output = preg_replace('/\r\n/', "\n", trim($out));
                   50526: 
                   50527:         if (isset($tmp_post) && realpath($tmp_post) && file_exists($tmp_post)) {
                   50528:             @unlink(realpath($tmp_post));
                   50529:         }
                   50530:         chdir($cwd); // in case the test moves us around
                   50531: 
                   50532:         $this->_testCleanup($section_text, $temp_clean);
                   50533: 
                   50534:         /* when using CGI, strip the headers from the output */
                   50535:         $output = $this->_stripHeadersCGI($output);
                   50536: 
                   50537:         if (isset($section_text['EXPECTHEADERS'])) {
                   50538:             $testheaders = $this->_processHeaders($section_text['EXPECTHEADERS']);
                   50539:             $missing = array_diff_assoc($testheaders, $this->_headers);
                   50540:             $changed = '';
                   50541:             foreach ($missing as $header => $value) {
                   50542:                 if (isset($this->_headers[$header])) {
                   50543:                     $changed .= "-$header: $value\n+$header: ";
                   50544:                     $changed .= $this->_headers[$header];
                   50545:                 } else {
                   50546:                     $changed .= "-$header: $value\n";
                   50547:                 }
                   50548:             }
                   50549:             if ($missing) {
                   50550:                 // tack on failed headers to output:
                   50551:                 $output .= "\n====EXPECTHEADERS FAILURE====:\n$changed";
                   50552:             }
                   50553:         }
                   50554:         // Does the output match what is expected?
                   50555:         do {
                   50556:             if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) {
                   50557:                 if (isset($section_text['EXPECTF'])) {
                   50558:                     $wanted = trim($section_text['EXPECTF']);
                   50559:                 } else {
                   50560:                     $wanted = trim($section_text['EXPECTREGEX']);
                   50561:                 }
                   50562:                 $wanted_re = preg_replace('/\r\n/', "\n", $wanted);
                   50563:                 if (isset($section_text['EXPECTF'])) {
                   50564:                     $wanted_re = preg_quote($wanted_re, '/');
                   50565:                     // Stick to basics
                   50566:                     $wanted_re = str_replace("%s", ".+?", $wanted_re); //not greedy
                   50567:                     $wanted_re = str_replace("%i", "[+\-]?[0-9]+", $wanted_re);
                   50568:                     $wanted_re = str_replace("%d", "[0-9]+", $wanted_re);
                   50569:                     $wanted_re = str_replace("%x", "[0-9a-fA-F]+", $wanted_re);
                   50570:                     $wanted_re = str_replace("%f", "[+\-]?\.?[0-9]+\.?[0-9]*(E-?[0-9]+)?", $wanted_re);
                   50571:                     $wanted_re = str_replace("%c", ".", $wanted_re);
                   50572:                     // %f allows two points "-.0.0" but that is the best *simple* expression
                   50573:                 }
                   50574: 
                   50575:     /* DEBUG YOUR REGEX HERE
                   50576:             var_dump($wanted_re);
                   50577:             print(str_repeat('=', 80) . "\n");
                   50578:             var_dump($output);
                   50579:     */
                   50580:                 if (!$returnfail && preg_match("/^$wanted_re\$/s", $output)) {
                   50581:                     if (file_exists($temp_file)) {
                   50582:                         unlink($temp_file);
                   50583:                     }
                   50584:                     if (array_key_exists('FAIL', $section_text)) {
                   50585:                         break;
                   50586:                     }
                   50587:                     if (!isset($this->_options['quiet'])) {
                   50588:                         $this->_logger->log(0, "PASS $test_nr$tested$info");
                   50589:                     }
                   50590:                     if (isset($this->_options['tapoutput'])) {
                   50591:                         return array('ok', ' - ' . $tested);
                   50592:                     }
                   50593:                     return 'PASSED';
                   50594:                 }
                   50595:             } else {
                   50596:                 if (isset($section_text['EXPECTFILE'])) {
                   50597:                     $f = $temp_dir . '/' . trim($section_text['EXPECTFILE']);
                   50598:                     if (!($fp = @fopen($f, 'rb'))) {
                   50599:                         return PEAR::raiseError('--EXPECTFILE-- section file ' .
                   50600:                             $f . ' not found');
                   50601:                     }
                   50602:                     fclose($fp);
                   50603:                     $section_text['EXPECT'] = file_get_contents($f);
                   50604:                 }
                   50605: 
                   50606:                 if (isset($section_text['EXPECT'])) {
                   50607:                     $wanted = preg_replace('/\r\n/', "\n", trim($section_text['EXPECT']));
                   50608:                 } else {
                   50609:                     $wanted = '';
                   50610:                 }
                   50611: 
                   50612:                 // compare and leave on success
                   50613:                 if (!$returnfail && 0 == strcmp($output, $wanted)) {
                   50614:                     if (file_exists($temp_file)) {
                   50615:                         unlink($temp_file);
                   50616:                     }
                   50617:                     if (array_key_exists('FAIL', $section_text)) {
                   50618:                         break;
                   50619:                     }
                   50620:                     if (!isset($this->_options['quiet'])) {
                   50621:                         $this->_logger->log(0, "PASS $test_nr$tested$info");
                   50622:                     }
                   50623:                     if (isset($this->_options['tapoutput'])) {
                   50624:                         return array('ok', ' - ' . $tested);
                   50625:                     }
                   50626:                     return 'PASSED';
                   50627:                 }
                   50628:             }
                   50629:         } while (false);
                   50630: 
                   50631:         if (array_key_exists('FAIL', $section_text)) {
                   50632:             // we expect a particular failure
                   50633:             // this is only used for testing PEAR_RunTest
                   50634:             $expectf  = isset($section_text['EXPECTF']) ? $wanted_re : null;
                   50635:             $faildiff = $this->generate_diff($wanted, $output, null, $expectf);
                   50636:             $faildiff = preg_replace('/\r/', '', $faildiff);
                   50637:             $wanted   = preg_replace('/\r/', '', trim($section_text['FAIL']));
                   50638:             if ($faildiff == $wanted) {
                   50639:                 if (!isset($this->_options['quiet'])) {
                   50640:                     $this->_logger->log(0, "PASS $test_nr$tested$info");
                   50641:                 }
                   50642:                 if (isset($this->_options['tapoutput'])) {
                   50643:                     return array('ok', ' - ' . $tested);
                   50644:                 }
                   50645:                 return 'PASSED';
                   50646:             }
                   50647:             unset($section_text['EXPECTF']);
                   50648:             $output = $faildiff;
                   50649:             if (isset($section_text['RETURNS'])) {
                   50650:                 return PEAR::raiseError('Cannot have both RETURNS and FAIL in the same test: ' .
                   50651:                     $file);
                   50652:             }
                   50653:         }
                   50654: 
                   50655:         // Test failed so we need to report details.
                   50656:         $txt = $warn ? 'WARN ' : 'FAIL ';
                   50657:         $this->_logger->log(0, $txt . $test_nr . $tested . $info);
                   50658: 
                   50659:         // write .exp
                   50660:         $res = $this->_writeLog($exp_filename, $wanted);
                   50661:         if (PEAR::isError($res)) {
                   50662:             return $res;
                   50663:         }
                   50664: 
                   50665:         // write .out
                   50666:         $res = $this->_writeLog($output_filename, $output);
                   50667:         if (PEAR::isError($res)) {
                   50668:             return $res;
                   50669:         }
                   50670: 
                   50671:         // write .diff
                   50672:         $returns = isset($section_text['RETURNS']) ?
                   50673:                         array(trim($section_text['RETURNS']), $return_value) : null;
                   50674:         $expectf = isset($section_text['EXPECTF']) ? $wanted_re : null;
                   50675:         $data = $this->generate_diff($wanted, $output, $returns, $expectf);
                   50676:         $res  = $this->_writeLog($diff_filename, $data);
                   50677:         if (PEAR::isError($res)) {
                   50678:             return $res;
                   50679:         }
                   50680: 
                   50681:         // write .log
                   50682:         $data = "
                   50683: ---- EXPECTED OUTPUT
                   50684: $wanted
                   50685: ---- ACTUAL OUTPUT
                   50686: $output
                   50687: ---- FAILED
                   50688: ";
                   50689: 
                   50690:         if ($returnfail) {
                   50691:             $data .= "
                   50692: ---- EXPECTED RETURN
                   50693: $section_text[RETURNS]
                   50694: ---- ACTUAL RETURN
                   50695: $return_value
                   50696: ";
                   50697:         }
                   50698: 
                   50699:         $res = $this->_writeLog($log_filename, $data);
                   50700:         if (PEAR::isError($res)) {
                   50701:             return $res;
                   50702:         }
                   50703: 
                   50704:         if (isset($this->_options['tapoutput'])) {
                   50705:             $wanted = explode("\n", $wanted);
                   50706:             $wanted = "# Expected output:\n#\n#" . implode("\n#", $wanted);
                   50707:             $output = explode("\n", $output);
                   50708:             $output = "#\n#\n# Actual output:\n#\n#" . implode("\n#", $output);
                   50709:             return array($wanted . $output . 'not ok', ' - ' . $tested);
                   50710:         }
                   50711:         return $warn ? 'WARNED' : 'FAILED';
                   50712:     }
                   50713: 
                   50714:     function generate_diff($wanted, $output, $rvalue, $wanted_re)
                   50715:     {
                   50716:         $w  = explode("\n", $wanted);
                   50717:         $o  = explode("\n", $output);
                   50718:         $wr = explode("\n", $wanted_re);
                   50719:         $w1 = array_diff_assoc($w, $o);
                   50720:         $o1 = array_diff_assoc($o, $w);
                   50721:         $o2 = $w2 = array();
                   50722:         foreach ($w1 as $idx => $val) {
                   50723:             if (!$wanted_re || !isset($wr[$idx]) || !isset($o1[$idx]) ||
                   50724:                   !preg_match('/^' . $wr[$idx] . '\\z/', $o1[$idx])) {
                   50725:                 $w2[sprintf("%03d<", $idx)] = sprintf("%03d- ", $idx + 1) . $val;
                   50726:             }
                   50727:         }
                   50728:         foreach ($o1 as $idx => $val) {
                   50729:             if (!$wanted_re || !isset($wr[$idx]) ||
                   50730:                   !preg_match('/^' . $wr[$idx] . '\\z/', $val)) {
                   50731:                 $o2[sprintf("%03d>", $idx)] = sprintf("%03d+ ", $idx + 1) . $val;
                   50732:             }
                   50733:         }
                   50734:         $diff = array_merge($w2, $o2);
                   50735:         ksort($diff);
                   50736:         $extra = $rvalue ? "##EXPECTED: $rvalue[0]\r\n##RETURNED: $rvalue[1]" : '';
                   50737:         return implode("\r\n", $diff) . $extra;
                   50738:     }
                   50739: 
                   50740:     //  Write the given text to a temporary file, and return the filename.
                   50741:     function save_text($filename, $text)
                   50742:     {
                   50743:         if (!$fp = fopen($filename, 'w')) {
                   50744:             return PEAR::raiseError("Cannot open file '" . $filename . "' (save_text)");
                   50745:         }
                   50746:         fwrite($fp, $text);
                   50747:         fclose($fp);
                   50748:     if (1 < DETAILED) echo "
                   50749: FILE $filename {{{
                   50750: $text
                   50751: }}}
                   50752: ";
                   50753:     }
                   50754: 
                   50755:     function _cleanupOldFiles($file)
                   50756:     {
                   50757:         $temp_dir = realpath(dirname($file));
                   50758:         $mainFileName = basename($file, 'phpt');
                   50759:         $diff_filename     = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'diff';
                   50760:         $log_filename      = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'log';
                   50761:         $exp_filename      = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'exp';
                   50762:         $output_filename   = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'out';
                   50763:         $memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'mem';
                   50764:         $temp_file         = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'php';
                   50765:         $temp_skipif       = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'skip.php';
                   50766:         $temp_clean        = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'clean.php';
                   50767:         $tmp_post          = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.');
                   50768: 
                   50769:         // unlink old test results
                   50770:         @unlink($diff_filename);
                   50771:         @unlink($log_filename);
                   50772:         @unlink($exp_filename);
                   50773:         @unlink($output_filename);
                   50774:         @unlink($memcheck_filename);
                   50775:         @unlink($temp_file);
                   50776:         @unlink($temp_skipif);
                   50777:         @unlink($tmp_post);
                   50778:         @unlink($temp_clean);
                   50779:     }
                   50780: 
                   50781:     function _runSkipIf($section_text, $temp_skipif, $tested, $ini_settings)
                   50782:     {
                   50783:         $info = '';
                   50784:         $warn = false;
                   50785:         if (array_key_exists('SKIPIF', $section_text) && trim($section_text['SKIPIF'])) {
                   50786:             $this->save_text($temp_skipif, $section_text['SKIPIF']);
                   50787:             $output = $this->system_with_timeout("$this->_php$ini_settings -f \"$temp_skipif\"");
                   50788:             $output = $output[1];
                   50789:             $loutput = ltrim($output);
                   50790:             unlink($temp_skipif);
                   50791:             if (!strncasecmp('skip', $loutput, 4)) {
                   50792:                 $skipreason = "SKIP $tested";
                   50793:                 if (preg_match('/^\s*skip\s*(.+)\s*/i', $output, $m)) {
                   50794:                     $skipreason .= '(reason: ' . $m[1] . ')';
                   50795:                 }
                   50796:                 if (!isset($this->_options['quiet'])) {
                   50797:                     $this->_logger->log(0, $skipreason);
                   50798:                 }
                   50799:                 if (isset($this->_options['tapoutput'])) {
                   50800:                     return array('ok', ' # skip ' . $reason);
                   50801:                 }
                   50802:                 return 'SKIPPED';
                   50803:             }
                   50804: 
                   50805:             if (!strncasecmp('info', $loutput, 4)
                   50806:                 && preg_match('/^\s*info\s*(.+)\s*/i', $output, $m)) {
                   50807:                 $info = " (info: $m[1])";
                   50808:             }
                   50809: 
                   50810:             if (!strncasecmp('warn', $loutput, 4)
                   50811:                 && preg_match('/^\s*warn\s*(.+)\s*/i', $output, $m)) {
                   50812:                 $warn = true; /* only if there is a reason */
                   50813:                 $info = " (warn: $m[1])";
                   50814:             }
                   50815:         }
                   50816: 
                   50817:         return array('warn' => $warn, 'info' => $info);
                   50818:     }
                   50819: 
                   50820:     function _stripHeadersCGI($output)
                   50821:     {
                   50822:         $this->headers = array();
                   50823:         if (!empty($this->_options['cgi']) &&
                   50824:               $this->_php == $this->_options['cgi'] &&
                   50825:               preg_match("/^(.*?)(?:\n\n(.*)|\\z)/s", $output, $match)) {
                   50826:             $output = isset($match[2]) ? trim($match[2]) : '';
                   50827:             $this->_headers = $this->_processHeaders($match[1]);
                   50828:         }
                   50829: 
                   50830:         return $output;
                   50831:     }
                   50832: 
                   50833:     /**
                   50834:      * Return an array that can be used with array_diff() to compare headers
                   50835:      *
                   50836:      * @param string $text
                   50837:      */
                   50838:     function _processHeaders($text)
                   50839:     {
                   50840:         $headers = array();
                   50841:         $rh = preg_split("/[\n\r]+/", $text);
                   50842:         foreach ($rh as $line) {
                   50843:             if (strpos($line, ':')!== false) {
                   50844:                 $line = explode(':', $line, 2);
                   50845:                 $headers[trim($line[0])] = trim($line[1]);
                   50846:             }
                   50847:         }
                   50848:         return $headers;
                   50849:     }
                   50850: 
                   50851:     function _readFile($file)
                   50852:     {
                   50853:         // Load the sections of the test file.
                   50854:         $section_text = array(
                   50855:             'TEST'   => '(unnamed test)',
                   50856:             'SKIPIF' => '',
                   50857:             'GET'    => '',
                   50858:             'COOKIE' => '',
                   50859:             'POST'   => '',
                   50860:             'ARGS'   => '',
                   50861:             'INI'    => '',
                   50862:             'CLEAN'  => '',
                   50863:         );
                   50864: 
                   50865:         if (!is_file($file) || !$fp = fopen($file, "r")) {
                   50866:             return PEAR::raiseError("Cannot open test file: $file");
                   50867:         }
                   50868: 
                   50869:         $section = '';
                   50870:         while (!feof($fp)) {
                   50871:             $line = fgets($fp);
                   50872: 
                   50873:             // Match the beginning of a section.
                   50874:             if (preg_match('/^--([_A-Z]+)--/', $line, $r)) {
                   50875:                 $section = $r[1];
                   50876:                 $section_text[$section] = '';
                   50877:                 continue;
                   50878:             } elseif (empty($section)) {
                   50879:                 fclose($fp);
                   50880:                 return PEAR::raiseError("Invalid sections formats in test file: $file");
                   50881:             }
                   50882: 
                   50883:             // Add to the section text.
                   50884:             $section_text[$section] .= $line;
                   50885:         }
                   50886:         fclose($fp);
                   50887: 
                   50888:         return $section_text;
                   50889:     }
                   50890: 
                   50891:     function _writeLog($logname, $data)
                   50892:     {
                   50893:         if (!$log = fopen($logname, 'w')) {
                   50894:             return PEAR::raiseError("Cannot create test log - $logname");
                   50895:         }
                   50896:         fwrite($log, $data);
                   50897:         fclose($log);
                   50898:     }
                   50899: 
                   50900:     function _resetEnv($section_text, $temp_file)
                   50901:     {
                   50902:         $env = $_ENV;
                   50903:         $env['REDIRECT_STATUS'] = '';
                   50904:         $env['QUERY_STRING']    = '';
                   50905:         $env['PATH_TRANSLATED'] = '';
                   50906:         $env['SCRIPT_FILENAME'] = '';
                   50907:         $env['REQUEST_METHOD']  = '';
                   50908:         $env['CONTENT_TYPE']    = '';
                   50909:         $env['CONTENT_LENGTH']  = '';
                   50910:         if (!empty($section_text['ENV'])) {
                   50911:             if (strpos($section_text['ENV'], '{PWD}') !== false) {
                   50912:                 $section_text['ENV'] = str_replace('{PWD}', dirname($temp_file), $section_text['ENV']);
                   50913:             }
                   50914:             foreach (explode("\n", trim($section_text['ENV'])) as $e) {
                   50915:                 $e = explode('=', trim($e), 2);
                   50916:                 if (!empty($e[0]) && isset($e[1])) {
                   50917:                     $env[$e[0]] = $e[1];
                   50918:                 }
                   50919:             }
                   50920:         }
                   50921:         if (array_key_exists('GET', $section_text)) {
                   50922:             $env['QUERY_STRING'] = trim($section_text['GET']);
                   50923:         } else {
                   50924:             $env['QUERY_STRING'] = '';
                   50925:         }
                   50926:         if (array_key_exists('COOKIE', $section_text)) {
                   50927:             $env['HTTP_COOKIE'] = trim($section_text['COOKIE']);
                   50928:         } else {
                   50929:             $env['HTTP_COOKIE'] = '';
                   50930:         }
                   50931:         $env['REDIRECT_STATUS'] = '1';
                   50932:         $env['PATH_TRANSLATED'] = $temp_file;
                   50933:         $env['SCRIPT_FILENAME'] = $temp_file;
                   50934: 
                   50935:         return $env;
                   50936:     }
                   50937: 
                   50938:     function _processUpload($section_text, $file)
                   50939:     {
                   50940:         if (array_key_exists('UPLOAD', $section_text) && !empty($section_text['UPLOAD'])) {
                   50941:             $upload_files = trim($section_text['UPLOAD']);
                   50942:             $upload_files = explode("\n", $upload_files);
                   50943: 
                   50944:             $request = "Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737\n" .
                   50945:                        "-----------------------------20896060251896012921717172737\n";
                   50946:             foreach ($upload_files as $fileinfo) {
                   50947:                 $fileinfo = explode('=', $fileinfo);
                   50948:                 if (count($fileinfo) != 2) {
                   50949:                     return PEAR::raiseError("Invalid UPLOAD section in test file: $file");
                   50950:                 }
                   50951:                 if (!realpath(dirname($file) . '/' . $fileinfo[1])) {
                   50952:                     return PEAR::raiseError("File for upload does not exist: $fileinfo[1] " .
                   50953:                         "in test file: $file");
                   50954:                 }
                   50955:                 $file_contents = file_get_contents(dirname($file) . '/' . $fileinfo[1]);
                   50956:                 $fileinfo[1] = basename($fileinfo[1]);
                   50957:                 $request .= "Content-Disposition: form-data; name=\"$fileinfo[0]\"; filename=\"$fileinfo[1]\"\n";
                   50958:                 $request .= "Content-Type: text/plain\n\n";
                   50959:                 $request .= $file_contents . "\n" .
                   50960:                     "-----------------------------20896060251896012921717172737\n";
                   50961:             }
                   50962: 
                   50963:             if (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
                   50964:                 // encode POST raw
                   50965:                 $post = trim($section_text['POST']);
                   50966:                 $post = explode('&', $post);
                   50967:                 foreach ($post as $i => $post_info) {
                   50968:                     $post_info = explode('=', $post_info);
                   50969:                     if (count($post_info) != 2) {
                   50970:                         return PEAR::raiseError("Invalid POST data in test file: $file");
                   50971:                     }
                   50972:                     $post_info[0] = rawurldecode($post_info[0]);
                   50973:                     $post_info[1] = rawurldecode($post_info[1]);
                   50974:                     $post[$i] = $post_info;
                   50975:                 }
                   50976:                 foreach ($post as $post_info) {
                   50977:                     $request .= "Content-Disposition: form-data; name=\"$post_info[0]\"\n\n";
                   50978:                     $request .= $post_info[1] . "\n" .
                   50979:                         "-----------------------------20896060251896012921717172737\n";
                   50980:                 }
                   50981:                 unset($section_text['POST']);
                   50982:             }
                   50983:             $section_text['POST_RAW'] = $request;
                   50984:         }
                   50985: 
                   50986:         return $section_text;
                   50987:     }
                   50988: 
                   50989:     function _testCleanup($section_text, $temp_clean)
                   50990:     {
                   50991:         if ($section_text['CLEAN']) {
                   50992:             // perform test cleanup
                   50993:             $this->save_text($temp_clean, $section_text['CLEAN']);
                   50994:             $output = $this->system_with_timeout("$this->_php $temp_clean  2>&1");
                   50995:             if (strlen($output[1])) {
                   50996:                 echo "BORKED --CLEAN-- section! output:\n", $output[1];
                   50997:             }
                   50998:             if (file_exists($temp_clean)) {
                   50999:                 unlink($temp_clean);
                   51000:             }
                   51001:         }
                   51002:     }
                   51003: }
1.1.1.2 ! misho    51004: PEAR-1.9.4/PEAR/Validate.php0000644000076500000240000005305511605156614014235 0ustar  helgistaff<?php
1.1       misho    51005: /**
                   51006:  * PEAR_Validate
                   51007:  *
                   51008:  * PHP versions 4 and 5
                   51009:  *
                   51010:  * @category   pear
                   51011:  * @package    PEAR
                   51012:  * @author     Greg Beaver <cellog@php.net>
                   51013:  * @copyright  1997-2009 The Authors
                   51014:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   51015:  * @version    CVS: $Id: Validate.php 313023 2011-07-06 19:17:11Z dufuz $
                   51016:  * @link       http://pear.php.net/package/PEAR
                   51017:  * @since      File available since Release 1.4.0a1
                   51018:  */
                   51019: /**#@+
                   51020:  * Constants for install stage
                   51021:  */
                   51022: define('PEAR_VALIDATE_INSTALLING', 1);
                   51023: define('PEAR_VALIDATE_UNINSTALLING', 2); // this is not bit-mapped like the others
                   51024: define('PEAR_VALIDATE_NORMAL', 3);
                   51025: define('PEAR_VALIDATE_DOWNLOADING', 4); // this is not bit-mapped like the others
                   51026: define('PEAR_VALIDATE_PACKAGING', 7);
                   51027: /**#@-*/
                   51028: require_once 'PEAR/Common.php';
                   51029: require_once 'PEAR/Validator/PECL.php';
                   51030: 
                   51031: /**
                   51032:  * Validation class for package.xml - channel-level advanced validation
                   51033:  * @category   pear
                   51034:  * @package    PEAR
                   51035:  * @author     Greg Beaver <cellog@php.net>
                   51036:  * @copyright  1997-2009 The Authors
                   51037:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   51038:  * @version    Release: 1.9.4
                   51039:  * @link       http://pear.php.net/package/PEAR
                   51040:  * @since      Class available since Release 1.4.0a1
                   51041:  */
                   51042: class PEAR_Validate
                   51043: {
                   51044:     var $packageregex = _PEAR_COMMON_PACKAGE_NAME_PREG;
                   51045:     /**
                   51046:      * @var PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   51047:      */
                   51048:     var $_packagexml;
                   51049:     /**
                   51050:      * @var int one of the PEAR_VALIDATE_* constants
                   51051:      */
                   51052:     var $_state = PEAR_VALIDATE_NORMAL;
                   51053:     /**
                   51054:      * Format: ('error' => array('field' => name, 'reason' => reason), 'warning' => same)
                   51055:      * @var array
                   51056:      * @access private
                   51057:      */
                   51058:     var $_failures = array('error' => array(), 'warning' => array());
                   51059: 
                   51060:     /**
                   51061:      * Override this method to handle validation of normal package names
                   51062:      * @param string
                   51063:      * @return bool
                   51064:      * @access protected
                   51065:      */
                   51066:     function _validPackageName($name)
                   51067:     {
                   51068:         return (bool) preg_match('/^' . $this->packageregex . '\\z/', $name);
                   51069:     }
                   51070: 
                   51071:     /**
                   51072:      * @param string package name to validate
                   51073:      * @param string name of channel-specific validation package
                   51074:      * @final
                   51075:      */
                   51076:     function validPackageName($name, $validatepackagename = false)
                   51077:     {
                   51078:         if ($validatepackagename) {
                   51079:             if (strtolower($name) == strtolower($validatepackagename)) {
                   51080:                 return (bool) preg_match('/^[a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)*\\z/', $name);
                   51081:             }
                   51082:         }
                   51083:         return $this->_validPackageName($name);
                   51084:     }
                   51085: 
                   51086:     /**
                   51087:      * This validates a bundle name, and bundle names must conform
                   51088:      * to the PEAR naming convention, so the method is final and static.
                   51089:      * @param string
                   51090:      * @final
                   51091:      * @static
                   51092:      */
                   51093:     function validGroupName($name)
                   51094:     {
                   51095:         return (bool) preg_match('/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/', $name);
                   51096:     }
                   51097: 
                   51098:     /**
                   51099:      * Determine whether $state represents a valid stability level
                   51100:      * @param string
                   51101:      * @return bool
                   51102:      * @static
                   51103:      * @final
                   51104:      */
                   51105:     function validState($state)
                   51106:     {
                   51107:         return in_array($state, array('snapshot', 'devel', 'alpha', 'beta', 'stable'));
                   51108:     }
                   51109: 
                   51110:     /**
                   51111:      * Get a list of valid stability levels
                   51112:      * @return array
                   51113:      * @static
                   51114:      * @final
                   51115:      */
                   51116:     function getValidStates()
                   51117:     {
                   51118:         return array('snapshot', 'devel', 'alpha', 'beta', 'stable');
                   51119:     }
                   51120: 
                   51121:     /**
                   51122:      * Determine whether a version is a properly formatted version number that can be used
                   51123:      * by version_compare
                   51124:      * @param string
                   51125:      * @return bool
                   51126:      * @static
                   51127:      * @final
                   51128:      */
                   51129:     function validVersion($ver)
                   51130:     {
                   51131:         return (bool) preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver);
                   51132:     }
                   51133: 
                   51134:     /**
                   51135:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   51136:      */
                   51137:     function setPackageFile(&$pf)
                   51138:     {
                   51139:         $this->_packagexml = &$pf;
                   51140:     }
                   51141: 
                   51142:     /**
                   51143:      * @access private
                   51144:      */
                   51145:     function _addFailure($field, $reason)
                   51146:     {
                   51147:         $this->_failures['errors'][] = array('field' => $field, 'reason' => $reason);
                   51148:     }
                   51149: 
                   51150:     /**
                   51151:      * @access private
                   51152:      */
                   51153:     function _addWarning($field, $reason)
                   51154:     {
                   51155:         $this->_failures['warnings'][] = array('field' => $field, 'reason' => $reason);
                   51156:     }
                   51157: 
                   51158:     function getFailures()
                   51159:     {
                   51160:         $failures = $this->_failures;
                   51161:         $this->_failures = array('warnings' => array(), 'errors' => array());
                   51162:         return $failures;
                   51163:     }
                   51164: 
                   51165:     /**
                   51166:      * @param int one of the PEAR_VALIDATE_* constants
                   51167:      */
                   51168:     function validate($state = null)
                   51169:     {
                   51170:         if (!isset($this->_packagexml)) {
                   51171:             return false;
                   51172:         }
                   51173:         if ($state !== null) {
                   51174:             $this->_state = $state;
                   51175:         }
                   51176:         $this->_failures = array('warnings' => array(), 'errors' => array());
                   51177:         $this->validatePackageName();
                   51178:         $this->validateVersion();
                   51179:         $this->validateMaintainers();
                   51180:         $this->validateDate();
                   51181:         $this->validateSummary();
                   51182:         $this->validateDescription();
                   51183:         $this->validateLicense();
                   51184:         $this->validateNotes();
                   51185:         if ($this->_packagexml->getPackagexmlVersion() == '1.0') {
                   51186:             $this->validateState();
                   51187:             $this->validateFilelist();
                   51188:         } elseif ($this->_packagexml->getPackagexmlVersion() == '2.0' ||
                   51189:                   $this->_packagexml->getPackagexmlVersion() == '2.1') {
                   51190:             $this->validateTime();
                   51191:             $this->validateStability();
                   51192:             $this->validateDeps();
                   51193:             $this->validateMainFilelist();
                   51194:             $this->validateReleaseFilelist();
                   51195:             //$this->validateGlobalTasks();
                   51196:             $this->validateChangelog();
                   51197:         }
                   51198:         return !((bool) count($this->_failures['errors']));
                   51199:     }
                   51200: 
                   51201:     /**
                   51202:      * @access protected
                   51203:      */
                   51204:     function validatePackageName()
                   51205:     {
                   51206:         if ($this->_state == PEAR_VALIDATE_PACKAGING ||
                   51207:               $this->_state == PEAR_VALIDATE_NORMAL) {
                   51208:             if (($this->_packagexml->getPackagexmlVersion() == '2.0' ||
                   51209:                  $this->_packagexml->getPackagexmlVersion() == '2.1') &&
                   51210:                   $this->_packagexml->getExtends()) {
                   51211:                 $version = $this->_packagexml->getVersion() . '';
                   51212:                 $name = $this->_packagexml->getPackage();
                   51213:                 $test = array_shift($a = explode('.', $version));
                   51214:                 if ($test == '0') {
                   51215:                     return true;
                   51216:                 }
                   51217:                 $vlen = strlen($test);
                   51218:                 $majver = substr($name, strlen($name) - $vlen);
                   51219:                 while ($majver && !is_numeric($majver{0})) {
                   51220:                     $majver = substr($majver, 1);
                   51221:                 }
                   51222:                 if ($majver != $test) {
                   51223:                     $this->_addWarning('package', "package $name extends package " .
                   51224:                         $this->_packagexml->getExtends() . ' and so the name should ' .
                   51225:                         'have a postfix equal to the major version like "' .
                   51226:                         $this->_packagexml->getExtends() . $test . '"');
                   51227:                     return true;
                   51228:                 } elseif (substr($name, 0, strlen($name) - $vlen) !=
                   51229:                             $this->_packagexml->getExtends()) {
                   51230:                     $this->_addWarning('package', "package $name extends package " .
                   51231:                         $this->_packagexml->getExtends() . ' and so the name must ' .
                   51232:                         'be an extension like "' . $this->_packagexml->getExtends() .
                   51233:                         $test . '"');
                   51234:                     return true;
                   51235:                 }
                   51236:             }
                   51237:         }
                   51238:         if (!$this->validPackageName($this->_packagexml->getPackage())) {
                   51239:             $this->_addFailure('name', 'package name "' .
                   51240:                 $this->_packagexml->getPackage() . '" is invalid');
                   51241:             return false;
                   51242:         }
                   51243:     }
                   51244: 
                   51245:     /**
                   51246:      * @access protected
                   51247:      */
                   51248:     function validateVersion()
                   51249:     {
                   51250:         if ($this->_state != PEAR_VALIDATE_PACKAGING) {
                   51251:             if (!$this->validVersion($this->_packagexml->getVersion())) {
                   51252:                 $this->_addFailure('version',
                   51253:                     'Invalid version number "' . $this->_packagexml->getVersion() . '"');
                   51254:             }
                   51255:             return false;
                   51256:         }
                   51257:         $version = $this->_packagexml->getVersion();
                   51258:         $versioncomponents = explode('.', $version);
                   51259:         if (count($versioncomponents) != 3) {
                   51260:             $this->_addWarning('version',
                   51261:                 'A version number should have 3 decimals (x.y.z)');
                   51262:             return true;
                   51263:         }
                   51264:         $name = $this->_packagexml->getPackage();
                   51265:         // version must be based upon state
                   51266:         switch ($this->_packagexml->getState()) {
                   51267:             case 'snapshot' :
                   51268:                 return true;
                   51269:             case 'devel' :
                   51270:                 if ($versioncomponents[0] . 'a' == '0a') {
                   51271:                     return true;
                   51272:                 }
                   51273:                 if ($versioncomponents[0] == 0) {
                   51274:                     $versioncomponents[0] = '0';
                   51275:                     $this->_addWarning('version',
                   51276:                         'version "' . $version . '" should be "' .
                   51277:                         implode('.' ,$versioncomponents) . '"');
                   51278:                 } else {
                   51279:                     $this->_addWarning('version',
                   51280:                         'packages with devel stability must be < version 1.0.0');
                   51281:                 }
                   51282:                 return true;
                   51283:             break;
                   51284:             case 'alpha' :
                   51285:             case 'beta' :
                   51286:                 // check for a package that extends a package,
                   51287:                 // like Foo and Foo2
                   51288:                 if ($this->_state == PEAR_VALIDATE_PACKAGING) {
                   51289:                     if (substr($versioncomponents[2], 1, 2) == 'rc') {
                   51290:                         $this->_addFailure('version', 'Release Candidate versions ' .
                   51291:                             'must have capital RC, not lower-case rc');
                   51292:                         return false;
                   51293:                     }
                   51294:                 }
                   51295:                 if (!$this->_packagexml->getExtends()) {
                   51296:                     if ($versioncomponents[0] == '1') {
                   51297:                         if ($versioncomponents[2]{0} == '0') {
                   51298:                             if ($versioncomponents[2] == '0') {
                   51299:                                 // version 1.*.0000
                   51300:                                 $this->_addWarning('version',
                   51301:                                     'version 1.' . $versioncomponents[1] .
                   51302:                                         '.0 probably should not be alpha or beta');
                   51303:                                 return true;
                   51304:                             } elseif (strlen($versioncomponents[2]) > 1) {
                   51305:                                 // version 1.*.0RC1 or 1.*.0beta24 etc.
                   51306:                                 return true;
                   51307:                             } else {
                   51308:                                 // version 1.*.0
                   51309:                                 $this->_addWarning('version',
                   51310:                                     'version 1.' . $versioncomponents[1] .
                   51311:                                         '.0 probably should not be alpha or beta');
                   51312:                                 return true;
                   51313:                             }
                   51314:                         } else {
                   51315:                             $this->_addWarning('version',
                   51316:                                 'bugfix versions (1.3.x where x > 0) probably should ' .
                   51317:                                 'not be alpha or beta');
                   51318:                             return true;
                   51319:                         }
                   51320:                     } elseif ($versioncomponents[0] != '0') {
                   51321:                         $this->_addWarning('version',
                   51322:                             'major versions greater than 1 are not allowed for packages ' .
                   51323:                             'without an <extends> tag or an identical postfix (foo2 v2.0.0)');
                   51324:                         return true;
                   51325:                     }
                   51326:                     if ($versioncomponents[0] . 'a' == '0a') {
                   51327:                         return true;
                   51328:                     }
                   51329:                     if ($versioncomponents[0] == 0) {
                   51330:                         $versioncomponents[0] = '0';
                   51331:                         $this->_addWarning('version',
                   51332:                             'version "' . $version . '" should be "' .
                   51333:                             implode('.' ,$versioncomponents) . '"');
                   51334:                     }
                   51335:                 } else {
                   51336:                     $vlen = strlen($versioncomponents[0] . '');
                   51337:                     $majver = substr($name, strlen($name) - $vlen);
                   51338:                     while ($majver && !is_numeric($majver{0})) {
                   51339:                         $majver = substr($majver, 1);
                   51340:                     }
                   51341:                     if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) {
                   51342:                         $this->_addWarning('version', 'first version number "' .
                   51343:                             $versioncomponents[0] . '" must match the postfix of ' .
                   51344:                             'package name "' . $name . '" (' .
                   51345:                             $majver . ')');
                   51346:                         return true;
                   51347:                     }
                   51348:                     if ($versioncomponents[0] == $majver) {
                   51349:                         if ($versioncomponents[2]{0} == '0') {
                   51350:                             if ($versioncomponents[2] == '0') {
                   51351:                                 // version 2.*.0000
                   51352:                                 $this->_addWarning('version',
                   51353:                                     "version $majver." . $versioncomponents[1] .
                   51354:                                         '.0 probably should not be alpha or beta');
                   51355:                                 return false;
                   51356:                             } elseif (strlen($versioncomponents[2]) > 1) {
                   51357:                                 // version 2.*.0RC1 or 2.*.0beta24 etc.
                   51358:                                 return true;
                   51359:                             } else {
                   51360:                                 // version 2.*.0
                   51361:                                 $this->_addWarning('version',
                   51362:                                     "version $majver." . $versioncomponents[1] .
                   51363:                                         '.0 cannot be alpha or beta');
                   51364:                                 return true;
                   51365:                             }
                   51366:                         } else {
                   51367:                             $this->_addWarning('version',
                   51368:                                 "bugfix versions ($majver.x.y where y > 0) should " .
                   51369:                                 'not be alpha or beta');
                   51370:                             return true;
                   51371:                         }
                   51372:                     } elseif ($versioncomponents[0] != '0') {
                   51373:                         $this->_addWarning('version',
                   51374:                             "only versions 0.x.y and $majver.x.y are allowed for alpha/beta releases");
                   51375:                         return true;
                   51376:                     }
                   51377:                     if ($versioncomponents[0] . 'a' == '0a') {
                   51378:                         return true;
                   51379:                     }
                   51380:                     if ($versioncomponents[0] == 0) {
                   51381:                         $versioncomponents[0] = '0';
                   51382:                         $this->_addWarning('version',
                   51383:                             'version "' . $version . '" should be "' .
                   51384:                             implode('.' ,$versioncomponents) . '"');
                   51385:                     }
                   51386:                 }
                   51387:                 return true;
                   51388:             break;
                   51389:             case 'stable' :
                   51390:                 if ($versioncomponents[0] == '0') {
                   51391:                     $this->_addWarning('version', 'versions less than 1.0.0 cannot ' .
                   51392:                     'be stable');
                   51393:                     return true;
                   51394:                 }
                   51395:                 if (!is_numeric($versioncomponents[2])) {
                   51396:                     if (preg_match('/\d+(rc|a|alpha|b|beta)\d*/i',
                   51397:                           $versioncomponents[2])) {
                   51398:                         $this->_addWarning('version', 'version "' . $version . '" or any ' .
                   51399:                             'RC/beta/alpha version cannot be stable');
                   51400:                         return true;
                   51401:                     }
                   51402:                 }
                   51403:                 // check for a package that extends a package,
                   51404:                 // like Foo and Foo2
                   51405:                 if ($this->_packagexml->getExtends()) {
                   51406:                     $vlen = strlen($versioncomponents[0] . '');
                   51407:                     $majver = substr($name, strlen($name) - $vlen);
                   51408:                     while ($majver && !is_numeric($majver{0})) {
                   51409:                         $majver = substr($majver, 1);
                   51410:                     }
                   51411:                     if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) {
                   51412:                         $this->_addWarning('version', 'first version number "' .
                   51413:                             $versioncomponents[0] . '" must match the postfix of ' .
                   51414:                             'package name "' . $name . '" (' .
                   51415:                             $majver . ')');
                   51416:                         return true;
                   51417:                     }
                   51418:                 } elseif ($versioncomponents[0] > 1) {
                   51419:                     $this->_addWarning('version', 'major version x in x.y.z may not be greater than ' .
                   51420:                         '1 for any package that does not have an <extends> tag');
                   51421:                 }
                   51422:                 return true;
                   51423:             break;
                   51424:             default :
                   51425:                 return false;
                   51426:             break;
                   51427:         }
                   51428:     }
                   51429: 
                   51430:     /**
                   51431:      * @access protected
                   51432:      */
                   51433:     function validateMaintainers()
                   51434:     {
                   51435:         // maintainers can only be truly validated server-side for most channels
                   51436:         // but allow this customization for those who wish it
                   51437:         return true;
                   51438:     }
                   51439: 
                   51440:     /**
                   51441:      * @access protected
                   51442:      */
                   51443:     function validateDate()
                   51444:     {
                   51445:         if ($this->_state == PEAR_VALIDATE_NORMAL ||
                   51446:               $this->_state == PEAR_VALIDATE_PACKAGING) {
                   51447: 
                   51448:             if (!preg_match('/(\d\d\d\d)\-(\d\d)\-(\d\d)/',
                   51449:                   $this->_packagexml->getDate(), $res) ||
                   51450:                   count($res) < 4
                   51451:                   || !checkdate($res[2], $res[3], $res[1])
                   51452:                 ) {
                   51453:                 $this->_addFailure('date', 'invalid release date "' .
                   51454:                     $this->_packagexml->getDate() . '"');
                   51455:                 return false;
                   51456:             }
                   51457: 
                   51458:             if ($this->_state == PEAR_VALIDATE_PACKAGING &&
                   51459:                   $this->_packagexml->getDate() != date('Y-m-d')) {
                   51460:                 $this->_addWarning('date', 'Release Date "' .
                   51461:                     $this->_packagexml->getDate() . '" is not today');
                   51462:             }
                   51463:         }
                   51464:         return true;
                   51465:     }
                   51466: 
                   51467:     /**
                   51468:      * @access protected
                   51469:      */
                   51470:     function validateTime()
                   51471:     {
                   51472:         if (!$this->_packagexml->getTime()) {
                   51473:             // default of no time value set
                   51474:             return true;
                   51475:         }
                   51476: 
                   51477:         // packager automatically sets time, so only validate if pear validate is called
                   51478:         if ($this->_state = PEAR_VALIDATE_NORMAL) {
                   51479:             if (!preg_match('/\d\d:\d\d:\d\d/',
                   51480:                   $this->_packagexml->getTime())) {
                   51481:                 $this->_addFailure('time', 'invalid release time "' .
                   51482:                     $this->_packagexml->getTime() . '"');
                   51483:                 return false;
                   51484:             }
                   51485: 
                   51486:             $result = preg_match('|\d{2}\:\d{2}\:\d{2}|', $this->_packagexml->getTime(), $matches);
                   51487:             if ($result === false || empty($matches)) {
                   51488:                 $this->_addFailure('time', 'invalid release time "' .
                   51489:                     $this->_packagexml->getTime() . '"');
                   51490:                 return false;
                   51491:             }
                   51492:         }
                   51493: 
                   51494:         return true;
                   51495:     }
                   51496: 
                   51497:     /**
                   51498:      * @access protected
                   51499:      */
                   51500:     function validateState()
                   51501:     {
                   51502:         // this is the closest to "final" php4 can get
                   51503:         if (!PEAR_Validate::validState($this->_packagexml->getState())) {
                   51504:             if (strtolower($this->_packagexml->getState() == 'rc')) {
                   51505:                 $this->_addFailure('state', 'RC is not a state, it is a version ' .
                   51506:                     'postfix, use ' . $this->_packagexml->getVersion() . 'RC1, state beta');
                   51507:             }
                   51508:             $this->_addFailure('state', 'invalid release state "' .
                   51509:                 $this->_packagexml->getState() . '", must be one of: ' .
                   51510:                 implode(', ', PEAR_Validate::getValidStates()));
                   51511:             return false;
                   51512:         }
                   51513:         return true;
                   51514:     }
                   51515: 
                   51516:     /**
                   51517:      * @access protected
                   51518:      */
                   51519:     function validateStability()
                   51520:     {
                   51521:         $ret = true;
                   51522:         $packagestability = $this->_packagexml->getState();
                   51523:         $apistability = $this->_packagexml->getState('api');
                   51524:         if (!PEAR_Validate::validState($packagestability)) {
                   51525:             $this->_addFailure('state', 'invalid release stability "' .
                   51526:                 $this->_packagexml->getState() . '", must be one of: ' .
                   51527:                 implode(', ', PEAR_Validate::getValidStates()));
                   51528:             $ret = false;
                   51529:         }
                   51530:         $apistates = PEAR_Validate::getValidStates();
                   51531:         array_shift($apistates); // snapshot is not allowed
                   51532:         if (!in_array($apistability, $apistates)) {
                   51533:             $this->_addFailure('state', 'invalid API stability "' .
                   51534:                 $this->_packagexml->getState('api') . '", must be one of: ' .
                   51535:                 implode(', ', $apistates));
                   51536:             $ret = false;
                   51537:         }
                   51538:         return $ret;
                   51539:     }
                   51540: 
                   51541:     /**
                   51542:      * @access protected
                   51543:      */
                   51544:     function validateSummary()
                   51545:     {
                   51546:         return true;
                   51547:     }
                   51548: 
                   51549:     /**
                   51550:      * @access protected
                   51551:      */
                   51552:     function validateDescription()
                   51553:     {
                   51554:         return true;
                   51555:     }
                   51556: 
                   51557:     /**
                   51558:      * @access protected
                   51559:      */
                   51560:     function validateLicense()
                   51561:     {
                   51562:         return true;
                   51563:     }
                   51564: 
                   51565:     /**
                   51566:      * @access protected
                   51567:      */
                   51568:     function validateNotes()
                   51569:     {
                   51570:         return true;
                   51571:     }
                   51572: 
                   51573:     /**
                   51574:      * for package.xml 2.0 only - channels can't use package.xml 1.0
                   51575:      * @access protected
                   51576:      */
                   51577:     function validateDependencies()
                   51578:     {
                   51579:         return true;
                   51580:     }
                   51581: 
                   51582:     /**
                   51583:      * for package.xml 1.0 only
                   51584:      * @access private
                   51585:      */
                   51586:     function _validateFilelist()
                   51587:     {
                   51588:         return true; // placeholder for now
                   51589:     }
                   51590: 
                   51591:     /**
                   51592:      * for package.xml 2.0 only
                   51593:      * @access protected
                   51594:      */
                   51595:     function validateMainFilelist()
                   51596:     {
                   51597:         return true; // placeholder for now
                   51598:     }
                   51599: 
                   51600:     /**
                   51601:      * for package.xml 2.0 only
                   51602:      * @access protected
                   51603:      */
                   51604:     function validateReleaseFilelist()
                   51605:     {
                   51606:         return true; // placeholder for now
                   51607:     }
                   51608: 
                   51609:     /**
                   51610:      * @access protected
                   51611:      */
                   51612:     function validateChangelog()
                   51613:     {
                   51614:         return true;
                   51615:     }
                   51616: 
                   51617:     /**
                   51618:      * @access protected
                   51619:      */
                   51620:     function validateFilelist()
                   51621:     {
                   51622:         return true;
                   51623:     }
                   51624: 
                   51625:     /**
                   51626:      * @access protected
                   51627:      */
                   51628:     function validateDeps()
                   51629:     {
                   51630:         return true;
                   51631:     }
1.1.1.2 ! misho    51632: }PEAR-1.9.4/PEAR/XMLParser.php0000644000076500000240000001600111605156614014307 0ustar  helgistaff<?php
1.1       misho    51633: /**
                   51634:  * PEAR_XMLParser
                   51635:  *
                   51636:  * PHP versions 4 and 5
                   51637:  *
                   51638:  * @category   pear
                   51639:  * @package    PEAR
                   51640:  * @author     Greg Beaver <cellog@php.net>
                   51641:  * @author     Stephan Schmidt (original XML_Unserializer code)
                   51642:  * @copyright  1997-2009 The Authors
                   51643:  * @license   http://opensource.org/licenses/bsd-license New BSD License
                   51644:  * @version    CVS: $Id: XMLParser.php 313023 2011-07-06 19:17:11Z dufuz $
                   51645:  * @link       http://pear.php.net/package/PEAR
                   51646:  * @since      File available since Release 1.4.0a1
                   51647:  */
                   51648: 
                   51649: /**
                   51650:  * Parser for any xml file
                   51651:  * @category  pear
                   51652:  * @package   PEAR
                   51653:  * @author    Greg Beaver <cellog@php.net>
                   51654:  * @author    Stephan Schmidt (original XML_Unserializer code)
                   51655:  * @copyright 1997-2009 The Authors
                   51656:  * @license   http://opensource.org/licenses/bsd-license New BSD License
                   51657:  * @version   Release: 1.9.4
                   51658:  * @link      http://pear.php.net/package/PEAR
                   51659:  * @since     Class available since Release 1.4.0a1
                   51660:  */
                   51661: class PEAR_XMLParser
                   51662: {
                   51663:     /**
                   51664:      * unserilialized data
                   51665:      * @var string $_serializedData
                   51666:      */
                   51667:     var $_unserializedData = null;
                   51668: 
                   51669:     /**
                   51670:      * name of the root tag
                   51671:      * @var string $_root
                   51672:      */
                   51673:     var $_root = null;
                   51674: 
                   51675:     /**
                   51676:      * stack for all data that is found
                   51677:      * @var array    $_dataStack
                   51678:      */
                   51679:     var $_dataStack = array();
                   51680: 
                   51681:     /**
                   51682:      * stack for all values that are generated
                   51683:      * @var array    $_valStack
                   51684:      */
                   51685:     var $_valStack = array();
                   51686: 
                   51687:     /**
                   51688:      * current tag depth
                   51689:      * @var int    $_depth
                   51690:      */
                   51691:     var $_depth = 0;
                   51692: 
                   51693:     /**
                   51694:      * The XML encoding to use
                   51695:      * @var string $encoding
                   51696:      */
                   51697:     var $encoding = 'ISO-8859-1';
                   51698: 
                   51699:     /**
                   51700:      * @return array
                   51701:      */
                   51702:     function getData()
                   51703:     {
                   51704:         return $this->_unserializedData;
                   51705:     }
                   51706: 
                   51707:     /**
                   51708:      * @param string xml content
                   51709:      * @return true|PEAR_Error
                   51710:      */
                   51711:     function parse($data)
                   51712:     {
                   51713:         if (!extension_loaded('xml')) {
                   51714:             include_once 'PEAR.php';
                   51715:             return PEAR::raiseError("XML Extension not found", 1);
                   51716:         }
                   51717:         $this->_dataStack =  $this->_valStack = array();
                   51718:         $this->_depth = 0;
                   51719: 
                   51720:         if (
                   51721:             strpos($data, 'encoding="UTF-8"')
                   51722:             || strpos($data, 'encoding="utf-8"')
                   51723:             || strpos($data, "encoding='UTF-8'")
                   51724:             || strpos($data, "encoding='utf-8'")
                   51725:         ) {
                   51726:             $this->encoding = 'UTF-8';
                   51727:         }
                   51728: 
                   51729:         if (version_compare(phpversion(), '5.0.0', 'lt') && $this->encoding == 'UTF-8') {
                   51730:             $data = utf8_decode($data);
                   51731:             $this->encoding = 'ISO-8859-1';
                   51732:         }
                   51733: 
                   51734:         $xp = xml_parser_create($this->encoding);
                   51735:         xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, 0);
                   51736:         xml_set_object($xp, $this);
                   51737:         xml_set_element_handler($xp, 'startHandler', 'endHandler');
                   51738:         xml_set_character_data_handler($xp, 'cdataHandler');
                   51739:         if (!xml_parse($xp, $data)) {
                   51740:             $msg = xml_error_string(xml_get_error_code($xp));
                   51741:             $line = xml_get_current_line_number($xp);
                   51742:             xml_parser_free($xp);
                   51743:             include_once 'PEAR.php';
                   51744:             return PEAR::raiseError("XML Error: '$msg' on line '$line'", 2);
                   51745:         }
                   51746:         xml_parser_free($xp);
                   51747:         return true;
                   51748:     }
                   51749: 
                   51750:     /**
                   51751:      * Start element handler for XML parser
                   51752:      *
                   51753:      * @access private
                   51754:      * @param  object $parser  XML parser object
                   51755:      * @param  string $element XML element
                   51756:      * @param  array  $attribs attributes of XML tag
                   51757:      * @return void
                   51758:      */
                   51759:     function startHandler($parser, $element, $attribs)
                   51760:     {
                   51761:         $this->_depth++;
                   51762:         $this->_dataStack[$this->_depth] = null;
                   51763: 
                   51764:         $val = array(
                   51765:             'name'         => $element,
                   51766:             'value'        => null,
                   51767:             'type'         => 'string',
                   51768:             'childrenKeys' => array(),
                   51769:             'aggregKeys'   => array()
                   51770:        );
                   51771: 
                   51772:         if (count($attribs) > 0) {
                   51773:             $val['children'] = array();
                   51774:             $val['type'] = 'array';
                   51775:             $val['children']['attribs'] = $attribs;
                   51776:         }
                   51777: 
                   51778:         array_push($this->_valStack, $val);
                   51779:     }
                   51780: 
                   51781:     /**
                   51782:      * post-process data
                   51783:      *
                   51784:      * @param string $data
                   51785:      * @param string $element element name
                   51786:      */
                   51787:     function postProcess($data, $element)
                   51788:     {
                   51789:         return trim($data);
                   51790:     }
                   51791: 
                   51792:     /**
                   51793:      * End element handler for XML parser
                   51794:      *
                   51795:      * @access private
                   51796:      * @param  object XML parser object
                   51797:      * @param  string
                   51798:      * @return void
                   51799:      */
                   51800:     function endHandler($parser, $element)
                   51801:     {
                   51802:         $value = array_pop($this->_valStack);
                   51803:         $data  = $this->postProcess($this->_dataStack[$this->_depth], $element);
                   51804: 
                   51805:         // adjust type of the value
                   51806:         switch (strtolower($value['type'])) {
                   51807:             // unserialize an array
                   51808:             case 'array':
                   51809:                 if ($data !== '') {
                   51810:                     $value['children']['_content'] = $data;
                   51811:                 }
                   51812: 
                   51813:                 $value['value'] = isset($value['children']) ? $value['children'] : array();
                   51814:                 break;
                   51815: 
                   51816:             /*
                   51817:              * unserialize a null value
                   51818:              */
                   51819:             case 'null':
                   51820:                 $data = null;
                   51821:                 break;
                   51822: 
                   51823:             /*
                   51824:              * unserialize any scalar value
                   51825:              */
                   51826:             default:
                   51827:                 settype($data, $value['type']);
                   51828:                 $value['value'] = $data;
                   51829:                 break;
                   51830:         }
                   51831: 
                   51832:         $parent = array_pop($this->_valStack);
                   51833:         if ($parent === null) {
                   51834:             $this->_unserializedData = &$value['value'];
                   51835:             $this->_root = &$value['name'];
                   51836:             return true;
                   51837:         }
                   51838: 
                   51839:         // parent has to be an array
                   51840:         if (!isset($parent['children']) || !is_array($parent['children'])) {
                   51841:             $parent['children'] = array();
                   51842:             if ($parent['type'] != 'array') {
                   51843:                 $parent['type'] = 'array';
                   51844:             }
                   51845:         }
                   51846: 
                   51847:         if (!empty($value['name'])) {
                   51848:             // there already has been a tag with this name
                   51849:             if (in_array($value['name'], $parent['childrenKeys'])) {
                   51850:                 // no aggregate has been created for this tag
                   51851:                 if (!in_array($value['name'], $parent['aggregKeys'])) {
                   51852:                     if (isset($parent['children'][$value['name']])) {
                   51853:                         $parent['children'][$value['name']] = array($parent['children'][$value['name']]);
                   51854:                     } else {
                   51855:                         $parent['children'][$value['name']] = array();
                   51856:                     }
                   51857:                     array_push($parent['aggregKeys'], $value['name']);
                   51858:                 }
                   51859:                 array_push($parent['children'][$value['name']], $value['value']);
                   51860:             } else {
                   51861:                 $parent['children'][$value['name']] = &$value['value'];
                   51862:                 array_push($parent['childrenKeys'], $value['name']);
                   51863:             }
                   51864:         } else {
                   51865:             array_push($parent['children'],$value['value']);
                   51866:         }
                   51867:         array_push($this->_valStack, $parent);
                   51868: 
                   51869:         $this->_depth--;
                   51870:     }
                   51871: 
                   51872:     /**
                   51873:      * Handler for character data
                   51874:      *
                   51875:      * @access private
                   51876:      * @param  object XML parser object
                   51877:      * @param  string CDATA
                   51878:      * @return void
                   51879:      */
                   51880:     function cdataHandler($parser, $cdata)
                   51881:     {
                   51882:         $this->_dataStack[$this->_depth] .= $cdata;
                   51883:     }
1.1.1.2 ! misho    51884: }PEAR-1.9.4/scripts/pear.bat0000755000076500000240000001036111605156614014346 0ustar  helgistaff@ECHO OFF
1.1       misho    51885: 
                   51886: REM ----------------------------------------------------------------------
                   51887: REM PHP version 5
                   51888: REM ----------------------------------------------------------------------
                   51889: REM Copyright (c) 1997-2010 The Authors
                   51890: REM ----------------------------------------------------------------------
                   51891: REM http://opensource.org/licenses/bsd-license.php New BSD License
                   51892: REM ----------------------------------------------------------------------
                   51893: REM  Authors:     Alexander Merz (alexmerz@php.net)
                   51894: REM ----------------------------------------------------------------------
                   51895: REM
                   51896: REM  Last updated 12/29/2004 ($Id$ is not replaced if the file is binary)
                   51897: 
                   51898: REM change this lines to match the paths of your system
                   51899: REM -------------------
                   51900: 
                   51901: 
                   51902: REM Test to see if this is a raw pear.bat (uninstalled version)
                   51903: SET TMPTMPTMPTMPT=@includ
                   51904: SET PMTPMTPMT=%TMPTMPTMPTMPT%e_path@
                   51905: FOR %%x IN ("@include_path@") DO (if %%x=="%PMTPMTPMT%" GOTO :NOTINSTALLED)
                   51906: 
                   51907: REM Check PEAR global ENV, set them if they do not exist
                   51908: IF "%PHP_PEAR_INSTALL_DIR%"=="" SET "PHP_PEAR_INSTALL_DIR=@include_path@"
                   51909: IF "%PHP_PEAR_BIN_DIR%"=="" SET "PHP_PEAR_BIN_DIR=@bin_dir@"
                   51910: IF "%PHP_PEAR_PHP_BIN%"=="" SET "PHP_PEAR_PHP_BIN=@php_bin@"
                   51911: 
                   51912: GOTO :INSTALLED
                   51913: 
                   51914: :NOTINSTALLED
                   51915: ECHO WARNING: This is a raw, uninstalled pear.bat
                   51916: 
                   51917: REM Check to see if we can grab the directory of this file (Windows NT+)
                   51918: IF %~n0 == pear (
                   51919: FOR %%x IN (cli\php.exe php.exe) DO (if "%%~$PATH:x" NEQ "" (
                   51920: SET "PHP_PEAR_PHP_BIN=%%~$PATH:x"
                   51921: echo Using PHP Executable "%PHP_PEAR_PHP_BIN%"
                   51922: "%PHP_PEAR_PHP_BIN%" -v
                   51923: GOTO :NEXTTEST
                   51924: ))
                   51925: GOTO :FAILAUTODETECT
                   51926: :NEXTTEST
                   51927: IF "%PHP_PEAR_PHP_BIN%" NEQ "" (
                   51928: 
                   51929: REM We can use this PHP to run a temporary php file to get the dirname of pear
                   51930: 
                   51931: echo ^<?php $s=getcwd^(^);chdir^($a=dirname^(__FILE__^).'\\'^);if^(stristr^($a,'\\scripts'^)^)$a=dirname^(dirname^($a^)^).'\\';$f=fopen^($s.'\\~a.a','wb'^);echo$s.'\\~a.a';fwrite^($f,$a^);fclose^($f^);chdir^($s^);?^> > ~~getloc.php
                   51932: "%PHP_PEAR_PHP_BIN%" ~~getloc.php
                   51933: set /p PHP_PEAR_BIN_DIR=fakeprompt < ~a.a
                   51934: DEL ~a.a
                   51935: DEL ~~getloc.php
                   51936: set "PHP_PEAR_INSTALL_DIR=%PHP_PEAR_BIN_DIR%pear"
                   51937: 
                   51938: REM Make sure there is a pearcmd.php at our disposal
                   51939: 
                   51940: IF NOT EXIST %PHP_PEAR_INSTALL_DIR%\pearcmd.php (
                   51941: IF EXIST %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php COPY %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php
                   51942: IF EXIST pearcmd.php COPY pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php
                   51943: IF EXIST %~dp0\scripts\pearcmd.php COPY %~dp0\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php
                   51944: )
                   51945: )
                   51946: GOTO :INSTALLED
                   51947: ) ELSE (
                   51948: REM Windows Me/98 cannot succeed, so allow the batch to fail
                   51949: )
                   51950: :FAILAUTODETECT
                   51951: echo WARNING: failed to auto-detect pear information
                   51952: :INSTALLED
                   51953: 
                   51954: REM Check Folders and files
                   51955: IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%" GOTO PEAR_INSTALL_ERROR
                   51956: IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" GOTO PEAR_INSTALL_ERROR2
                   51957: IF NOT EXIST "%PHP_PEAR_BIN_DIR%" GOTO PEAR_BIN_ERROR
                   51958: IF NOT EXIST "%PHP_PEAR_PHP_BIN%" GOTO PEAR_PHPBIN_ERROR
                   51959: 
                   51960: REM launch pearcmd
                   51961: GOTO RUN
                   51962: :PEAR_INSTALL_ERROR
                   51963: ECHO PHP_PEAR_INSTALL_DIR is not set correctly.
                   51964: ECHO Please fix it using your environment variable or modify
                   51965: ECHO the default value in pear.bat
                   51966: ECHO The current value is:
                   51967: ECHO %PHP_PEAR_INSTALL_DIR%
                   51968: GOTO END
                   51969: :PEAR_INSTALL_ERROR2
                   51970: ECHO PHP_PEAR_INSTALL_DIR is not set correctly.
                   51971: ECHO pearcmd.php could not be found there.
                   51972: ECHO Please fix it using your environment variable or modify
                   51973: ECHO the default value in pear.bat
                   51974: ECHO The current value is:
                   51975: ECHO %PHP_PEAR_INSTALL_DIR%
                   51976: GOTO END
                   51977: :PEAR_BIN_ERROR
                   51978: ECHO PHP_PEAR_BIN_DIR is not set correctly.
                   51979: ECHO Please fix it using your environment variable or modify
                   51980: ECHO the default value in pear.bat
                   51981: ECHO The current value is:
                   51982: ECHO %PHP_PEAR_BIN_DIR%
                   51983: GOTO END
                   51984: :PEAR_PHPBIN_ERROR
                   51985: ECHO PHP_PEAR_PHP_BIN is not set correctly.
                   51986: ECHO Please fix it using your environment variable or modify
                   51987: ECHO the default value in pear.bat
                   51988: ECHO The current value is:
                   51989: ECHO %PHP_PEAR_PHP_BIN%
                   51990: GOTO END
                   51991: :RUN
                   51992: "%PHP_PEAR_PHP_BIN%" -C -d date.timezone=UTC -d output_buffering=1 -d safe_mode=0 -d open_basedir="" -d auto_prepend_file="" -d auto_append_file="" -d variables_order=EGPCS -d register_argc_argv="On" -d "include_path='%PHP_PEAR_INSTALL_DIR%'" -f "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" -- %1 %2 %3 %4 %5 %6 %7 %8 %9
                   51993: :END
1.1.1.2 ! misho    51994: @ECHO ONPEAR-1.9.4/scripts/peardev.bat0000644000076500000240000001113711605156614015044 0ustar  helgistaff@ECHO OFF
1.1       misho    51995: 
                   51996: REM ----------------------------------------------------------------------
                   51997: REM PHP version 5
                   51998: REM ----------------------------------------------------------------------
                   51999: REM Copyright (c) 1997-2004 The PHP Group
                   52000: REM ----------------------------------------------------------------------
                   52001: REM  This source file is subject to version 3.0 of the PHP license,
                   52002: REM  that is bundled with this package in the file LICENSE, and is
                   52003: REM  available at through the world-wide-web at
                   52004: REM  http://www.php.net/license/3_0.txt.
                   52005: REM  If you did not receive a copy of the PHP license and are unable to
                   52006: REM  obtain it through the world-wide-web, please send a note to
                   52007: REM  license@php.net so we can mail you a copy immediately.
                   52008: REM ----------------------------------------------------------------------
                   52009: REM  Authors:     Alexander Merz (alexmerz@php.net)
                   52010: REM ----------------------------------------------------------------------
                   52011: REM
                   52012: REM  $Id: peardev.bat,v 1.6 2007-09-03 03:00:17 cellog Exp $
                   52013: 
                   52014: REM change this lines to match the paths of your system
                   52015: REM -------------------
                   52016: 
                   52017: 
                   52018: REM Test to see if this is a raw pear.bat (uninstalled version)
                   52019: SET TMPTMPTMPTMPT=@includ
                   52020: SET PMTPMTPMT=%TMPTMPTMPTMPT%e_path@
                   52021: FOR %%x IN ("@include_path@") DO (if %%x=="%PMTPMTPMT%" GOTO :NOTINSTALLED)
                   52022: 
                   52023: REM Check PEAR global ENV, set them if they do not exist
                   52024: IF "%PHP_PEAR_INSTALL_DIR%"=="" SET "PHP_PEAR_INSTALL_DIR=@include_path@"
                   52025: IF "%PHP_PEAR_BIN_DIR%"=="" SET "PHP_PEAR_BIN_DIR=@bin_dir@"
                   52026: IF "%PHP_PEAR_PHP_BIN%"=="" SET "PHP_PEAR_PHP_BIN=@php_bin@"
                   52027: GOTO :INSTALLED
                   52028: 
                   52029: :NOTINSTALLED
                   52030: ECHO WARNING: This is a raw, uninstalled pear.bat
                   52031: 
                   52032: REM Check to see if we can grab the directory of this file (Windows NT+)
                   52033: IF %~n0 == pear (
                   52034: FOR %%x IN (cli\php.exe php.exe) DO (if "%%~$PATH:x" NEQ "" (
                   52035: SET "PHP_PEAR_PHP_BIN=%%~$PATH:x"
                   52036: echo Using PHP Executable "%PHP_PEAR_PHP_BIN%"
                   52037: "%PHP_PEAR_PHP_BIN%" -v
                   52038: GOTO :NEXTTEST
                   52039: ))
                   52040: GOTO :FAILAUTODETECT
                   52041: :NEXTTEST
                   52042: IF "%PHP_PEAR_PHP_BIN%" NEQ "" (
                   52043: 
                   52044: REM We can use this PHP to run a temporary php file to get the dirname of pear
                   52045: 
                   52046: echo ^<?php $s=getcwd^(^);chdir^($a=dirname^(__FILE__^).'\\'^);if^(stristr^($a,'\\scripts'^)^)$a=dirname^(dirname^($a^)^).'\\';$f=fopen^($s.'\\~a.a','wb'^);echo$s.'\\~a.a';fwrite^($f,$a^);fclose^($f^);chdir^($s^);?^> > ~~getloc.php
                   52047: "%PHP_PEAR_PHP_BIN%" ~~getloc.php
                   52048: set /p PHP_PEAR_BIN_DIR=fakeprompt < ~a.a
                   52049: DEL ~a.a
                   52050: DEL ~~getloc.php
                   52051: set "PHP_PEAR_INSTALL_DIR=%PHP_PEAR_BIN_DIR%pear"
                   52052: 
                   52053: REM Make sure there is a pearcmd.php at our disposal
                   52054: 
                   52055: IF NOT EXIST %PHP_PEAR_INSTALL_DIR%\pearcmd.php (
                   52056: IF EXIST %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php COPY %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php
                   52057: IF EXIST pearcmd.php COPY pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php
                   52058: IF EXIST %~dp0\scripts\pearcmd.php COPY %~dp0\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php
                   52059: )
                   52060: )
                   52061: GOTO :INSTALLED
                   52062: ) ELSE (
                   52063: REM Windows Me/98 cannot succeed, so allow the batch to fail
                   52064: )
                   52065: :FAILAUTODETECT
                   52066: echo WARNING: failed to auto-detect pear information
                   52067: :INSTALLED
                   52068: 
                   52069: REM Check Folders and files
                   52070: IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%" GOTO PEAR_INSTALL_ERROR
                   52071: IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" GOTO PEAR_INSTALL_ERROR2
                   52072: IF NOT EXIST "%PHP_PEAR_BIN_DIR%" GOTO PEAR_BIN_ERROR
                   52073: IF NOT EXIST "%PHP_PEAR_PHP_BIN%" GOTO PEAR_PHPBIN_ERROR
                   52074: REM launch pearcmd
                   52075: GOTO RUN
                   52076: :PEAR_INSTALL_ERROR
                   52077: ECHO PHP_PEAR_INSTALL_DIR is not set correctly.
                   52078: ECHO Please fix it using your environment variable or modify
                   52079: ECHO the default value in pear.bat
                   52080: ECHO The current value is:
                   52081: ECHO %PHP_PEAR_INSTALL_DIR%
                   52082: GOTO END
                   52083: :PEAR_INSTALL_ERROR2
                   52084: ECHO PHP_PEAR_INSTALL_DIR is not set correctly.
                   52085: ECHO pearcmd.php could not be found there.
                   52086: ECHO Please fix it using your environment variable or modify
                   52087: ECHO the default value in pear.bat
                   52088: ECHO The current value is:
                   52089: ECHO %PHP_PEAR_INSTALL_DIR%
                   52090: GOTO END
                   52091: :PEAR_BIN_ERROR
                   52092: ECHO PHP_PEAR_BIN_DIR is not set correctly.
                   52093: ECHO Please fix it using your environment variable or modify
                   52094: ECHO the default value in pear.bat
                   52095: ECHO The current value is:
                   52096: ECHO %PHP_PEAR_BIN_DIR%
                   52097: GOTO END
                   52098: :PEAR_PHPBIN_ERROR
                   52099: ECHO PHP_PEAR_PHP_BIN is not set correctly.
                   52100: ECHO Please fix it using your environment variable or modify
                   52101: ECHO the default value in pear.bat
                   52102: ECHO The current value is:
                   52103: ECHO %PHP_PEAR_PHP_BIN%
                   52104: GOTO END
                   52105: :RUN
                   52106: "%PHP_PEAR_PHP_BIN%" -C -d date.timezone=UTC -d memory_limit="-1" -d safe_mode=0 -d register_argc_argv="On" -d auto_prepend_file="" -d auto_append_file="" -d variables_order=EGPCS -d open_basedir="" -d output_buffering=1 -d "include_path='%PHP_PEAR_INSTALL_DIR%'" -f "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" -- %1 %2 %3 %4 %5 %6 %7 %8 %9
                   52107: :END
1.1.1.2 ! misho    52108: @ECHO ONPEAR-1.9.4/scripts/pecl.bat0000644000076500000240000001103011605156614014331 0ustar  helgistaff@ECHO OFF
1.1       misho    52109: 
                   52110: REM ----------------------------------------------------------------------
                   52111: REM PHP version 5
                   52112: REM ----------------------------------------------------------------------
                   52113: REM Copyright (c) 1997-2004 The PHP Group
                   52114: REM ----------------------------------------------------------------------
                   52115: REM  This source file is subject to version 3.0 of the PHP license,
                   52116: REM  that is bundled with this package in the file LICENSE, and is
                   52117: REM  available at through the world-wide-web at
                   52118: REM  http://www.php.net/license/3_0.txt.
                   52119: REM  If you did not receive a copy of the PHP license and are unable to
                   52120: REM  obtain it through the world-wide-web, please send a note to
                   52121: REM  license@php.net so we can mail you a copy immediately.
                   52122: REM ----------------------------------------------------------------------
                   52123: REM  Authors:     Alexander Merz (alexmerz@php.net)
                   52124: REM ----------------------------------------------------------------------
                   52125: REM
                   52126: REM  Last updated 02/08/2004 ($Id$ is not replaced if the file is binary)
                   52127: 
                   52128: REM change this lines to match the paths of your system
                   52129: REM -------------------
                   52130: 
                   52131: 
                   52132: REM Test to see if this is a raw pear.bat (uninstalled version)
                   52133: SET TMPTMPTMPTMPT=@includ
                   52134: SET PMTPMTPMT=%TMPTMPTMPTMPT%e_path@
                   52135: FOR %%x IN ("@include_path@") DO (if %%x=="%PMTPMTPMT%" GOTO :NOTINSTALLED)
                   52136: 
                   52137: REM Check PEAR global ENV, set them if they do not exist
                   52138: IF "%PHP_PEAR_INSTALL_DIR%"=="" SET "PHP_PEAR_INSTALL_DIR=@include_path@"
                   52139: IF "%PHP_PEAR_BIN_DIR%"=="" SET "PHP_PEAR_BIN_DIR=@bin_dir@"
                   52140: IF "%PHP_PEAR_PHP_BIN%"=="" SET "PHP_PEAR_PHP_BIN=@php_bin@"
                   52141: GOTO :INSTALLED
                   52142: 
                   52143: :NOTINSTALLED
                   52144: ECHO WARNING: This is a raw, uninstalled pear.bat
                   52145: 
                   52146: REM Check to see if we can grab the directory of this file (Windows NT+)
                   52147: IF %~n0 == pear (
                   52148: FOR %%x IN (cli\php.exe php.exe) DO (if "%%~$PATH:x" NEQ "" (
                   52149: SET "PHP_PEAR_PHP_BIN=%%~$PATH:x"
                   52150: echo Using PHP Executable "%PHP_PEAR_PHP_BIN%"
                   52151: "%PHP_PEAR_PHP_BIN%" -v
                   52152: GOTO :NEXTTEST
                   52153: ))
                   52154: GOTO :FAILAUTODETECT
                   52155: :NEXTTEST
                   52156: IF "%PHP_PEAR_PHP_BIN%" NEQ "" (
                   52157: 
                   52158: REM We can use this PHP to run a temporary php file to get the dirname of pear
                   52159: 
                   52160: echo ^<?php $s=getcwd^(^);chdir^($a=dirname^(__FILE__^).'\\'^);if^(stristr^($a,'\\scripts'^)^)$a=dirname^(dirname^($a^)^).'\\';$f=fopen^($s.'\\~a.a','wb'^);echo$s.'\\~a.a';fwrite^($f,$a^);fclose^($f^);chdir^($s^);?^> > ~~getloc.php
                   52161: "%PHP_PEAR_PHP_BIN%" ~~getloc.php
                   52162: set /p PHP_PEAR_BIN_DIR=fakeprompt < ~a.a
                   52163: DEL ~a.a
                   52164: DEL ~~getloc.php
                   52165: set "PHP_PEAR_INSTALL_DIR=%PHP_PEAR_BIN_DIR%pear"
                   52166: 
                   52167: REM Make sure there is a pearcmd.php at our disposal
                   52168: 
                   52169: IF NOT EXIST %PHP_PEAR_INSTALL_DIR%\pearcmd.php (
                   52170: IF EXIST %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php COPY %PHP_PEAR_INSTALL_DIR%\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php
                   52171: IF EXIST pearcmd.php COPY pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php
                   52172: IF EXIST %~dp0\scripts\pearcmd.php COPY %~dp0\scripts\pearcmd.php %PHP_PEAR_INSTALL_DIR%\pearcmd.php
                   52173: )
                   52174: )
                   52175: GOTO :INSTALLED
                   52176: ) ELSE (
                   52177: REM Windows Me/98 cannot succeed, so allow the batch to fail
                   52178: )
                   52179: :FAILAUTODETECT
                   52180: echo WARNING: failed to auto-detect pear information
                   52181: :INSTALLED
                   52182: 
                   52183: REM Check Folders and files
                   52184: IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%" GOTO PEAR_INSTALL_ERROR
                   52185: IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" GOTO PEAR_INSTALL_ERROR2
                   52186: IF NOT EXIST "%PHP_PEAR_BIN_DIR%" GOTO PEAR_BIN_ERROR
                   52187: IF NOT EXIST "%PHP_PEAR_PHP_BIN%" GOTO PEAR_PHPBIN_ERROR
                   52188: REM launch pearcmd
                   52189: GOTO RUN
                   52190: :PEAR_INSTALL_ERROR
                   52191: ECHO PHP_PEAR_INSTALL_DIR is not set correctly.
                   52192: ECHO Please fix it using your environment variable or modify
                   52193: ECHO the default value in pear.bat
                   52194: ECHO The current value is:
                   52195: ECHO %PHP_PEAR_INSTALL_DIR%
                   52196: GOTO END
                   52197: :PEAR_INSTALL_ERROR2
                   52198: ECHO PHP_PEAR_INSTALL_DIR is not set correctly.
                   52199: ECHO pearcmd.php could not be found there.
                   52200: ECHO Please fix it using your environment variable or modify
                   52201: ECHO the default value in pear.bat
                   52202: ECHO The current value is:
                   52203: ECHO %PHP_PEAR_INSTALL_DIR%
                   52204: GOTO END
                   52205: :PEAR_BIN_ERROR
                   52206: ECHO PHP_PEAR_BIN_DIR is not set correctly.
                   52207: ECHO Please fix it using your environment variable or modify
                   52208: ECHO the default value in pear.bat
                   52209: ECHO The current value is:
                   52210: ECHO %PHP_PEAR_BIN_DIR%
                   52211: GOTO END
                   52212: :PEAR_PHPBIN_ERROR
                   52213: ECHO PHP_PEAR_PHP_BIN is not set correctly.
                   52214: ECHO Please fix it using your environment variable or modify
                   52215: ECHO the default value in pear.bat
                   52216: ECHO The current value is:
                   52217: ECHO %PHP_PEAR_PHP_BIN%
                   52218: GOTO END
                   52219: :RUN
                   52220: "%PHP_PEAR_PHP_BIN%" -C -n -d date.timezone=UTC -d output_buffering=1 -d safe_mode=0 -d "include_path='%PHP_PEAR_INSTALL_DIR%'" -d register_argc_argv="On" -d variables_order=EGPCS -f "%PHP_PEAR_INSTALL_DIR%\peclcmd.php" -- %1 %2 %3 %4 %5 %6 %7 %8 %9
                   52221: :END
1.1.1.2 ! misho    52222: @ECHO ONPEAR-1.9.4/scripts/pear.sh0000644000076500000240000000140411605156614014205 0ustar  helgistaff#!/bin/sh
1.1       misho    52223: 
                   52224: # first find which PHP binary to use
                   52225: if test "x$PHP_PEAR_PHP_BIN" != "x"; then
                   52226:   PHP="$PHP_PEAR_PHP_BIN"
                   52227: else
                   52228:   if test "@php_bin@" = '@'php_bin'@'; then
                   52229:     PHP=php
                   52230:   else
                   52231:     PHP="@php_bin@"
                   52232:   fi
                   52233: fi
                   52234: 
                   52235: # then look for the right pear include dir
                   52236: if test "x$PHP_PEAR_INSTALL_DIR" != "x"; then
                   52237:   INCDIR=$PHP_PEAR_INSTALL_DIR
                   52238:   INCARG="-d include_path=$PHP_PEAR_INSTALL_DIR"
                   52239: else
                   52240:   if test "@php_dir@" = '@'php_dir'@'; then
                   52241:     INCDIR=`dirname $0`
                   52242:     INCARG=""
                   52243:   else
                   52244:     INCDIR="@php_dir@"
                   52245:     INCARG="-d include_path=@php_dir@"
                   52246:   fi
                   52247: fi
                   52248: 
                   52249: exec $PHP -C -q $INCARG -d date.timezone=UTC -d output_buffering=1 -d variables_order=EGPCS -d open_basedir="" -d safe_mode=0 -d register_argc_argv="On" -d auto_prepend_file="" -d auto_append_file="" $INCDIR/pearcmd.php "$@"
1.1.1.2 ! misho    52250: PEAR-1.9.4/scripts/peardev.sh0000644000076500000240000000143111605156614014704 0ustar  helgistaff#!/bin/sh
1.1       misho    52251: 
                   52252: # first find which PHP binary to use
                   52253: if test "x$PHP_PEAR_PHP_BIN" != "x"; then
                   52254:   PHP="$PHP_PEAR_PHP_BIN"
                   52255: else
                   52256:   if test "@php_bin@" = '@'php_bin'@'; then
                   52257:     PHP=php
                   52258:   else
                   52259:     PHP="@php_bin@"
                   52260:   fi
                   52261: fi
                   52262: 
                   52263: # then look for the right pear include dir
                   52264: if test "x$PHP_PEAR_INSTALL_DIR" != "x"; then
                   52265:   INCDIR=$PHP_PEAR_INSTALL_DIR
                   52266:   INCARG="-d include_path=$PHP_PEAR_INSTALL_DIR"
                   52267: else
                   52268:   if test "@php_dir@" = '@'php_dir'@'; then
                   52269:     INCDIR=`dirname $0`
                   52270:     INCARG=""
                   52271:   else
                   52272:     INCDIR="@php_dir@"
                   52273:     INCARG="-d include_path=@php_dir@"
                   52274:   fi
                   52275: fi
                   52276: 
                   52277: exec $PHP -d date.timezone=UTC -d memory_limit="-1" -C -q $INCARG -d output_buffering=1 -d open_basedir="" -d safe_mode=0 -d register_argc_argv="On" -d auto_prepend_file="" -d variables_order=EGPCS -d auto_append_file="" $INCDIR/pearcmd.php "$@"
1.1.1.2 ! misho    52278: PEAR-1.9.4/scripts/pecl.sh0000644000076500000240000000130511605156614014201 0ustar  helgistaff#!/bin/sh
1.1       misho    52279: 
                   52280: # first find which PHP binary to use
                   52281: if test "x$PHP_PEAR_PHP_BIN" != "x"; then
                   52282:   PHP="$PHP_PEAR_PHP_BIN"
                   52283: else
                   52284:   if test "@php_bin@" = '@'php_bin'@'; then
                   52285:     PHP=php
                   52286:   else
                   52287:     PHP="@php_bin@"
                   52288:   fi
                   52289: fi
                   52290: 
                   52291: # then look for the right pear include dir
                   52292: if test "x$PHP_PEAR_INSTALL_DIR" != "x"; then
                   52293:   INCDIR=$PHP_PEAR_INSTALL_DIR
                   52294:   INCARG="-d include_path=$PHP_PEAR_INSTALL_DIR"
                   52295: else
                   52296:   if test "@php_dir@" = '@'php_dir'@'; then
                   52297:     INCDIR=`dirname $0`
                   52298:     INCARG=""
                   52299:   else
                   52300:     INCDIR="@php_dir@"
                   52301:     INCARG="-d include_path=@php_dir@"
                   52302:   fi
                   52303: fi
                   52304: 
                   52305: exec $PHP -C -n -q $INCARG -d date.timezone=UTC -d output_buffering=1 -d variables_order=EGPCS -d safe_mode=0 -d register_argc_argv="On" $INCDIR/peclcmd.php "$@"
1.1.1.2 ! misho    52306: PEAR-1.9.4/scripts/pearcmd.php0000644000076500000240000003414511605156614015056 0ustar  helgistaff<?php
1.1       misho    52307: /**
                   52308:  * PEAR, the PHP Extension and Application Repository
                   52309:  *
                   52310:  * Command line interface
                   52311:  *
                   52312:  * PHP versions 4 and 5
                   52313:  *
                   52314:  * @category   pear
                   52315:  * @package    PEAR
                   52316:  * @author     Stig Bakken <ssb@php.net>
                   52317:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   52318:  * @copyright  1997-2009 The Authors
                   52319:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   52320:  * @version    CVS: $Id: pearcmd.php 313023 2011-07-06 19:17:11Z dufuz $
                   52321:  * @link       http://pear.php.net/package/PEAR
                   52322:  */
                   52323: 
                   52324: ob_end_clean();
                   52325: if (!defined('PEAR_RUNTYPE')) {
                   52326:     // this is defined in peclcmd.php as 'pecl'
                   52327:     define('PEAR_RUNTYPE', 'pear');
                   52328: }
                   52329: define('PEAR_IGNORE_BACKTRACE', 1);
                   52330: /**
                   52331:  * @nodep Gtk
                   52332:  */
                   52333: if ('@include_path@' != '@'.'include_path'.'@') {
                   52334:     ini_set('include_path', '@include_path@');
                   52335:     $raw = false;
                   52336: } else {
                   52337:     // this is a raw, uninstalled pear, either a cvs checkout, or php distro
                   52338:     $raw = true;
                   52339: }
                   52340: @ini_set('allow_url_fopen', true);
                   52341: if (!ini_get('safe_mode')) {
                   52342:     @set_time_limit(0);
                   52343: }
                   52344: ob_implicit_flush(true);
                   52345: @ini_set('track_errors', true);
                   52346: @ini_set('html_errors', false);
                   52347: @ini_set('magic_quotes_runtime', false);
                   52348: $_PEAR_PHPDIR = '#$%^&*';
                   52349: set_error_handler('error_handler');
                   52350: 
                   52351: $pear_package_version = "@pear_version@";
                   52352: 
                   52353: require_once 'PEAR.php';
                   52354: require_once 'PEAR/Frontend.php';
                   52355: require_once 'PEAR/Config.php';
                   52356: require_once 'PEAR/Command.php';
                   52357: require_once 'Console/Getopt.php';
                   52358: 
                   52359: 
                   52360: PEAR_Command::setFrontendType('CLI');
                   52361: $all_commands = PEAR_Command::getCommands();
                   52362: 
                   52363: // remove this next part when we stop supporting that crap-ass PHP 4.2
                   52364: if (!isset($_SERVER['argv']) && !isset($argv) && !isset($HTTP_SERVER_VARS['argv'])) {
                   52365:     echo 'ERROR: either use the CLI php executable, or set register_argc_argv=On in php.ini';
                   52366:     exit(1);
                   52367: }
                   52368: 
                   52369: $argv = Console_Getopt::readPHPArgv();
                   52370: // fix CGI sapi oddity - the -- in pear.bat/pear is not removed
                   52371: if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
                   52372:     unset($argv[1]);
                   52373:     $argv = array_values($argv);
                   52374: }
                   52375: $progname = PEAR_RUNTYPE;
                   52376: array_shift($argv);
                   52377: $options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV");
                   52378: if (PEAR::isError($options)) {
                   52379:     usage($options);
                   52380: }
                   52381: 
                   52382: $opts = $options[0];
                   52383: 
                   52384: $fetype = 'CLI';
                   52385: if ($progname == 'gpear' || $progname == 'pear-gtk') {
                   52386:     $fetype = 'Gtk';
                   52387: } else {
                   52388:     foreach ($opts as $opt) {
                   52389:         if ($opt[0] == 'G') {
                   52390:             $fetype = 'Gtk';
                   52391:         }
                   52392:     }
                   52393: }
                   52394: //Check if Gtk and PHP >= 5.1.0
                   52395: if ($fetype == 'Gtk' && version_compare(phpversion(), '5.1.0', '>=')) {
                   52396:     $fetype = 'Gtk2';
                   52397: }
                   52398: 
                   52399: $pear_user_config = '';
                   52400: $pear_system_config = '';
                   52401: $store_user_config = false;
                   52402: $store_system_config = false;
                   52403: $verbose = 1;
                   52404: 
                   52405: foreach ($opts as $opt) {
                   52406:     switch ($opt[0]) {
                   52407:         case 'c':
                   52408:             $pear_user_config = $opt[1];
                   52409:             break;
                   52410:         case 'C':
                   52411:             $pear_system_config = $opt[1];
                   52412:             break;
                   52413:     }
                   52414: }
                   52415: 
                   52416: PEAR_Command::setFrontendType($fetype);
                   52417: $ui = &PEAR_Command::getFrontendObject();
                   52418: $config = &PEAR_Config::singleton($pear_user_config, $pear_system_config);
                   52419: 
                   52420: if (PEAR::isError($config)) {
                   52421:     $_file = '';
                   52422:     if ($pear_user_config !== false) {
                   52423:        $_file .= $pear_user_config;
                   52424:     }
                   52425:     if ($pear_system_config !== false) {
                   52426:        $_file .= '/' . $pear_system_config;
                   52427:     }
                   52428:     if ($_file == '/') {
                   52429:         $_file = 'The default config file';
                   52430:     }
                   52431:     $config->getMessage();
                   52432:     $ui->outputData("ERROR: $_file is not a valid config file or is corrupted.");
                   52433:     // We stop, we have no idea where we are :)
                   52434:     exit(1);
                   52435: }
                   52436: 
                   52437: // this is used in the error handler to retrieve a relative path
                   52438: $_PEAR_PHPDIR = $config->get('php_dir');
                   52439: $ui->setConfig($config);
                   52440: PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));
                   52441: if (ini_get('safe_mode')) {
                   52442:     $ui->outputData('WARNING: running in safe mode requires that all files created ' .
                   52443:         'be the same uid as the current script.  PHP reports this script is uid: ' .
                   52444:         @getmyuid() . ', and current user is: ' . @get_current_user());
                   52445: }
                   52446: 
                   52447: $verbose = $config->get("verbose");
                   52448: $cmdopts = array();
                   52449: 
                   52450: if ($raw) {
                   52451:     if (!$config->isDefinedLayer('user') && !$config->isDefinedLayer('system')) {
                   52452:         $found = false;
                   52453:         foreach ($opts as $opt) {
                   52454:             if ($opt[0] == 'd' || $opt[0] == 'D') {
                   52455:                 $found = true; // the user knows what they are doing, and are setting config values
                   52456:             }
                   52457:         }
                   52458:         if (!$found) {
                   52459:             // no prior runs, try to install PEAR
                   52460:             if (strpos(dirname(__FILE__), 'scripts')) {
                   52461:                 $packagexml = dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'package2.xml';
                   52462:                 $pearbase = dirname(dirname(__FILE__));
                   52463:             } else {
                   52464:                 $packagexml = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'package2.xml';
                   52465:                 $pearbase = dirname(__FILE__);
                   52466:             }
                   52467:             if (file_exists($packagexml)) {
                   52468:                 $options[1] = array(
                   52469:                     'install',
                   52470:                     $packagexml
                   52471:                 );
                   52472:                 $config->set('php_dir', $pearbase . DIRECTORY_SEPARATOR . 'php');
                   52473:                 $config->set('data_dir', $pearbase . DIRECTORY_SEPARATOR . 'data');
                   52474:                 $config->set('doc_dir', $pearbase . DIRECTORY_SEPARATOR . 'docs');
                   52475:                 $config->set('test_dir', $pearbase . DIRECTORY_SEPARATOR . 'tests');
                   52476:                 $config->set('ext_dir', $pearbase . DIRECTORY_SEPARATOR . 'extensions');
                   52477:                 $config->set('bin_dir', $pearbase);
                   52478:                 $config->mergeConfigFile($pearbase . 'pear.ini', false);
                   52479:                 $config->store();
                   52480:                 $config->set('auto_discover', 1);
                   52481:             }
                   52482:         }
                   52483:     }
                   52484: }
                   52485: foreach ($opts as $opt) {
                   52486:     $param = !empty($opt[1]) ? $opt[1] : true;
                   52487:     switch ($opt[0]) {
                   52488:         case 'd':
                   52489:             if ($param === true) {
                   52490:                 die('Invalid usage of "-d" option, expected -d config_value=value, ' .
                   52491:                     'received "-d"' . "\n");
                   52492:             }
                   52493:             $possible = explode('=', $param);
                   52494:             if (count($possible) != 2) {
                   52495:                 die('Invalid usage of "-d" option, expected -d config_value=value, received "' .
                   52496:                     $param . '"' . "\n");
                   52497:             }
                   52498:             list($key, $value) = explode('=', $param);
                   52499:             $config->set($key, $value, 'user');
                   52500:             break;
                   52501:         case 'D':
                   52502:             if ($param === true) {
                   52503:                 die('Invalid usage of "-d" option, expected -d config_value=value, ' .
                   52504:                     'received "-d"' . "\n");
                   52505:             }
                   52506:             $possible = explode('=', $param);
                   52507:             if (count($possible) != 2) {
                   52508:                 die('Invalid usage of "-d" option, expected -d config_value=value, received "' .
                   52509:                     $param . '"' . "\n");
                   52510:             }
                   52511:             list($key, $value) = explode('=', $param);
                   52512:             $config->set($key, $value, 'system');
                   52513:             break;
                   52514:         case 's':
                   52515:             $store_user_config = true;
                   52516:             break;
                   52517:         case 'S':
                   52518:             $store_system_config = true;
                   52519:             break;
                   52520:         case 'u':
                   52521:             $config->remove($param, 'user');
                   52522:             break;
                   52523:         case 'v':
                   52524:             $config->set('verbose', $config->get('verbose') + 1);
                   52525:             break;
                   52526:         case 'q':
                   52527:             $config->set('verbose', $config->get('verbose') - 1);
                   52528:             break;
                   52529:         case 'V':
                   52530:             usage(null, 'version');
                   52531:         case 'c':
                   52532:         case 'C':
                   52533:             break;
                   52534:         default:
                   52535:             // all non pear params goes to the command
                   52536:             $cmdopts[$opt[0]] = $param;
                   52537:             break;
                   52538:     }
                   52539: }
                   52540: 
                   52541: if ($store_system_config) {
                   52542:     $config->store('system');
                   52543: }
                   52544: 
                   52545: if ($store_user_config) {
                   52546:     $config->store('user');
                   52547: }
                   52548: 
                   52549: $command = (isset($options[1][0])) ? $options[1][0] : null;
                   52550: if (empty($command) && ($store_user_config || $store_system_config)) {
                   52551:     exit;
                   52552: }
                   52553: 
                   52554: if ($fetype == 'Gtk' || $fetype == 'Gtk2') {
                   52555:     if (!$config->validConfiguration()) {
                   52556:         PEAR::raiseError('CRITICAL ERROR: no existing valid configuration files found in files ' .
                   52557:             "'$pear_user_config' or '$pear_system_config', please copy an existing configuration" .
                   52558:             'file to one of these locations, or use the -c and -s options to create one');
                   52559:     }
                   52560:     Gtk::main();
                   52561: } else do {
                   52562:     if ($command == 'help') {
                   52563:         usage(null, @$options[1][1]);
                   52564:     }
                   52565: 
                   52566:     if (!$config->validConfiguration()) {
                   52567:         PEAR::raiseError('CRITICAL ERROR: no existing valid configuration files found in files ' .
                   52568:             "'$pear_user_config' or '$pear_system_config', please copy an existing configuration" .
                   52569:             'file to one of these locations, or use the -c and -s options to create one');
                   52570:     }
                   52571: 
                   52572:     PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   52573:     $cmd = PEAR_Command::factory($command, $config);
                   52574:     PEAR::popErrorHandling();
                   52575:     if (PEAR::isError($cmd)) {
                   52576:         usage(null, @$options[1][0]);
                   52577:     }
                   52578: 
                   52579:     $short_args = $long_args = null;
                   52580:     PEAR_Command::getGetoptArgs($command, $short_args, $long_args);
                   52581:     array_shift($options[1]);
                   52582:     $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args);
                   52583: 
                   52584:     if (PEAR::isError($tmp)) {
                   52585:         break;
                   52586:     }
                   52587: 
                   52588:     list($tmpopt, $params) = $tmp;
                   52589:     $opts = array();
                   52590:     foreach ($tmpopt as $foo => $tmp2) {
                   52591:         list($opt, $value) = $tmp2;
                   52592:         if ($value === null) {
                   52593:             $value = true; // options without args
                   52594:         }
                   52595: 
                   52596:         if (strlen($opt) == 1) {
                   52597:             $cmdoptions = $cmd->getOptions($command);
                   52598:             foreach ($cmdoptions as $o => $d) {
                   52599:                 if (isset($d['shortopt']) && $d['shortopt'] == $opt) {
                   52600:                     $opts[$o] = $value;
                   52601:                 }
                   52602:             }
                   52603:         } else {
                   52604:             if (substr($opt, 0, 2) == '--') {
                   52605:                 $opts[substr($opt, 2)] = $value;
                   52606:             }
                   52607:         }
                   52608:     }
                   52609: 
                   52610:     $ok = $cmd->run($command, $opts, $params);
                   52611:     if ($ok === false) {
                   52612:         PEAR::raiseError("unknown command `$command'");
                   52613:     }
                   52614: 
                   52615:     if (PEAR::isError($ok)) {
                   52616:         PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError"));
                   52617:         PEAR::raiseError($ok);
                   52618:     }
                   52619: } while (false);
                   52620: 
                   52621: // {{{ usage()
                   52622: 
                   52623: function usage($error = null, $helpsubject = null)
                   52624: {
                   52625:     global $progname, $all_commands;
                   52626:     $stdout = fopen('php://stdout', 'w');
                   52627:     if (PEAR::isError($error)) {
                   52628:         fputs($stdout, $error->getMessage() . "\n");
                   52629:     } elseif ($error !== null) {
                   52630:         fputs($stdout, "$error\n");
                   52631:     }
                   52632: 
                   52633:     if ($helpsubject != null) {
                   52634:         $put = cmdHelp($helpsubject);
                   52635:     } else {
                   52636:         $put = "Commands:\n";
                   52637:         $maxlen = max(array_map("strlen", $all_commands));
                   52638:         $formatstr = "%-{$maxlen}s  %s\n";
                   52639:         ksort($all_commands);
                   52640:         foreach ($all_commands as $cmd => $class) {
                   52641:             $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd));
                   52642:         }
                   52643:         $put .=
                   52644:             "Usage: $progname [options] command [command-options] <parameters>\n".
                   52645:             "Type \"$progname help options\" to list all options.\n".
                   52646:             "Type \"$progname help shortcuts\" to list all command shortcuts.\n".
                   52647:             "Type \"$progname help <command>\" to get the help for the specified command.";
                   52648:     }
                   52649:     fputs($stdout, "$put\n");
                   52650:     fclose($stdout);
                   52651: 
                   52652:     if ($error === null) {
                   52653:         exit(0);
                   52654:     }
                   52655:     exit(1);
                   52656: }
                   52657: 
                   52658: function cmdHelp($command)
                   52659: {
                   52660:     global $progname, $all_commands, $config;
                   52661:     if ($command == "options") {
                   52662:         return
                   52663:         "Options:\n".
                   52664:         "     -v         increase verbosity level (default 1)\n".
                   52665:         "     -q         be quiet, decrease verbosity level\n".
                   52666:         "     -c file    find user configuration in `file'\n".
                   52667:         "     -C file    find system configuration in `file'\n".
                   52668:         "     -d foo=bar set user config variable `foo' to `bar'\n".
                   52669:         "     -D foo=bar set system config variable `foo' to `bar'\n".
                   52670:         "     -G         start in graphical (Gtk) mode\n".
                   52671:         "     -s         store user configuration\n".
                   52672:         "     -S         store system configuration\n".
                   52673:         "     -u foo     unset `foo' in the user configuration\n".
                   52674:         "     -h, -?     display help/usage (this message)\n".
                   52675:         "     -V         version information\n";
                   52676:     } elseif ($command == "shortcuts") {
                   52677:         $sc = PEAR_Command::getShortcuts();
                   52678:         $ret = "Shortcuts:\n";
                   52679:         foreach ($sc as $s => $c) {
                   52680:             $ret .= sprintf("     %-8s %s\n", $s, $c);
                   52681:         }
                   52682:         return $ret;
                   52683: 
                   52684:     } elseif ($command == "version") {
                   52685:         return "PEAR Version: ".$GLOBALS['pear_package_version'].
                   52686:                "\nPHP Version: ".phpversion().
                   52687:                "\nZend Engine Version: ".zend_version().
                   52688:                "\nRunning on: ".php_uname();
                   52689: 
                   52690:     } elseif ($help = PEAR_Command::getHelp($command)) {
                   52691:         if (is_string($help)) {
                   52692:             return "$progname $command [options] $help\n";
                   52693:         }
                   52694: 
                   52695:         if ($help[1] === null) {
                   52696:             return "$progname $command $help[0]";
                   52697:         }
                   52698: 
                   52699:         return "$progname $command [options] $help[0]\n$help[1]";
                   52700:     }
                   52701: 
                   52702:     return "Command '$command' is not valid, try '$progname help'";
                   52703: }
                   52704: 
                   52705: // }}}
                   52706: 
                   52707: function error_handler($errno, $errmsg, $file, $line, $vars) {
                   52708:     if ((defined('E_STRICT') && $errno & E_STRICT) || (defined('E_DEPRECATED') &&
                   52709:           $errno & E_DEPRECATED) || !error_reporting()) {
                   52710:         if (defined('E_STRICT') && $errno & E_STRICT) {
                   52711:             return; // E_STRICT
                   52712:         }
                   52713:         if (defined('E_DEPRECATED') && $errno & E_DEPRECATED) {
                   52714:             return; // E_DEPRECATED
                   52715:         }
                   52716:         if ($GLOBALS['config']->get('verbose') < 4) {
                   52717:             return false; // @silenced error, show all if debug is high enough
                   52718:         }
                   52719:     }
                   52720:     $errortype = array (
                   52721:         E_ERROR   =>  "Error",
                   52722:         E_WARNING   =>  "Warning",
                   52723:         E_PARSE   =>  "Parsing Error",
                   52724:         E_NOTICE   =>  "Notice",
                   52725:         E_CORE_ERROR  =>  "Core Error",
                   52726:         E_CORE_WARNING  =>  "Core Warning",
                   52727:         E_COMPILE_ERROR  =>  "Compile Error",
                   52728:         E_COMPILE_WARNING =>  "Compile Warning",
                   52729:         E_USER_ERROR =>  "User Error",
                   52730:         E_USER_WARNING =>  "User Warning",
                   52731:         E_USER_NOTICE =>  "User Notice"
                   52732:     );
                   52733:     $prefix = $errortype[$errno];
                   52734:     global $_PEAR_PHPDIR;
                   52735:     if (stristr($file, $_PEAR_PHPDIR)) {
                   52736:         $file = substr($file, strlen($_PEAR_PHPDIR) + 1);
                   52737:     } else {
                   52738:         $file = basename($file);
                   52739:     }
                   52740:     print "\n$prefix: $errmsg in $file on line $line\n";
                   52741:     return false;
                   52742: }
                   52743: 
                   52744: 
                   52745: /*
                   52746:  * Local variables:
                   52747:  * tab-width: 4
                   52748:  * c-basic-offset: 4
                   52749:  * indent-tabs-mode: nil
                   52750:  * mode: php
                   52751:  * End:
                   52752:  */
1.1.1.2 ! misho    52753: // vim600:syn=phpPEAR-1.9.4/scripts/peclcmd.php0000644000076500000240000000163611605156614015051 0ustar  helgistaff<?php
1.1       misho    52754: /**
                   52755:  * PEAR, the PHP Extension and Application Repository
                   52756:  *
                   52757:  * Command line interface
                   52758:  *
                   52759:  * PHP versions 4 and 5
                   52760:  *
                   52761:  * @category   pear
                   52762:  * @package    PEAR
                   52763:  * @author     Stig Bakken <ssb@php.net>
                   52764:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   52765:  * @copyright  1997-2009 The Authors
                   52766:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   52767:  * @version    CVS: $Id: peclcmd.php 313023 2011-07-06 19:17:11Z dufuz $
                   52768:  * @link       http://pear.php.net/package/PEAR
                   52769:  */
                   52770: 
                   52771: /**
                   52772:  * @nodep Gtk
                   52773:  */
                   52774: if ('@include_path@' != '@'.'include_path'.'@') {
                   52775:     ini_set('include_path', '@include_path@');
                   52776:     $raw = false;
                   52777: } else {
                   52778:     // this is a raw, uninstalled pear, either a cvs checkout, or php distro
                   52779:     $raw = true;
                   52780: }
                   52781: define('PEAR_RUNTYPE', 'pecl');
                   52782: require_once 'pearcmd.php';
                   52783: /*
                   52784:  * Local variables:
                   52785:  * tab-width: 4
                   52786:  * c-basic-offset: 4
                   52787:  * indent-tabs-mode: nil
                   52788:  * mode: php
                   52789:  * End:
                   52790:  */
                   52791: // vim600:syn=php
                   52792: 
                   52793: ?>
1.1.1.2 ! misho    52794: PEAR-1.9.4/LICENSE0000644000076500000240000000270511605156614012245 0ustar  helgistaffCopyright (c) 1997-2009,
1.1       misho    52795:  Stig Bakken <ssb@php.net>,
                   52796:  Gregory Beaver <cellog@php.net>,
                   52797:  Helgi Þormar Þorbjörnsson <helgi@php.net>,
                   52798:  Tomas V.V.Cox <cox@idecnet.com>,
                   52799:  Martin Jansen <mj@php.net>.
                   52800: All rights reserved.
                   52801: 
                   52802: Redistribution and use in source and binary forms, with or without
                   52803: modification, are permitted provided that the following conditions are met:
                   52804: 
                   52805:     * Redistributions of source code must retain the above copyright notice,
                   52806:       this list of conditions and the following disclaimer.
                   52807:     * Redistributions in binary form must reproduce the above copyright
                   52808:       notice, this list of conditions and the following disclaimer in the
                   52809:       documentation and/or other materials provided with the distribution.
                   52810: 
                   52811: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
                   52812: AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                   52813: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                   52814: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
                   52815: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                   52816: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                   52817: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
                   52818: CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
                   52819: OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
                   52820: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.1.1.2 ! misho    52821: PEAR-1.9.4/INSTALL0000644000076500000240000000425111605156614012267 0ustar  helgistaffPEAR - The PEAR Installer
1.1       misho    52822: =========================
                   52823: Installing the PEAR Installer.
                   52824: 
                   52825: You should install PEAR on a local development machine first.  Installing
                   52826: PEAR on a remote production machine should only be done after you are
                   52827: familiar with PEAR and have tested code using PEAR on your development
                   52828: machine.
                   52829: 
                   52830: There are two methods of installing PEAR
                   52831:  - PEAR bundled in PHP
                   52832:  - go-pear
                   52833: 
                   52834: We will first examine how to install PEAR that is bundled with PHP.
                   52835: 
                   52836: Microsoft Windows
                   52837: =================
                   52838: If you are running PHP 5.2.0 or newer, simply download and
                   52839: run the windows installer (.msi) and PEAR can be automatically
                   52840: installed.
                   52841: 
                   52842: Otherwise, for older PHP versions, download the .zip of windows,
                   52843: there is a script included with your PHP distribution that is called
                   52844: "go-pear".  You must open a command box in order to run it.  Click
                   52845: "start" then click "Run..." and type "cmd.exe" to open a command box.
                   52846: Use "cd" to change directory to the location of PHP where you unzipped it,
                   52847: and run the go-pear command.
                   52848: 
                   52849: Unix
                   52850: ====
                   52851: When compiling PHP from source, you simply need to include the
                   52852: --with-pear directive on the "./configure" command.  This is "on"
                   52853: by default in most PHP versions, but it doesn't hurt to list it
                   52854: explicitly.  You should also consider enabling the zlib extension via
                   52855: --enable-zlib, so that the PEAR installer will be able to handle gzipped
                   52856: files (i.e. smaller package files for faster downloads).  Later, when you
                   52857: run "make install" to install PHP itself, part of the process will be
                   52858: prompts that ask you where you want PEAR to be installed.
                   52859: 
                   52860: go-pear
                   52861: =======
                   52862: For users who cannot perform the above steps, or who wish to obtain the
                   52863: latest PEAR with a slightly higher risk of failure, use go-pear.  go-pear
                   52864: is obtained by downloading http://pear.php.net/go-pear and saving it as go-pear.php.
                   52865: After downloading, simply run "php go-pear.php" or open it in a web browser
                   52866: (windows only) to download and install PEAR.
                   52867: 
                   52868: You can always ask general installation questions on pear-general@lists.php.net,
                   52869: a public mailing list devoted to support for PEAR packages and installation-
                   52870: related issues.
                   52871: 
                   52872: Happy PHPing, we hope PEAR will be a great tool for your development work!
                   52873: 
1.1.1.2 ! misho    52874: $Id: INSTALL 313023 2011-07-06 19:17:11Z dufuz $PEAR-1.9.4/package.dtd0000644000076500000240000000647711605156614013342 0ustar  helgistaff<!--
1.1       misho    52875:      $Id: package.dtd,v 1.38 2005-11-12 02:23:07 cellog Exp $
                   52876: 
                   52877:      This is the PEAR package description, version 1.0.
                   52878:      It should be used with the informal public identifier:
                   52879: 
                   52880:          "-//PHP Group//DTD PEAR Package 1.0//EN//XML"
                   52881: 
                   52882:      Copyright (c) 1997-2005 The PHP Group             
                   52883: 
                   52884:      This source file is subject to version 3.00 of the PHP license,
                   52885:      that is bundled with this package in the file LICENSE, and is
                   52886:      available at through the world-wide-web at
                   52887:      http://www.php.net/license/3_0.txt. 
                   52888:      If you did not receive a copy of the PHP license and are unable to
                   52889:      obtain it through the world-wide-web, please send a note to
                   52890:      license@php.net so we can mail you a copy immediately.
                   52891: 
                   52892:      Authors:
                   52893:          Stig S. Bakken <ssb@fast.no>
                   52894:          Gregory Beaver <cellog@php.net>
                   52895: 
                   52896:   -->
                   52897: <!ENTITY % NUMBER "CDATA">
                   52898: <!ELEMENT package (name,summary,description,license?,maintainers,release,changelog?)>
                   52899: <!ATTLIST package type    (source|binary|empty) "empty"
                   52900:                   version CDATA                 #REQUIRED
                   52901:                   packagerversion CDATA         #IMPLIED>
                   52902: 
                   52903: <!ELEMENT name (#PCDATA)>
                   52904: 
                   52905: <!ELEMENT summary (#PCDATA)>
                   52906: 
                   52907: <!ELEMENT license (#PCDATA)>
                   52908: 
                   52909: <!ELEMENT description (#PCDATA)>
                   52910: 
                   52911: <!ELEMENT maintainers (maintainer)+>
                   52912: 
                   52913: <!ELEMENT maintainer (user|role|name|email)+>
                   52914: 
                   52915: <!ELEMENT user (#PCDATA)>
                   52916: 
                   52917: <!ELEMENT role (#PCDATA)>
                   52918: 
                   52919: <!ELEMENT email (#PCDATA)>
                   52920: 
                   52921: <!ELEMENT changelog (release)+>
                   52922: 
                   52923: <!ELEMENT release (version,date,license,state,notes,warnings?,provides*,deps?,configureoptions?,filelist?)>
                   52924: 
                   52925: <!ELEMENT version (#PCDATA)>
                   52926: 
                   52927: <!ELEMENT date (#PCDATA)>
                   52928: 
                   52929: <!ELEMENT state (#PCDATA)>
                   52930: 
                   52931: <!ELEMENT notes (#PCDATA)>
                   52932: 
                   52933: <!ELEMENT warnings (#PCDATA)>
                   52934: 
                   52935: <!ELEMENT deps (dep*)>
                   52936: 
                   52937: <!ELEMENT dep (#PCDATA)>
                   52938: <!ATTLIST dep type    (pkg|ext|php) #REQUIRED
                   52939:                               rel     (has|eq|lt|le|gt|ge)                          #IMPLIED
                   52940:                               version CDATA                                     #IMPLIED
                   52941:                               optional (yes|no)     'no'>
                   52942: 
                   52943: <!ELEMENT configureoptions (configureoption)+>
                   52944: 
                   52945: <!ELEMENT configureoption EMPTY>
                   52946: <!ATTLIST configureoption name CDATA #REQUIRED
                   52947:                                            default CDATA #IMPLIED
                   52948:                                            prompt CDATA #REQUIRED>
                   52949: 
                   52950: <!ELEMENT provides EMPTY>
                   52951: <!ATTLIST provides type (ext|prog|class|function|feature|api) #REQUIRED
                   52952:                                 name CDATA #REQUIRED
                   52953:                                 extends CDATA #IMPLIED>
                   52954: <!ELEMENT filelist (dir|file)+>
                   52955: 
                   52956: <!ELEMENT dir (dir|file)+>
                   52957: <!ATTLIST dir name           CDATA #REQUIRED
                   52958:               role           (php|ext|src|test|doc|data|script) 'php'
                   52959:               baseinstalldir CDATA #IMPLIED>
                   52960: 
                   52961: <!ELEMENT file (replace*)>
                   52962: <!ATTLIST file role           (php|ext|src|test|doc|data|script) 'php'
                   52963:                debug          (na|on|off)        'na'
                   52964:                format         CDATA              #IMPLIED
                   52965:                baseinstalldir CDATA              #IMPLIED
                   52966:                platform       CDATA              #IMPLIED
                   52967:                md5sum         CDATA              #IMPLIED
                   52968:                name           CDATA              #REQUIRED
                   52969:                install-as     CDATA              #IMPLIED>
                   52970: 
                   52971: <!ELEMENT replace EMPTY>
                   52972: <!ATTLIST replace type (php-const|pear-config|package-info) #REQUIRED
                   52973:                               from CDATA #REQUIRED
                   52974:                               to CDATA #REQUIRED>
                   52975: 
                   52976: 
1.1.1.2 ! misho    52977: PEAR-1.9.4/PEAR5.php0000644000076500000240000000207711605156614012567 0ustar  helgistaff<?php
1.1       misho    52978: /**
                   52979:  * This is only meant for PHP 5 to get rid of certain strict warning
                   52980:  * that doesn't get hidden since it's in the shutdown function
                   52981:  */
                   52982: class PEAR5
                   52983: {
                   52984:     /**
                   52985:     * If you have a class that's mostly/entirely static, and you need static
                   52986:     * properties, you can use this method to simulate them. Eg. in your method(s)
                   52987:     * do this: $myVar = &PEAR5::getStaticProperty('myclass', 'myVar');
                   52988:     * You MUST use a reference, or they will not persist!
                   52989:     *
                   52990:     * @access public
                   52991:     * @param  string $class  The calling classname, to prevent clashes
                   52992:     * @param  string $var    The variable to retrieve.
                   52993:     * @return mixed   A reference to the variable. If not set it will be
                   52994:     *                 auto initialised to NULL.
                   52995:     */
                   52996:     static function &getStaticProperty($class, $var)
                   52997:     {
                   52998:         static $properties;
                   52999:         if (!isset($properties[$class])) {
                   53000:             $properties[$class] = array();
                   53001:         }
                   53002: 
                   53003:         if (!array_key_exists($var, $properties[$class])) {
                   53004:             $properties[$class][$var] = null;
                   53005:         }
                   53006: 
                   53007:         return $properties[$class][$var];
                   53008:     }
1.1.1.2 ! misho    53009: }PEAR-1.9.4/PEAR.php0000644000076500000240000010215111605156614012474 0ustar  helgistaff<?php
1.1       misho    53010: /**
                   53011:  * PEAR, the PHP Extension and Application Repository
                   53012:  *
                   53013:  * PEAR class and PEAR_Error class
                   53014:  *
                   53015:  * PHP versions 4 and 5
                   53016:  *
                   53017:  * @category   pear
                   53018:  * @package    PEAR
                   53019:  * @author     Sterling Hughes <sterling@php.net>
                   53020:  * @author     Stig Bakken <ssb@php.net>
                   53021:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   53022:  * @author     Greg Beaver <cellog@php.net>
                   53023:  * @copyright  1997-2010 The Authors
                   53024:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   53025:  * @version    CVS: $Id: PEAR.php 313023 2011-07-06 19:17:11Z dufuz $
                   53026:  * @link       http://pear.php.net/package/PEAR
                   53027:  * @since      File available since Release 0.1
                   53028:  */
                   53029: 
                   53030: /**#@+
                   53031:  * ERROR constants
                   53032:  */
                   53033: define('PEAR_ERROR_RETURN',     1);
                   53034: define('PEAR_ERROR_PRINT',      2);
                   53035: define('PEAR_ERROR_TRIGGER',    4);
                   53036: define('PEAR_ERROR_DIE',        8);
                   53037: define('PEAR_ERROR_CALLBACK',  16);
                   53038: /**
                   53039:  * WARNING: obsolete
                   53040:  * @deprecated
                   53041:  */
                   53042: define('PEAR_ERROR_EXCEPTION', 32);
                   53043: /**#@-*/
                   53044: define('PEAR_ZE2', (function_exists('version_compare') &&
                   53045:                     version_compare(zend_version(), "2-dev", "ge")));
                   53046: 
                   53047: if (substr(PHP_OS, 0, 3) == 'WIN') {
                   53048:     define('OS_WINDOWS', true);
                   53049:     define('OS_UNIX',    false);
                   53050:     define('PEAR_OS',    'Windows');
                   53051: } else {
                   53052:     define('OS_WINDOWS', false);
                   53053:     define('OS_UNIX',    true);
                   53054:     define('PEAR_OS',    'Unix'); // blatant assumption
                   53055: }
                   53056: 
                   53057: $GLOBALS['_PEAR_default_error_mode']     = PEAR_ERROR_RETURN;
                   53058: $GLOBALS['_PEAR_default_error_options']  = E_USER_NOTICE;
                   53059: $GLOBALS['_PEAR_destructor_object_list'] = array();
                   53060: $GLOBALS['_PEAR_shutdown_funcs']         = array();
                   53061: $GLOBALS['_PEAR_error_handler_stack']    = array();
                   53062: 
                   53063: @ini_set('track_errors', true);
                   53064: 
                   53065: /**
                   53066:  * Base class for other PEAR classes.  Provides rudimentary
                   53067:  * emulation of destructors.
                   53068:  *
                   53069:  * If you want a destructor in your class, inherit PEAR and make a
                   53070:  * destructor method called _yourclassname (same name as the
                   53071:  * constructor, but with a "_" prefix).  Also, in your constructor you
                   53072:  * have to call the PEAR constructor: $this->PEAR();.
                   53073:  * The destructor method will be called without parameters.  Note that
                   53074:  * at in some SAPI implementations (such as Apache), any output during
                   53075:  * the request shutdown (in which destructors are called) seems to be
                   53076:  * discarded.  If you need to get any debug information from your
                   53077:  * destructor, use error_log(), syslog() or something similar.
                   53078:  *
                   53079:  * IMPORTANT! To use the emulated destructors you need to create the
                   53080:  * objects by reference: $obj =& new PEAR_child;
                   53081:  *
                   53082:  * @category   pear
                   53083:  * @package    PEAR
                   53084:  * @author     Stig Bakken <ssb@php.net>
                   53085:  * @author     Tomas V.V. Cox <cox@idecnet.com>
                   53086:  * @author     Greg Beaver <cellog@php.net>
                   53087:  * @copyright  1997-2006 The PHP Group
                   53088:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   53089:  * @version    Release: 1.9.4
                   53090:  * @link       http://pear.php.net/package/PEAR
                   53091:  * @see        PEAR_Error
                   53092:  * @since      Class available since PHP 4.0.2
                   53093:  * @link        http://pear.php.net/manual/en/core.pear.php#core.pear.pear
                   53094:  */
                   53095: class PEAR
                   53096: {
                   53097:     /**
                   53098:      * Whether to enable internal debug messages.
                   53099:      *
                   53100:      * @var     bool
                   53101:      * @access  private
                   53102:      */
                   53103:     var $_debug = false;
                   53104: 
                   53105:     /**
                   53106:      * Default error mode for this object.
                   53107:      *
                   53108:      * @var     int
                   53109:      * @access  private
                   53110:      */
                   53111:     var $_default_error_mode = null;
                   53112: 
                   53113:     /**
                   53114:      * Default error options used for this object when error mode
                   53115:      * is PEAR_ERROR_TRIGGER.
                   53116:      *
                   53117:      * @var     int
                   53118:      * @access  private
                   53119:      */
                   53120:     var $_default_error_options = null;
                   53121: 
                   53122:     /**
                   53123:      * Default error handler (callback) for this object, if error mode is
                   53124:      * PEAR_ERROR_CALLBACK.
                   53125:      *
                   53126:      * @var     string
                   53127:      * @access  private
                   53128:      */
                   53129:     var $_default_error_handler = '';
                   53130: 
                   53131:     /**
                   53132:      * Which class to use for error objects.
                   53133:      *
                   53134:      * @var     string
                   53135:      * @access  private
                   53136:      */
                   53137:     var $_error_class = 'PEAR_Error';
                   53138: 
                   53139:     /**
                   53140:      * An array of expected errors.
                   53141:      *
                   53142:      * @var     array
                   53143:      * @access  private
                   53144:      */
                   53145:     var $_expected_errors = array();
                   53146: 
                   53147:     /**
                   53148:      * Constructor.  Registers this object in
                   53149:      * $_PEAR_destructor_object_list for destructor emulation if a
                   53150:      * destructor object exists.
                   53151:      *
                   53152:      * @param string $error_class  (optional) which class to use for
                   53153:      *        error objects, defaults to PEAR_Error.
                   53154:      * @access public
                   53155:      * @return void
                   53156:      */
                   53157:     function PEAR($error_class = null)
                   53158:     {
                   53159:         $classname = strtolower(get_class($this));
                   53160:         if ($this->_debug) {
                   53161:             print "PEAR constructor called, class=$classname\n";
                   53162:         }
                   53163: 
                   53164:         if ($error_class !== null) {
                   53165:             $this->_error_class = $error_class;
                   53166:         }
                   53167: 
                   53168:         while ($classname && strcasecmp($classname, "pear")) {
                   53169:             $destructor = "_$classname";
                   53170:             if (method_exists($this, $destructor)) {
                   53171:                 global $_PEAR_destructor_object_list;
                   53172:                 $_PEAR_destructor_object_list[] = &$this;
                   53173:                 if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
                   53174:                     register_shutdown_function("_PEAR_call_destructors");
                   53175:                     $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
                   53176:                 }
                   53177:                 break;
                   53178:             } else {
                   53179:                 $classname = get_parent_class($classname);
                   53180:             }
                   53181:         }
                   53182:     }
                   53183: 
                   53184:     /**
                   53185:      * Destructor (the emulated type of...).  Does nothing right now,
                   53186:      * but is included for forward compatibility, so subclass
                   53187:      * destructors should always call it.
                   53188:      *
                   53189:      * See the note in the class desciption about output from
                   53190:      * destructors.
                   53191:      *
                   53192:      * @access public
                   53193:      * @return void
                   53194:      */
                   53195:     function _PEAR() {
                   53196:         if ($this->_debug) {
                   53197:             printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));
                   53198:         }
                   53199:     }
                   53200: 
                   53201:     /**
                   53202:     * If you have a class that's mostly/entirely static, and you need static
                   53203:     * properties, you can use this method to simulate them. Eg. in your method(s)
                   53204:     * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
                   53205:     * You MUST use a reference, or they will not persist!
                   53206:     *
                   53207:     * @access public
                   53208:     * @param  string $class  The calling classname, to prevent clashes
                   53209:     * @param  string $var    The variable to retrieve.
                   53210:     * @return mixed   A reference to the variable. If not set it will be
                   53211:     *                 auto initialised to NULL.
                   53212:     */
                   53213:     function &getStaticProperty($class, $var)
                   53214:     {
                   53215:         static $properties;
                   53216:         if (!isset($properties[$class])) {
                   53217:             $properties[$class] = array();
                   53218:         }
                   53219: 
                   53220:         if (!array_key_exists($var, $properties[$class])) {
                   53221:             $properties[$class][$var] = null;
                   53222:         }
                   53223: 
                   53224:         return $properties[$class][$var];
                   53225:     }
                   53226: 
                   53227:     /**
                   53228:     * Use this function to register a shutdown method for static
                   53229:     * classes.
                   53230:     *
                   53231:     * @access public
                   53232:     * @param  mixed $func  The function name (or array of class/method) to call
                   53233:     * @param  mixed $args  The arguments to pass to the function
                   53234:     * @return void
                   53235:     */
                   53236:     function registerShutdownFunc($func, $args = array())
                   53237:     {
                   53238:         // if we are called statically, there is a potential
                   53239:         // that no shutdown func is registered.  Bug #6445
                   53240:         if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
                   53241:             register_shutdown_function("_PEAR_call_destructors");
                   53242:             $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
                   53243:         }
                   53244:         $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
                   53245:     }
                   53246: 
                   53247:     /**
                   53248:      * Tell whether a value is a PEAR error.
                   53249:      *
                   53250:      * @param   mixed $data   the value to test
                   53251:      * @param   int   $code   if $data is an error object, return true
                   53252:      *                        only if $code is a string and
                   53253:      *                        $obj->getMessage() == $code or
                   53254:      *                        $code is an integer and $obj->getCode() == $code
                   53255:      * @access  public
                   53256:      * @return  bool    true if parameter is an error
                   53257:      */
                   53258:     function isError($data, $code = null)
                   53259:     {
                   53260:         if (!is_a($data, 'PEAR_Error')) {
                   53261:             return false;
                   53262:         }
                   53263: 
                   53264:         if (is_null($code)) {
                   53265:             return true;
                   53266:         } elseif (is_string($code)) {
                   53267:             return $data->getMessage() == $code;
                   53268:         }
                   53269: 
                   53270:         return $data->getCode() == $code;
                   53271:     }
                   53272: 
                   53273:     /**
                   53274:      * Sets how errors generated by this object should be handled.
                   53275:      * Can be invoked both in objects and statically.  If called
                   53276:      * statically, setErrorHandling sets the default behaviour for all
                   53277:      * PEAR objects.  If called in an object, setErrorHandling sets
                   53278:      * the default behaviour for that object.
                   53279:      *
                   53280:      * @param int $mode
                   53281:      *        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
                   53282:      *        PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
                   53283:      *        PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
                   53284:      *
                   53285:      * @param mixed $options
                   53286:      *        When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
                   53287:      *        of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
                   53288:      *
                   53289:      *        When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
                   53290:      *        to be the callback function or method.  A callback
                   53291:      *        function is a string with the name of the function, a
                   53292:      *        callback method is an array of two elements: the element
                   53293:      *        at index 0 is the object, and the element at index 1 is
                   53294:      *        the name of the method to call in the object.
                   53295:      *
                   53296:      *        When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
                   53297:      *        a printf format string used when printing the error
                   53298:      *        message.
                   53299:      *
                   53300:      * @access public
                   53301:      * @return void
                   53302:      * @see PEAR_ERROR_RETURN
                   53303:      * @see PEAR_ERROR_PRINT
                   53304:      * @see PEAR_ERROR_TRIGGER
                   53305:      * @see PEAR_ERROR_DIE
                   53306:      * @see PEAR_ERROR_CALLBACK
                   53307:      * @see PEAR_ERROR_EXCEPTION
                   53308:      *
                   53309:      * @since PHP 4.0.5
                   53310:      */
                   53311:     function setErrorHandling($mode = null, $options = null)
                   53312:     {
                   53313:         if (isset($this) && is_a($this, 'PEAR')) {
                   53314:             $setmode     = &$this->_default_error_mode;
                   53315:             $setoptions  = &$this->_default_error_options;
                   53316:         } else {
                   53317:             $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
                   53318:             $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
                   53319:         }
                   53320: 
                   53321:         switch ($mode) {
                   53322:             case PEAR_ERROR_EXCEPTION:
                   53323:             case PEAR_ERROR_RETURN:
                   53324:             case PEAR_ERROR_PRINT:
                   53325:             case PEAR_ERROR_TRIGGER:
                   53326:             case PEAR_ERROR_DIE:
                   53327:             case null:
                   53328:                 $setmode = $mode;
                   53329:                 $setoptions = $options;
                   53330:                 break;
                   53331: 
                   53332:             case PEAR_ERROR_CALLBACK:
                   53333:                 $setmode = $mode;
                   53334:                 // class/object method callback
                   53335:                 if (is_callable($options)) {
                   53336:                     $setoptions = $options;
                   53337:                 } else {
                   53338:                     trigger_error("invalid error callback", E_USER_WARNING);
                   53339:                 }
                   53340:                 break;
                   53341: 
                   53342:             default:
                   53343:                 trigger_error("invalid error mode", E_USER_WARNING);
                   53344:                 break;
                   53345:         }
                   53346:     }
                   53347: 
                   53348:     /**
                   53349:      * This method is used to tell which errors you expect to get.
                   53350:      * Expected errors are always returned with error mode
                   53351:      * PEAR_ERROR_RETURN.  Expected error codes are stored in a stack,
                   53352:      * and this method pushes a new element onto it.  The list of
                   53353:      * expected errors are in effect until they are popped off the
                   53354:      * stack with the popExpect() method.
                   53355:      *
                   53356:      * Note that this method can not be called statically
                   53357:      *
                   53358:      * @param mixed $code a single error code or an array of error codes to expect
                   53359:      *
                   53360:      * @return int     the new depth of the "expected errors" stack
                   53361:      * @access public
                   53362:      */
                   53363:     function expectError($code = '*')
                   53364:     {
                   53365:         if (is_array($code)) {
                   53366:             array_push($this->_expected_errors, $code);
                   53367:         } else {
                   53368:             array_push($this->_expected_errors, array($code));
                   53369:         }
                   53370:         return count($this->_expected_errors);
                   53371:     }
                   53372: 
                   53373:     /**
                   53374:      * This method pops one element off the expected error codes
                   53375:      * stack.
                   53376:      *
                   53377:      * @return array   the list of error codes that were popped
                   53378:      */
                   53379:     function popExpect()
                   53380:     {
                   53381:         return array_pop($this->_expected_errors);
                   53382:     }
                   53383: 
                   53384:     /**
                   53385:      * This method checks unsets an error code if available
                   53386:      *
                   53387:      * @param mixed error code
                   53388:      * @return bool true if the error code was unset, false otherwise
                   53389:      * @access private
                   53390:      * @since PHP 4.3.0
                   53391:      */
                   53392:     function _checkDelExpect($error_code)
                   53393:     {
                   53394:         $deleted = false;
                   53395:         foreach ($this->_expected_errors as $key => $error_array) {
                   53396:             if (in_array($error_code, $error_array)) {
                   53397:                 unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
                   53398:                 $deleted = true;
                   53399:             }
                   53400: 
                   53401:             // clean up empty arrays
                   53402:             if (0 == count($this->_expected_errors[$key])) {
                   53403:                 unset($this->_expected_errors[$key]);
                   53404:             }
                   53405:         }
                   53406: 
                   53407:         return $deleted;
                   53408:     }
                   53409: 
                   53410:     /**
                   53411:      * This method deletes all occurences of the specified element from
                   53412:      * the expected error codes stack.
                   53413:      *
                   53414:      * @param  mixed $error_code error code that should be deleted
                   53415:      * @return mixed list of error codes that were deleted or error
                   53416:      * @access public
                   53417:      * @since PHP 4.3.0
                   53418:      */
                   53419:     function delExpect($error_code)
                   53420:     {
                   53421:         $deleted = false;
                   53422:         if ((is_array($error_code) && (0 != count($error_code)))) {
                   53423:             // $error_code is a non-empty array here; we walk through it trying
                   53424:             // to unset all values
                   53425:             foreach ($error_code as $key => $error) {
                   53426:                 $deleted =  $this->_checkDelExpect($error) ? true : false;
                   53427:             }
                   53428: 
                   53429:             return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
                   53430:         } elseif (!empty($error_code)) {
                   53431:             // $error_code comes alone, trying to unset it
                   53432:             if ($this->_checkDelExpect($error_code)) {
                   53433:                 return true;
                   53434:             }
                   53435: 
                   53436:             return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
                   53437:         }
                   53438: 
                   53439:         // $error_code is empty
                   53440:         return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
                   53441:     }
                   53442: 
                   53443:     /**
                   53444:      * This method is a wrapper that returns an instance of the
                   53445:      * configured error class with this object's default error
                   53446:      * handling applied.  If the $mode and $options parameters are not
                   53447:      * specified, the object's defaults are used.
                   53448:      *
                   53449:      * @param mixed $message a text error message or a PEAR error object
                   53450:      *
                   53451:      * @param int $code      a numeric error code (it is up to your class
                   53452:      *                  to define these if you want to use codes)
                   53453:      *
                   53454:      * @param int $mode      One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
                   53455:      *                  PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
                   53456:      *                  PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
                   53457:      *
                   53458:      * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter
                   53459:      *                  specifies the PHP-internal error level (one of
                   53460:      *                  E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
                   53461:      *                  If $mode is PEAR_ERROR_CALLBACK, this
                   53462:      *                  parameter specifies the callback function or
                   53463:      *                  method.  In other error modes this parameter
                   53464:      *                  is ignored.
                   53465:      *
                   53466:      * @param string $userinfo If you need to pass along for example debug
                   53467:      *                  information, this parameter is meant for that.
                   53468:      *
                   53469:      * @param string $error_class The returned error object will be
                   53470:      *                  instantiated from this class, if specified.
                   53471:      *
                   53472:      * @param bool $skipmsg If true, raiseError will only pass error codes,
                   53473:      *                  the error message parameter will be dropped.
                   53474:      *
                   53475:      * @access public
                   53476:      * @return object   a PEAR error object
                   53477:      * @see PEAR::setErrorHandling
                   53478:      * @since PHP 4.0.5
                   53479:      */
                   53480:     function &raiseError($message = null,
                   53481:                          $code = null,
                   53482:                          $mode = null,
                   53483:                          $options = null,
                   53484:                          $userinfo = null,
                   53485:                          $error_class = null,
                   53486:                          $skipmsg = false)
                   53487:     {
                   53488:         // The error is yet a PEAR error object
                   53489:         if (is_object($message)) {
                   53490:             $code        = $message->getCode();
                   53491:             $userinfo    = $message->getUserInfo();
                   53492:             $error_class = $message->getType();
                   53493:             $message->error_message_prefix = '';
                   53494:             $message     = $message->getMessage();
                   53495:         }
                   53496: 
                   53497:         if (
                   53498:             isset($this) &&
                   53499:             isset($this->_expected_errors) &&
                   53500:             count($this->_expected_errors) > 0 &&
                   53501:             count($exp = end($this->_expected_errors))
                   53502:         ) {
                   53503:             if ($exp[0] == "*" ||
                   53504:                 (is_int(reset($exp)) && in_array($code, $exp)) ||
                   53505:                 (is_string(reset($exp)) && in_array($message, $exp))
                   53506:             ) {
                   53507:                 $mode = PEAR_ERROR_RETURN;
                   53508:             }
                   53509:         }
                   53510: 
                   53511:         // No mode given, try global ones
                   53512:         if ($mode === null) {
                   53513:             // Class error handler
                   53514:             if (isset($this) && isset($this->_default_error_mode)) {
                   53515:                 $mode    = $this->_default_error_mode;
                   53516:                 $options = $this->_default_error_options;
                   53517:             // Global error handler
                   53518:             } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
                   53519:                 $mode    = $GLOBALS['_PEAR_default_error_mode'];
                   53520:                 $options = $GLOBALS['_PEAR_default_error_options'];
                   53521:             }
                   53522:         }
                   53523: 
                   53524:         if ($error_class !== null) {
                   53525:             $ec = $error_class;
                   53526:         } elseif (isset($this) && isset($this->_error_class)) {
                   53527:             $ec = $this->_error_class;
                   53528:         } else {
                   53529:             $ec = 'PEAR_Error';
                   53530:         }
                   53531: 
                   53532:         if (intval(PHP_VERSION) < 5) {
                   53533:             // little non-eval hack to fix bug #12147
                   53534:             include 'PEAR/FixPHP5PEARWarnings.php';
                   53535:             return $a;
                   53536:         }
                   53537: 
                   53538:         if ($skipmsg) {
                   53539:             $a = new $ec($code, $mode, $options, $userinfo);
                   53540:         } else {
                   53541:             $a = new $ec($message, $code, $mode, $options, $userinfo);
                   53542:         }
                   53543: 
                   53544:         return $a;
                   53545:     }
                   53546: 
                   53547:     /**
                   53548:      * Simpler form of raiseError with fewer options.  In most cases
                   53549:      * message, code and userinfo are enough.
                   53550:      *
                   53551:      * @param mixed $message a text error message or a PEAR error object
                   53552:      *
                   53553:      * @param int $code      a numeric error code (it is up to your class
                   53554:      *                  to define these if you want to use codes)
                   53555:      *
                   53556:      * @param string $userinfo If you need to pass along for example debug
                   53557:      *                  information, this parameter is meant for that.
                   53558:      *
                   53559:      * @access public
                   53560:      * @return object   a PEAR error object
                   53561:      * @see PEAR::raiseError
                   53562:      */
                   53563:     function &throwError($message = null, $code = null, $userinfo = null)
                   53564:     {
                   53565:         if (isset($this) && is_a($this, 'PEAR')) {
                   53566:             $a = &$this->raiseError($message, $code, null, null, $userinfo);
                   53567:             return $a;
                   53568:         }
                   53569: 
                   53570:         $a = &PEAR::raiseError($message, $code, null, null, $userinfo);
                   53571:         return $a;
                   53572:     }
                   53573: 
                   53574:     function staticPushErrorHandling($mode, $options = null)
                   53575:     {
                   53576:         $stack       = &$GLOBALS['_PEAR_error_handler_stack'];
                   53577:         $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
                   53578:         $def_options = &$GLOBALS['_PEAR_default_error_options'];
                   53579:         $stack[] = array($def_mode, $def_options);
                   53580:         switch ($mode) {
                   53581:             case PEAR_ERROR_EXCEPTION:
                   53582:             case PEAR_ERROR_RETURN:
                   53583:             case PEAR_ERROR_PRINT:
                   53584:             case PEAR_ERROR_TRIGGER:
                   53585:             case PEAR_ERROR_DIE:
                   53586:             case null:
                   53587:                 $def_mode = $mode;
                   53588:                 $def_options = $options;
                   53589:                 break;
                   53590: 
                   53591:             case PEAR_ERROR_CALLBACK:
                   53592:                 $def_mode = $mode;
                   53593:                 // class/object method callback
                   53594:                 if (is_callable($options)) {
                   53595:                     $def_options = $options;
                   53596:                 } else {
                   53597:                     trigger_error("invalid error callback", E_USER_WARNING);
                   53598:                 }
                   53599:                 break;
                   53600: 
                   53601:             default:
                   53602:                 trigger_error("invalid error mode", E_USER_WARNING);
                   53603:                 break;
                   53604:         }
                   53605:         $stack[] = array($mode, $options);
                   53606:         return true;
                   53607:     }
                   53608: 
                   53609:     function staticPopErrorHandling()
                   53610:     {
                   53611:         $stack = &$GLOBALS['_PEAR_error_handler_stack'];
                   53612:         $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
                   53613:         $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
                   53614:         array_pop($stack);
                   53615:         list($mode, $options) = $stack[sizeof($stack) - 1];
                   53616:         array_pop($stack);
                   53617:         switch ($mode) {
                   53618:             case PEAR_ERROR_EXCEPTION:
                   53619:             case PEAR_ERROR_RETURN:
                   53620:             case PEAR_ERROR_PRINT:
                   53621:             case PEAR_ERROR_TRIGGER:
                   53622:             case PEAR_ERROR_DIE:
                   53623:             case null:
                   53624:                 $setmode = $mode;
                   53625:                 $setoptions = $options;
                   53626:                 break;
                   53627: 
                   53628:             case PEAR_ERROR_CALLBACK:
                   53629:                 $setmode = $mode;
                   53630:                 // class/object method callback
                   53631:                 if (is_callable($options)) {
                   53632:                     $setoptions = $options;
                   53633:                 } else {
                   53634:                     trigger_error("invalid error callback", E_USER_WARNING);
                   53635:                 }
                   53636:                 break;
                   53637: 
                   53638:             default:
                   53639:                 trigger_error("invalid error mode", E_USER_WARNING);
                   53640:                 break;
                   53641:         }
                   53642:         return true;
                   53643:     }
                   53644: 
                   53645:     /**
                   53646:      * Push a new error handler on top of the error handler options stack. With this
                   53647:      * you can easily override the actual error handler for some code and restore
                   53648:      * it later with popErrorHandling.
                   53649:      *
                   53650:      * @param mixed $mode (same as setErrorHandling)
                   53651:      * @param mixed $options (same as setErrorHandling)
                   53652:      *
                   53653:      * @return bool Always true
                   53654:      *
                   53655:      * @see PEAR::setErrorHandling
                   53656:      */
                   53657:     function pushErrorHandling($mode, $options = null)
                   53658:     {
                   53659:         $stack = &$GLOBALS['_PEAR_error_handler_stack'];
                   53660:         if (isset($this) && is_a($this, 'PEAR')) {
                   53661:             $def_mode    = &$this->_default_error_mode;
                   53662:             $def_options = &$this->_default_error_options;
                   53663:         } else {
                   53664:             $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
                   53665:             $def_options = &$GLOBALS['_PEAR_default_error_options'];
                   53666:         }
                   53667:         $stack[] = array($def_mode, $def_options);
                   53668: 
                   53669:         if (isset($this) && is_a($this, 'PEAR')) {
                   53670:             $this->setErrorHandling($mode, $options);
                   53671:         } else {
                   53672:             PEAR::setErrorHandling($mode, $options);
                   53673:         }
                   53674:         $stack[] = array($mode, $options);
                   53675:         return true;
                   53676:     }
                   53677: 
                   53678:     /**
                   53679:     * Pop the last error handler used
                   53680:     *
                   53681:     * @return bool Always true
                   53682:     *
                   53683:     * @see PEAR::pushErrorHandling
                   53684:     */
                   53685:     function popErrorHandling()
                   53686:     {
                   53687:         $stack = &$GLOBALS['_PEAR_error_handler_stack'];
                   53688:         array_pop($stack);
                   53689:         list($mode, $options) = $stack[sizeof($stack) - 1];
                   53690:         array_pop($stack);
                   53691:         if (isset($this) && is_a($this, 'PEAR')) {
                   53692:             $this->setErrorHandling($mode, $options);
                   53693:         } else {
                   53694:             PEAR::setErrorHandling($mode, $options);
                   53695:         }
                   53696:         return true;
                   53697:     }
                   53698: 
                   53699:     /**
                   53700:     * OS independant PHP extension load. Remember to take care
                   53701:     * on the correct extension name for case sensitive OSes.
                   53702:     *
                   53703:     * @param string $ext The extension name
                   53704:     * @return bool Success or not on the dl() call
                   53705:     */
                   53706:     function loadExtension($ext)
                   53707:     {
                   53708:         if (extension_loaded($ext)) {
                   53709:             return true;
                   53710:         }
                   53711: 
                   53712:         // if either returns true dl() will produce a FATAL error, stop that
                   53713:         if (
                   53714:             function_exists('dl') === false ||
                   53715:             ini_get('enable_dl') != 1 ||
                   53716:             ini_get('safe_mode') == 1
                   53717:         ) {
                   53718:             return false;
                   53719:         }
                   53720: 
                   53721:         if (OS_WINDOWS) {
                   53722:             $suffix = '.dll';
                   53723:         } elseif (PHP_OS == 'HP-UX') {
                   53724:             $suffix = '.sl';
                   53725:         } elseif (PHP_OS == 'AIX') {
                   53726:             $suffix = '.a';
                   53727:         } elseif (PHP_OS == 'OSX') {
                   53728:             $suffix = '.bundle';
                   53729:         } else {
                   53730:             $suffix = '.so';
                   53731:         }
                   53732: 
                   53733:         return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
                   53734:     }
                   53735: }
                   53736: 
                   53737: if (PEAR_ZE2) {
                   53738:     include_once 'PEAR5.php';
                   53739: }
                   53740: 
                   53741: function _PEAR_call_destructors()
                   53742: {
                   53743:     global $_PEAR_destructor_object_list;
                   53744:     if (is_array($_PEAR_destructor_object_list) &&
                   53745:         sizeof($_PEAR_destructor_object_list))
                   53746:     {
                   53747:         reset($_PEAR_destructor_object_list);
                   53748:         if (PEAR_ZE2) {
                   53749:             $destructLifoExists = PEAR5::getStaticProperty('PEAR', 'destructlifo');
                   53750:         } else {
                   53751:             $destructLifoExists = PEAR::getStaticProperty('PEAR', 'destructlifo');
                   53752:         }
                   53753: 
                   53754:         if ($destructLifoExists) {
                   53755:             $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
                   53756:         }
                   53757: 
                   53758:         while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
                   53759:             $classname = get_class($objref);
                   53760:             while ($classname) {
                   53761:                 $destructor = "_$classname";
                   53762:                 if (method_exists($objref, $destructor)) {
                   53763:                     $objref->$destructor();
                   53764:                     break;
                   53765:                 } else {
                   53766:                     $classname = get_parent_class($classname);
                   53767:                 }
                   53768:             }
                   53769:         }
                   53770:         // Empty the object list to ensure that destructors are
                   53771:         // not called more than once.
                   53772:         $_PEAR_destructor_object_list = array();
                   53773:     }
                   53774: 
                   53775:     // Now call the shutdown functions
                   53776:     if (
                   53777:         isset($GLOBALS['_PEAR_shutdown_funcs']) &&
                   53778:         is_array($GLOBALS['_PEAR_shutdown_funcs']) &&
                   53779:         !empty($GLOBALS['_PEAR_shutdown_funcs'])
                   53780:     ) {
                   53781:         foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
                   53782:             call_user_func_array($value[0], $value[1]);
                   53783:         }
                   53784:     }
                   53785: }
                   53786: 
                   53787: /**
                   53788:  * Standard PEAR error class for PHP 4
                   53789:  *
                   53790:  * This class is supserseded by {@link PEAR_Exception} in PHP 5
                   53791:  *
                   53792:  * @category   pear
                   53793:  * @package    PEAR
                   53794:  * @author     Stig Bakken <ssb@php.net>
                   53795:  * @author     Tomas V.V. Cox <cox@idecnet.com>
                   53796:  * @author     Gregory Beaver <cellog@php.net>
                   53797:  * @copyright  1997-2006 The PHP Group
                   53798:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   53799:  * @version    Release: 1.9.4
                   53800:  * @link       http://pear.php.net/manual/en/core.pear.pear-error.php
                   53801:  * @see        PEAR::raiseError(), PEAR::throwError()
                   53802:  * @since      Class available since PHP 4.0.2
                   53803:  */
                   53804: class PEAR_Error
                   53805: {
                   53806:     var $error_message_prefix = '';
                   53807:     var $mode                 = PEAR_ERROR_RETURN;
                   53808:     var $level                = E_USER_NOTICE;
                   53809:     var $code                 = -1;
                   53810:     var $message              = '';
                   53811:     var $userinfo             = '';
                   53812:     var $backtrace            = null;
                   53813: 
                   53814:     /**
                   53815:      * PEAR_Error constructor
                   53816:      *
                   53817:      * @param string $message  message
                   53818:      *
                   53819:      * @param int $code     (optional) error code
                   53820:      *
                   53821:      * @param int $mode     (optional) error mode, one of: PEAR_ERROR_RETURN,
                   53822:      * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
                   53823:      * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
                   53824:      *
                   53825:      * @param mixed $options   (optional) error level, _OR_ in the case of
                   53826:      * PEAR_ERROR_CALLBACK, the callback function or object/method
                   53827:      * tuple.
                   53828:      *
                   53829:      * @param string $userinfo (optional) additional user/debug info
                   53830:      *
                   53831:      * @access public
                   53832:      *
                   53833:      */
                   53834:     function PEAR_Error($message = 'unknown error', $code = null,
                   53835:                         $mode = null, $options = null, $userinfo = null)
                   53836:     {
                   53837:         if ($mode === null) {
                   53838:             $mode = PEAR_ERROR_RETURN;
                   53839:         }
                   53840:         $this->message   = $message;
                   53841:         $this->code      = $code;
                   53842:         $this->mode      = $mode;
                   53843:         $this->userinfo  = $userinfo;
                   53844: 
                   53845:         if (PEAR_ZE2) {
                   53846:             $skiptrace = PEAR5::getStaticProperty('PEAR_Error', 'skiptrace');
                   53847:         } else {
                   53848:             $skiptrace = PEAR::getStaticProperty('PEAR_Error', 'skiptrace');
                   53849:         }
                   53850: 
                   53851:         if (!$skiptrace) {
                   53852:             $this->backtrace = debug_backtrace();
                   53853:             if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) {
                   53854:                 unset($this->backtrace[0]['object']);
                   53855:             }
                   53856:         }
                   53857: 
                   53858:         if ($mode & PEAR_ERROR_CALLBACK) {
                   53859:             $this->level = E_USER_NOTICE;
                   53860:             $this->callback = $options;
                   53861:         } else {
                   53862:             if ($options === null) {
                   53863:                 $options = E_USER_NOTICE;
                   53864:             }
                   53865: 
                   53866:             $this->level = $options;
                   53867:             $this->callback = null;
                   53868:         }
                   53869: 
                   53870:         if ($this->mode & PEAR_ERROR_PRINT) {
                   53871:             if (is_null($options) || is_int($options)) {
                   53872:                 $format = "%s";
                   53873:             } else {
                   53874:                 $format = $options;
                   53875:             }
                   53876: 
                   53877:             printf($format, $this->getMessage());
                   53878:         }
                   53879: 
                   53880:         if ($this->mode & PEAR_ERROR_TRIGGER) {
                   53881:             trigger_error($this->getMessage(), $this->level);
                   53882:         }
                   53883: 
                   53884:         if ($this->mode & PEAR_ERROR_DIE) {
                   53885:             $msg = $this->getMessage();
                   53886:             if (is_null($options) || is_int($options)) {
                   53887:                 $format = "%s";
                   53888:                 if (substr($msg, -1) != "\n") {
                   53889:                     $msg .= "\n";
                   53890:                 }
                   53891:             } else {
                   53892:                 $format = $options;
                   53893:             }
                   53894:             die(sprintf($format, $msg));
                   53895:         }
                   53896: 
                   53897:         if ($this->mode & PEAR_ERROR_CALLBACK && is_callable($this->callback)) {
                   53898:             call_user_func($this->callback, $this);
                   53899:         }
                   53900: 
                   53901:         if ($this->mode & PEAR_ERROR_EXCEPTION) {
                   53902:             trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING);
                   53903:             eval('$e = new Exception($this->message, $this->code);throw($e);');
                   53904:         }
                   53905:     }
                   53906: 
                   53907:     /**
                   53908:      * Get the error mode from an error object.
                   53909:      *
                   53910:      * @return int error mode
                   53911:      * @access public
                   53912:      */
                   53913:     function getMode()
                   53914:     {
                   53915:         return $this->mode;
                   53916:     }
                   53917: 
                   53918:     /**
                   53919:      * Get the callback function/method from an error object.
                   53920:      *
                   53921:      * @return mixed callback function or object/method array
                   53922:      * @access public
                   53923:      */
                   53924:     function getCallback()
                   53925:     {
                   53926:         return $this->callback;
                   53927:     }
                   53928: 
                   53929:     /**
                   53930:      * Get the error message from an error object.
                   53931:      *
                   53932:      * @return  string  full error message
                   53933:      * @access public
                   53934:      */
                   53935:     function getMessage()
                   53936:     {
                   53937:         return ($this->error_message_prefix . $this->message);
                   53938:     }
                   53939: 
                   53940:     /**
                   53941:      * Get error code from an error object
                   53942:      *
                   53943:      * @return int error code
                   53944:      * @access public
                   53945:      */
                   53946:      function getCode()
                   53947:      {
                   53948:         return $this->code;
                   53949:      }
                   53950: 
                   53951:     /**
                   53952:      * Get the name of this error/exception.
                   53953:      *
                   53954:      * @return string error/exception name (type)
                   53955:      * @access public
                   53956:      */
                   53957:     function getType()
                   53958:     {
                   53959:         return get_class($this);
                   53960:     }
                   53961: 
                   53962:     /**
                   53963:      * Get additional user-supplied information.
                   53964:      *
                   53965:      * @return string user-supplied information
                   53966:      * @access public
                   53967:      */
                   53968:     function getUserInfo()
                   53969:     {
                   53970:         return $this->userinfo;
                   53971:     }
                   53972: 
                   53973:     /**
                   53974:      * Get additional debug information supplied by the application.
                   53975:      *
                   53976:      * @return string debug information
                   53977:      * @access public
                   53978:      */
                   53979:     function getDebugInfo()
                   53980:     {
                   53981:         return $this->getUserInfo();
                   53982:     }
                   53983: 
                   53984:     /**
                   53985:      * Get the call backtrace from where the error was generated.
                   53986:      * Supported with PHP 4.3.0 or newer.
                   53987:      *
                   53988:      * @param int $frame (optional) what frame to fetch
                   53989:      * @return array Backtrace, or NULL if not available.
                   53990:      * @access public
                   53991:      */
                   53992:     function getBacktrace($frame = null)
                   53993:     {
                   53994:         if (defined('PEAR_IGNORE_BACKTRACE')) {
                   53995:             return null;
                   53996:         }
                   53997:         if ($frame === null) {
                   53998:             return $this->backtrace;
                   53999:         }
                   54000:         return $this->backtrace[$frame];
                   54001:     }
                   54002: 
                   54003:     function addUserInfo($info)
                   54004:     {
                   54005:         if (empty($this->userinfo)) {
                   54006:             $this->userinfo = $info;
                   54007:         } else {
                   54008:             $this->userinfo .= " ** $info";
                   54009:         }
                   54010:     }
                   54011: 
                   54012:     function __toString()
                   54013:     {
                   54014:         return $this->getMessage();
                   54015:     }
                   54016: 
                   54017:     /**
                   54018:      * Make a string representation of this object.
                   54019:      *
                   54020:      * @return string a string with an object summary
                   54021:      * @access public
                   54022:      */
                   54023:     function toString()
                   54024:     {
                   54025:         $modes = array();
                   54026:         $levels = array(E_USER_NOTICE  => 'notice',
                   54027:                         E_USER_WARNING => 'warning',
                   54028:                         E_USER_ERROR   => 'error');
                   54029:         if ($this->mode & PEAR_ERROR_CALLBACK) {
                   54030:             if (is_array($this->callback)) {
                   54031:                 $callback = (is_object($this->callback[0]) ?
                   54032:                     strtolower(get_class($this->callback[0])) :
                   54033:                     $this->callback[0]) . '::' .
                   54034:                     $this->callback[1];
                   54035:             } else {
                   54036:                 $callback = $this->callback;
                   54037:             }
                   54038:             return sprintf('[%s: message="%s" code=%d mode=callback '.
                   54039:                            'callback=%s prefix="%s" info="%s"]',
                   54040:                            strtolower(get_class($this)), $this->message, $this->code,
                   54041:                            $callback, $this->error_message_prefix,
                   54042:                            $this->userinfo);
                   54043:         }
                   54044:         if ($this->mode & PEAR_ERROR_PRINT) {
                   54045:             $modes[] = 'print';
                   54046:         }
                   54047:         if ($this->mode & PEAR_ERROR_TRIGGER) {
                   54048:             $modes[] = 'trigger';
                   54049:         }
                   54050:         if ($this->mode & PEAR_ERROR_DIE) {
                   54051:             $modes[] = 'die';
                   54052:         }
                   54053:         if ($this->mode & PEAR_ERROR_RETURN) {
                   54054:             $modes[] = 'return';
                   54055:         }
                   54056:         return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
                   54057:                        'prefix="%s" info="%s"]',
                   54058:                        strtolower(get_class($this)), $this->message, $this->code,
                   54059:                        implode("|", $modes), $levels[$this->level],
                   54060:                        $this->error_message_prefix,
                   54061:                        $this->userinfo);
                   54062:     }
                   54063: }
                   54064: 
                   54065: /*
                   54066:  * Local Variables:
                   54067:  * mode: php
                   54068:  * tab-width: 4
                   54069:  * c-basic-offset: 4
                   54070:  * End:
                   54071:  */
1.1.1.2 ! misho    54072: PEAR-1.9.4/README0000644000076500000240000000224511605156614012117 0ustar  helgistaffPEAR - The PEAR Installer
1.1       misho    54073: =========================
                   54074: 
                   54075: What is the PEAR Installer?  What is PEAR?
                   54076: 
                   54077: PEAR is the PHP Extension and Application Repository, found at
                   54078: http://pear.php.net.  The PEAR Installer is this software, which
                   54079: contains executable files and PHP code that is used to download
                   54080: and install PEAR code from pear.php.net.
                   54081: 
                   54082: PEAR contains useful software libraries and applications such as
                   54083: MDB2 (database abstraction), HTML_QuickForm (HTML forms management),
                   54084: PhpDocumentor (auto-documentation generator), DB_DataObject
                   54085: (Data Access Abstraction), and many hundreds more.  Browse all
                   54086: available packages at http://pear.php.net, the list is constantly
                   54087: growing and updating to reflect improvements in the PHP language.
                   54088: 
                   54089: DOCUMENTATION
                   54090: =============
                   54091: 
                   54092: Documentation for PEAR can be found at http://pear.php.net/manual/.
                   54093: Installation documentation can be found in the INSTALL file included
                   54094: in this tarball.
                   54095: 
                   54096: WARNING: DO NOT RUN PEAR WITHOUT INSTALLING IT - if you downloaded this
                   54097: tarball manually, you MUST install it.  Read the instructions in INSTALL
                   54098: prior to use.
                   54099: 
                   54100: 
                   54101: Happy PHPing, we hope PEAR will be a great tool for your development work!
                   54102: 
1.1.1.2 ! misho    54103: $Id: README 313023 2011-07-06 19:17:11Z dufuz $PEAR-1.9.4/System.php0000644000076500000240000004742311605156614013243 0ustar  helgistaff<?php
1.1       misho    54104: /**
                   54105:  * File/Directory manipulation
                   54106:  *
                   54107:  * PHP versions 4 and 5
                   54108:  *
                   54109:  * @category   pear
                   54110:  * @package    System
                   54111:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   54112:  * @copyright  1997-2009 The Authors
                   54113:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   54114:  * @version    CVS: $Id: System.php 313024 2011-07-06 19:51:24Z dufuz $
                   54115:  * @link       http://pear.php.net/package/PEAR
                   54116:  * @since      File available since Release 0.1
                   54117:  */
                   54118: 
                   54119: /**
                   54120:  * base class
                   54121:  */
                   54122: require_once 'PEAR.php';
                   54123: require_once 'Console/Getopt.php';
                   54124: 
                   54125: $GLOBALS['_System_temp_files'] = array();
                   54126: 
                   54127: /**
                   54128: * System offers cross plattform compatible system functions
                   54129: *
                   54130: * Static functions for different operations. Should work under
                   54131: * Unix and Windows. The names and usage has been taken from its respectively
                   54132: * GNU commands. The functions will return (bool) false on error and will
                   54133: * trigger the error with the PHP trigger_error() function (you can silence
                   54134: * the error by prefixing a '@' sign after the function call, but this
                   54135: * is not recommended practice.  Instead use an error handler with
                   54136: * {@link set_error_handler()}).
                   54137: *
                   54138: * Documentation on this class you can find in:
                   54139: * http://pear.php.net/manual/
                   54140: *
                   54141: * Example usage:
                   54142: * if (!@System::rm('-r file1 dir1')) {
                   54143: *    print "could not delete file1 or dir1";
                   54144: * }
                   54145: *
                   54146: * In case you need to to pass file names with spaces,
                   54147: * pass the params as an array:
                   54148: *
                   54149: * System::rm(array('-r', $file1, $dir1));
                   54150: *
                   54151: * @category   pear
                   54152: * @package    System
                   54153: * @author     Tomas V.V. Cox <cox@idecnet.com>
                   54154: * @copyright  1997-2006 The PHP Group
                   54155: * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   54156: * @version    Release: 1.9.4
                   54157: * @link       http://pear.php.net/package/PEAR
                   54158: * @since      Class available since Release 0.1
                   54159: * @static
                   54160: */
                   54161: class System
                   54162: {
                   54163:     /**
                   54164:      * returns the commandline arguments of a function
                   54165:      *
                   54166:      * @param    string  $argv           the commandline
                   54167:      * @param    string  $short_options  the allowed option short-tags
                   54168:      * @param    string  $long_options   the allowed option long-tags
                   54169:      * @return   array   the given options and there values
                   54170:      * @static
                   54171:      * @access private
                   54172:      */
                   54173:     function _parseArgs($argv, $short_options, $long_options = null)
                   54174:     {
                   54175:         if (!is_array($argv) && $argv !== null) {
                   54176:             // Find all items, quoted or otherwise
                   54177:             preg_match_all("/(?:[\"'])(.*?)(?:['\"])|([^\s]+)/", $argv, $av);
                   54178:             $argv = $av[1];
                   54179:             foreach ($av[2] as $k => $a) {
                   54180:                 if (empty($a)) {
                   54181:                     continue;
                   54182:                 }
                   54183:                 $argv[$k] = trim($a) ;
                   54184:             }
                   54185:         }
                   54186:         return Console_Getopt::getopt2($argv, $short_options, $long_options);
                   54187:     }
                   54188: 
                   54189:     /**
                   54190:      * Output errors with PHP trigger_error(). You can silence the errors
                   54191:      * with prefixing a "@" sign to the function call: @System::mkdir(..);
                   54192:      *
                   54193:      * @param mixed $error a PEAR error or a string with the error message
                   54194:      * @return bool false
                   54195:      * @static
                   54196:      * @access private
                   54197:      */
                   54198:     function raiseError($error)
                   54199:     {
                   54200:         if (PEAR::isError($error)) {
                   54201:             $error = $error->getMessage();
                   54202:         }
                   54203:         trigger_error($error, E_USER_WARNING);
                   54204:         return false;
                   54205:     }
                   54206: 
                   54207:     /**
                   54208:      * Creates a nested array representing the structure of a directory
                   54209:      *
                   54210:      * System::_dirToStruct('dir1', 0) =>
                   54211:      *   Array
                   54212:      *    (
                   54213:      *    [dirs] => Array
                   54214:      *        (
                   54215:      *            [0] => dir1
                   54216:      *        )
                   54217:      *
                   54218:      *    [files] => Array
                   54219:      *        (
                   54220:      *            [0] => dir1/file2
                   54221:      *            [1] => dir1/file3
                   54222:      *        )
                   54223:      *    )
                   54224:      * @param    string  $sPath      Name of the directory
                   54225:      * @param    integer $maxinst    max. deep of the lookup
                   54226:      * @param    integer $aktinst    starting deep of the lookup
                   54227:      * @param    bool    $silent     if true, do not emit errors.
                   54228:      * @return   array   the structure of the dir
                   54229:      * @static
                   54230:      * @access   private
                   54231:      */
                   54232:     function _dirToStruct($sPath, $maxinst, $aktinst = 0, $silent = false)
                   54233:     {
                   54234:         $struct = array('dirs' => array(), 'files' => array());
                   54235:         if (($dir = @opendir($sPath)) === false) {
                   54236:             if (!$silent) {
                   54237:                 System::raiseError("Could not open dir $sPath");
                   54238:             }
                   54239:             return $struct; // XXX could not open error
                   54240:         }
                   54241: 
                   54242:         $struct['dirs'][] = $sPath = realpath($sPath); // XXX don't add if '.' or '..' ?
                   54243:         $list = array();
                   54244:         while (false !== ($file = readdir($dir))) {
                   54245:             if ($file != '.' && $file != '..') {
                   54246:                 $list[] = $file;
                   54247:             }
                   54248:         }
                   54249: 
                   54250:         closedir($dir);
                   54251:         natsort($list);
                   54252:         if ($aktinst < $maxinst || $maxinst == 0) {
                   54253:             foreach ($list as $val) {
                   54254:                 $path = $sPath . DIRECTORY_SEPARATOR . $val;
                   54255:                 if (is_dir($path) && !is_link($path)) {
                   54256:                     $tmp    = System::_dirToStruct($path, $maxinst, $aktinst+1, $silent);
                   54257:                     $struct = array_merge_recursive($struct, $tmp);
                   54258:                 } else {
                   54259:                     $struct['files'][] = $path;
                   54260:                 }
                   54261:             }
                   54262:         }
                   54263: 
                   54264:         return $struct;
                   54265:     }
                   54266: 
                   54267:     /**
                   54268:      * Creates a nested array representing the structure of a directory and files
                   54269:      *
                   54270:      * @param    array $files Array listing files and dirs
                   54271:      * @return   array
                   54272:      * @static
                   54273:      * @see System::_dirToStruct()
                   54274:      */
                   54275:     function _multipleToStruct($files)
                   54276:     {
                   54277:         $struct = array('dirs' => array(), 'files' => array());
                   54278:         settype($files, 'array');
                   54279:         foreach ($files as $file) {
                   54280:             if (is_dir($file) && !is_link($file)) {
                   54281:                 $tmp    = System::_dirToStruct($file, 0);
                   54282:                 $struct = array_merge_recursive($tmp, $struct);
                   54283:             } else {
                   54284:                 if (!in_array($file, $struct['files'])) {
                   54285:                     $struct['files'][] = $file;
                   54286:                 }
                   54287:             }
                   54288:         }
                   54289:         return $struct;
                   54290:     }
                   54291: 
                   54292:     /**
                   54293:      * The rm command for removing files.
                   54294:      * Supports multiple files and dirs and also recursive deletes
                   54295:      *
                   54296:      * @param    string  $args   the arguments for rm
                   54297:      * @return   mixed   PEAR_Error or true for success
                   54298:      * @static
                   54299:      * @access   public
                   54300:      */
                   54301:     function rm($args)
                   54302:     {
                   54303:         $opts = System::_parseArgs($args, 'rf'); // "f" does nothing but I like it :-)
                   54304:         if (PEAR::isError($opts)) {
                   54305:             return System::raiseError($opts);
                   54306:         }
                   54307:         foreach ($opts[0] as $opt) {
                   54308:             if ($opt[0] == 'r') {
                   54309:                 $do_recursive = true;
                   54310:             }
                   54311:         }
                   54312:         $ret = true;
                   54313:         if (isset($do_recursive)) {
                   54314:             $struct = System::_multipleToStruct($opts[1]);
                   54315:             foreach ($struct['files'] as $file) {
                   54316:                 if (!@unlink($file)) {
                   54317:                     $ret = false;
                   54318:                 }
                   54319:             }
                   54320: 
                   54321:             rsort($struct['dirs']);
                   54322:             foreach ($struct['dirs'] as $dir) {
                   54323:                 if (!@rmdir($dir)) {
                   54324:                     $ret = false;
                   54325:                 }
                   54326:             }
                   54327:         } else {
                   54328:             foreach ($opts[1] as $file) {
                   54329:                 $delete = (is_dir($file)) ? 'rmdir' : 'unlink';
                   54330:                 if (!@$delete($file)) {
                   54331:                     $ret = false;
                   54332:                 }
                   54333:             }
                   54334:         }
                   54335:         return $ret;
                   54336:     }
                   54337: 
                   54338:     /**
                   54339:      * Make directories.
                   54340:      *
                   54341:      * The -p option will create parent directories
                   54342:      * @param    string  $args    the name of the director(y|ies) to create
                   54343:      * @return   bool    True for success
                   54344:      * @static
                   54345:      * @access   public
                   54346:      */
                   54347:     function mkDir($args)
                   54348:     {
                   54349:         $opts = System::_parseArgs($args, 'pm:');
                   54350:         if (PEAR::isError($opts)) {
                   54351:             return System::raiseError($opts);
                   54352:         }
                   54353: 
                   54354:         $mode = 0777; // default mode
                   54355:         foreach ($opts[0] as $opt) {
                   54356:             if ($opt[0] == 'p') {
                   54357:                 $create_parents = true;
                   54358:             } elseif ($opt[0] == 'm') {
                   54359:                 // if the mode is clearly an octal number (starts with 0)
                   54360:                 // convert it to decimal
                   54361:                 if (strlen($opt[1]) && $opt[1]{0} == '0') {
                   54362:                     $opt[1] = octdec($opt[1]);
                   54363:                 } else {
                   54364:                     // convert to int
                   54365:                     $opt[1] += 0;
                   54366:                 }
                   54367:                 $mode = $opt[1];
                   54368:             }
                   54369:         }
                   54370: 
                   54371:         $ret = true;
                   54372:         if (isset($create_parents)) {
                   54373:             foreach ($opts[1] as $dir) {
                   54374:                 $dirstack = array();
                   54375:                 while ((!file_exists($dir) || !is_dir($dir)) &&
                   54376:                         $dir != DIRECTORY_SEPARATOR) {
                   54377:                     array_unshift($dirstack, $dir);
                   54378:                     $dir = dirname($dir);
                   54379:                 }
                   54380: 
                   54381:                 while ($newdir = array_shift($dirstack)) {
                   54382:                     if (!is_writeable(dirname($newdir))) {
                   54383:                         $ret = false;
                   54384:                         break;
                   54385:                     }
                   54386: 
                   54387:                     if (!mkdir($newdir, $mode)) {
                   54388:                         $ret = false;
                   54389:                     }
                   54390:                 }
                   54391:             }
                   54392:         } else {
                   54393:             foreach($opts[1] as $dir) {
                   54394:                 if ((@file_exists($dir) || !is_dir($dir)) && !mkdir($dir, $mode)) {
                   54395:                     $ret = false;
                   54396:                 }
                   54397:             }
                   54398:         }
                   54399: 
                   54400:         return $ret;
                   54401:     }
                   54402: 
                   54403:     /**
                   54404:      * Concatenate files
                   54405:      *
                   54406:      * Usage:
                   54407:      * 1) $var = System::cat('sample.txt test.txt');
                   54408:      * 2) System::cat('sample.txt test.txt > final.txt');
                   54409:      * 3) System::cat('sample.txt test.txt >> final.txt');
                   54410:      *
                   54411:      * Note: as the class use fopen, urls should work also (test that)
                   54412:      *
                   54413:      * @param    string  $args   the arguments
                   54414:      * @return   boolean true on success
                   54415:      * @static
                   54416:      * @access   public
                   54417:      */
                   54418:     function &cat($args)
                   54419:     {
                   54420:         $ret = null;
                   54421:         $files = array();
                   54422:         if (!is_array($args)) {
                   54423:             $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY);
                   54424:         }
                   54425: 
                   54426:         $count_args = count($args);
                   54427:         for ($i = 0; $i < $count_args; $i++) {
                   54428:             if ($args[$i] == '>') {
                   54429:                 $mode = 'wb';
                   54430:                 $outputfile = $args[$i+1];
                   54431:                 break;
                   54432:             } elseif ($args[$i] == '>>') {
                   54433:                 $mode = 'ab+';
                   54434:                 $outputfile = $args[$i+1];
                   54435:                 break;
                   54436:             } else {
                   54437:                 $files[] = $args[$i];
                   54438:             }
                   54439:         }
                   54440:         $outputfd = false;
                   54441:         if (isset($mode)) {
                   54442:             if (!$outputfd = fopen($outputfile, $mode)) {
                   54443:                 $err = System::raiseError("Could not open $outputfile");
                   54444:                 return $err;
                   54445:             }
                   54446:             $ret = true;
                   54447:         }
                   54448:         foreach ($files as $file) {
                   54449:             if (!$fd = fopen($file, 'r')) {
                   54450:                 System::raiseError("Could not open $file");
                   54451:                 continue;
                   54452:             }
                   54453:             while ($cont = fread($fd, 2048)) {
                   54454:                 if (is_resource($outputfd)) {
                   54455:                     fwrite($outputfd, $cont);
                   54456:                 } else {
                   54457:                     $ret .= $cont;
                   54458:                 }
                   54459:             }
                   54460:             fclose($fd);
                   54461:         }
                   54462:         if (is_resource($outputfd)) {
                   54463:             fclose($outputfd);
                   54464:         }
                   54465:         return $ret;
                   54466:     }
                   54467: 
                   54468:     /**
                   54469:      * Creates temporary files or directories. This function will remove
                   54470:      * the created files when the scripts finish its execution.
                   54471:      *
                   54472:      * Usage:
                   54473:      *   1) $tempfile = System::mktemp("prefix");
                   54474:      *   2) $tempdir  = System::mktemp("-d prefix");
                   54475:      *   3) $tempfile = System::mktemp();
                   54476:      *   4) $tempfile = System::mktemp("-t /var/tmp prefix");
                   54477:      *
                   54478:      * prefix -> The string that will be prepended to the temp name
                   54479:      *           (defaults to "tmp").
                   54480:      * -d     -> A temporary dir will be created instead of a file.
                   54481:      * -t     -> The target dir where the temporary (file|dir) will be created. If
                   54482:      *           this param is missing by default the env vars TMP on Windows or
                   54483:      *           TMPDIR in Unix will be used. If these vars are also missing
                   54484:      *           c:\windows\temp or /tmp will be used.
                   54485:      *
                   54486:      * @param   string  $args  The arguments
                   54487:      * @return  mixed   the full path of the created (file|dir) or false
                   54488:      * @see System::tmpdir()
                   54489:      * @static
                   54490:      * @access  public
                   54491:      */
                   54492:     function mktemp($args = null)
                   54493:     {
                   54494:         static $first_time = true;
                   54495:         $opts = System::_parseArgs($args, 't:d');
                   54496:         if (PEAR::isError($opts)) {
                   54497:             return System::raiseError($opts);
                   54498:         }
                   54499: 
                   54500:         foreach ($opts[0] as $opt) {
                   54501:             if ($opt[0] == 'd') {
                   54502:                 $tmp_is_dir = true;
                   54503:             } elseif ($opt[0] == 't') {
                   54504:                 $tmpdir = $opt[1];
                   54505:             }
                   54506:         }
                   54507: 
                   54508:         $prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp';
                   54509:         if (!isset($tmpdir)) {
                   54510:             $tmpdir = System::tmpdir();
                   54511:         }
                   54512: 
                   54513:         if (!System::mkDir(array('-p', $tmpdir))) {
                   54514:             return false;
                   54515:         }
                   54516: 
                   54517:         $tmp = tempnam($tmpdir, $prefix);
                   54518:         if (isset($tmp_is_dir)) {
                   54519:             unlink($tmp); // be careful possible race condition here
                   54520:             if (!mkdir($tmp, 0700)) {
                   54521:                 return System::raiseError("Unable to create temporary directory $tmpdir");
                   54522:             }
                   54523:         }
                   54524: 
                   54525:         $GLOBALS['_System_temp_files'][] = $tmp;
                   54526:         if (isset($tmp_is_dir)) {
                   54527:             //$GLOBALS['_System_temp_files'][] = dirname($tmp);
                   54528:         }
                   54529: 
                   54530:         if ($first_time) {
                   54531:             PEAR::registerShutdownFunc(array('System', '_removeTmpFiles'));
                   54532:             $first_time = false;
                   54533:         }
                   54534: 
                   54535:         return $tmp;
                   54536:     }
                   54537: 
                   54538:     /**
                   54539:      * Remove temporary files created my mkTemp. This function is executed
                   54540:      * at script shutdown time
                   54541:      *
                   54542:      * @static
                   54543:      * @access private
                   54544:      */
                   54545:     function _removeTmpFiles()
                   54546:     {
                   54547:         if (count($GLOBALS['_System_temp_files'])) {
                   54548:             $delete = $GLOBALS['_System_temp_files'];
                   54549:             array_unshift($delete, '-r');
                   54550:             System::rm($delete);
                   54551:             $GLOBALS['_System_temp_files'] = array();
                   54552:         }
                   54553:     }
                   54554: 
                   54555:     /**
                   54556:      * Get the path of the temporal directory set in the system
                   54557:      * by looking in its environments variables.
                   54558:      * Note: php.ini-recommended removes the "E" from the variables_order setting,
                   54559:      * making unavaible the $_ENV array, that s why we do tests with _ENV
                   54560:      *
                   54561:      * @static
                   54562:      * @return string The temporary directory on the system
                   54563:      */
                   54564:     function tmpdir()
                   54565:     {
                   54566:         if (OS_WINDOWS) {
                   54567:             if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) {
                   54568:                 return $var;
                   54569:             }
                   54570:             if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) {
                   54571:                 return $var;
                   54572:             }
                   54573:             if ($var = isset($_ENV['USERPROFILE']) ? $_ENV['USERPROFILE'] : getenv('USERPROFILE')) {
                   54574:                 return $var;
                   54575:             }
                   54576:             if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) {
                   54577:                 return $var;
                   54578:             }
                   54579:             return getenv('SystemRoot') . '\temp';
                   54580:         }
                   54581:         if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) {
                   54582:             return $var;
                   54583:         }
                   54584:         return realpath('/tmp');
                   54585:     }
                   54586: 
                   54587:     /**
                   54588:      * The "which" command (show the full path of a command)
                   54589:      *
                   54590:      * @param string $program The command to search for
                   54591:      * @param mixed  $fallback Value to return if $program is not found
                   54592:      *
                   54593:      * @return mixed A string with the full path or false if not found
                   54594:      * @static
                   54595:      * @author Stig Bakken <ssb@php.net>
                   54596:      */
                   54597:     function which($program, $fallback = false)
                   54598:     {
                   54599:         // enforce API
                   54600:         if (!is_string($program) || '' == $program) {
                   54601:             return $fallback;
                   54602:         }
                   54603: 
                   54604:         // full path given
                   54605:         if (basename($program) != $program) {
                   54606:             $path_elements[] = dirname($program);
                   54607:             $program = basename($program);
                   54608:         } else {
                   54609:             // Honor safe mode
                   54610:             if (!ini_get('safe_mode') || !$path = ini_get('safe_mode_exec_dir')) {
                   54611:                 $path = getenv('PATH');
                   54612:                 if (!$path) {
                   54613:                     $path = getenv('Path'); // some OSes are just stupid enough to do this
                   54614:                 }
                   54615:             }
                   54616:             $path_elements = explode(PATH_SEPARATOR, $path);
                   54617:         }
                   54618: 
                   54619:         if (OS_WINDOWS) {
                   54620:             $exe_suffixes = getenv('PATHEXT')
                   54621:                                 ? explode(PATH_SEPARATOR, getenv('PATHEXT'))
                   54622:                                 : array('.exe','.bat','.cmd','.com');
                   54623:             // allow passing a command.exe param
                   54624:             if (strpos($program, '.') !== false) {
                   54625:                 array_unshift($exe_suffixes, '');
                   54626:             }
                   54627:             // is_executable() is not available on windows for PHP4
                   54628:             $pear_is_executable = (function_exists('is_executable')) ? 'is_executable' : 'is_file';
                   54629:         } else {
                   54630:             $exe_suffixes = array('');
                   54631:             $pear_is_executable = 'is_executable';
                   54632:         }
                   54633: 
                   54634:         foreach ($exe_suffixes as $suff) {
                   54635:             foreach ($path_elements as $dir) {
                   54636:                 $file = $dir . DIRECTORY_SEPARATOR . $program . $suff;
                   54637:                 if (@$pear_is_executable($file)) {
                   54638:                     return $file;
                   54639:                 }
                   54640:             }
                   54641:         }
                   54642:         return $fallback;
                   54643:     }
                   54644: 
                   54645:     /**
                   54646:      * The "find" command
                   54647:      *
                   54648:      * Usage:
                   54649:      *
                   54650:      * System::find($dir);
                   54651:      * System::find("$dir -type d");
                   54652:      * System::find("$dir -type f");
                   54653:      * System::find("$dir -name *.php");
                   54654:      * System::find("$dir -name *.php -name *.htm*");
                   54655:      * System::find("$dir -maxdepth 1");
                   54656:      *
                   54657:      * Params implmented:
                   54658:      * $dir            -> Start the search at this directory
                   54659:      * -type d         -> return only directories
                   54660:      * -type f         -> return only files
                   54661:      * -maxdepth <n>   -> max depth of recursion
                   54662:      * -name <pattern> -> search pattern (bash style). Multiple -name param allowed
                   54663:      *
                   54664:      * @param  mixed Either array or string with the command line
                   54665:      * @return array Array of found files
                   54666:      * @static
                   54667:      *
                   54668:      */
                   54669:     function find($args)
                   54670:     {
                   54671:         if (!is_array($args)) {
                   54672:             $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY);
                   54673:         }
                   54674:         $dir = realpath(array_shift($args));
                   54675:         if (!$dir) {
                   54676:             return array();
                   54677:         }
                   54678:         $patterns = array();
                   54679:         $depth = 0;
                   54680:         $do_files = $do_dirs = true;
                   54681:         $args_count = count($args);
                   54682:         for ($i = 0; $i < $args_count; $i++) {
                   54683:             switch ($args[$i]) {
                   54684:                 case '-type':
                   54685:                     if (in_array($args[$i+1], array('d', 'f'))) {
                   54686:                         if ($args[$i+1] == 'd') {
                   54687:                             $do_files = false;
                   54688:                         } else {
                   54689:                             $do_dirs = false;
                   54690:                         }
                   54691:                     }
                   54692:                     $i++;
                   54693:                     break;
                   54694:                 case '-name':
                   54695:                     $name = preg_quote($args[$i+1], '#');
                   54696:                     // our magic characters ? and * have just been escaped,
                   54697:                     // so now we change the escaped versions to PCRE operators
                   54698:                     $name = strtr($name, array('\?' => '.', '\*' => '.*'));
                   54699:                     $patterns[] = '('.$name.')';
                   54700:                     $i++;
                   54701:                     break;
                   54702:                 case '-maxdepth':
                   54703:                     $depth = $args[$i+1];
                   54704:                     break;
                   54705:             }
                   54706:         }
                   54707:         $path = System::_dirToStruct($dir, $depth, 0, true);
                   54708:         if ($do_files && $do_dirs) {
                   54709:             $files = array_merge($path['files'], $path['dirs']);
                   54710:         } elseif ($do_dirs) {
                   54711:             $files = $path['dirs'];
                   54712:         } else {
                   54713:             $files = $path['files'];
                   54714:         }
                   54715:         if (count($patterns)) {
                   54716:             $dsq = preg_quote(DIRECTORY_SEPARATOR, '#');
                   54717:             $pattern = '#(^|'.$dsq.')'.implode('|', $patterns).'($|'.$dsq.')#';
                   54718:             $ret = array();
                   54719:             $files_count = count($files);
                   54720:             for ($i = 0; $i < $files_count; $i++) {
                   54721:                 // only search in the part of the file below the current directory
                   54722:                 $filepart = basename($files[$i]);
                   54723:                 if (preg_match($pattern, $filepart)) {
                   54724:                     $ret[] = $files[$i];
                   54725:                 }
                   54726:             }
                   54727:             return $ret;
                   54728:         }
                   54729:         return $files;
                   54730:     }
1.1.1.2 ! misho    54731: }PEAR-1.9.4/template.spec0000644000076500000240000000372511605156614013732 0ustar  helgistaffSummary: PEAR: @summary@
1.1       misho    54732: Name: @rpm_package@
                   54733: Version: @version@
                   54734: Release: 1
                   54735: License: @release_license@
                   54736: Group: Development/Libraries
                   54737: Source: http://@master_server@/get/@package@-%{version}.tgz
                   54738: BuildRoot: %{_tmppath}/%{name}-root
                   54739: URL: http://@master_server@/package/@package@
                   54740: Prefix: %{_prefix}
                   54741: BuildArchitectures: @arch@
                   54742: @extra_headers@
                   54743: 
                   54744: %description
                   54745: @description@
                   54746: 
                   54747: %prep
                   54748: rm -rf %{buildroot}/*
                   54749: %setup -c -T
                   54750: # XXX Source files location is missing here in pear cmd
                   54751: pear -v -c %{buildroot}/pearrc \
                   54752:         -d php_dir=%{_libdir}/php/pear \
                   54753:         -d doc_dir=/docs \
                   54754:         -d bin_dir=%{_bindir} \
                   54755:         -d data_dir=%{_libdir}/php/pear/data \
                   54756:         -d test_dir=%{_libdir}/php/pear/tests \
                   54757:         -d ext_dir=%{_libdir} \@extra_config@
                   54758:         -s
                   54759: 
                   54760: %build
                   54761: echo BuildRoot=%{buildroot}
                   54762: 
                   54763: %postun
                   54764: # if refcount = 0 then package has been removed (not upgraded)
                   54765: if [ "$1" -eq "0" ]; then
                   54766:     pear uninstall --nodeps -r @possible_channel@@package@
                   54767:     rm @rpm_xml_dir@/@package@.xml
                   54768: fi
                   54769: 
                   54770: 
                   54771: %post
                   54772: # if refcount = 2 then package has been upgraded
                   54773: if [ "$1" -ge "2" ]; then
                   54774:     pear upgrade --nodeps -r @rpm_xml_dir@/@package@.xml
                   54775: else
                   54776:     pear install --nodeps -r @rpm_xml_dir@/@package@.xml
                   54777: fi
                   54778: 
                   54779: %install
                   54780: pear -c %{buildroot}/pearrc install --nodeps -R %{buildroot} \
                   54781:         $RPM_SOURCE_DIR/@package@-%{version}.tgz
                   54782: rm %{buildroot}/pearrc
                   54783: rm %{buildroot}/%{_libdir}/php/pear/.filemap
                   54784: rm %{buildroot}/%{_libdir}/php/pear/.lock
                   54785: rm -rf %{buildroot}/%{_libdir}/php/pear/.registry
                   54786: if [ "@doc_files@" != "" ]; then
                   54787:      mv %{buildroot}/docs/@package@/* .
                   54788:      rm -rf %{buildroot}/docs
                   54789: fi
                   54790: mkdir -p %{buildroot}@rpm_xml_dir@
                   54791: tar -xzf $RPM_SOURCE_DIR/@package@-%{version}.tgz package@package2xml@.xml
                   54792: cp -p package@package2xml@.xml %{buildroot}@rpm_xml_dir@/@package@.xml
                   54793: 
                   54794: #rm -rf %{buildroot}/*
                   54795: #pear -q install -R %{buildroot} -n package@package2xml@.xml
                   54796: #mkdir -p %{buildroot}@rpm_xml_dir@
                   54797: #cp -p package@package2xml@.xml %{buildroot}@rpm_xml_dir@/@package@.xml
                   54798: 
                   54799: %files
                   54800:     %defattr(-,root,root)
                   54801:     %doc @doc_files@
                   54802:     /
1.1.1.2 ! misho    54803: package.xml0000644000076500000240000010644711605156615012170 0ustar  helgistaff<?xml version="1.0" encoding="UTF-8" ?>
1.1       misho    54804: <!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0">
                   54805: <package version="1.0" packagerversion="1.9.4">
                   54806:  <name>PEAR</name>
                   54807:  <summary>PEAR Base System</summary>
                   54808:  <description>The PEAR package contains:
                   54809:  * the PEAR installer, for creating, distributing
                   54810:    and installing packages
                   54811:  * the PEAR_Exception PHP5 error handling mechanism
                   54812:  * the PEAR_ErrorStack advanced error handling mechanism
                   54813:  * the PEAR_Error error handling mechanism
                   54814:  * the OS_Guess class for retrieving info about the OS
                   54815:    where PHP is running on
                   54816:  * the System class for quick handling of common operations
                   54817:    with files and directories
                   54818:  * the PEAR base class
                   54819: 
                   54820:   Features in a nutshell:
                   54821:   * full support for channels
                   54822:   * pre-download dependency validation
                   54823:   * new package.xml 2.0 format allows tremendous flexibility while maintaining BC
                   54824:   * support for optional dependency groups and limited support for sub-packaging
                   54825:   * robust dependency support
                   54826:   * full dependency validation on uninstall
                   54827:   * remote install for hosts with only ftp access - no more problems with
                   54828:     restricted host installation
                   54829:   * full support for mirroring
                   54830:   * support for bundling several packages into a single tarball
                   54831:   * support for static dependencies on a url-based package
                   54832:   * support for custom file roles and installation tasks
                   54833:  </description>
                   54834:  <maintainers>
                   54835:   <maintainer>
                   54836:    <user>cellog</user>
                   54837:    <name>Greg Beaver</name>
                   54838:    <email>cellog@php.net</email>
                   54839:    <role>lead</role>
                   54840:   </maintainer>
                   54841:   <maintainer>
                   54842:    <user>pajoye</user>
                   54843:    <name>Pierre-Alain Joye</name>
                   54844:    <email>pierre@php.net</email>
                   54845:    <role>lead</role>
                   54846:   </maintainer>
                   54847:   <maintainer>
                   54848:    <user>ssb</user>
                   54849:    <name>Stig Bakken</name>
                   54850:    <email>stig@php.net</email>
                   54851:    <role>lead</role>
                   54852:   </maintainer>
                   54853:   <maintainer>
                   54854:    <user>cox</user>
                   54855:    <name>Tomas V.V.Cox</name>
                   54856:    <email>cox@idecnet.com</email>
                   54857:    <role>lead</role>
                   54858:   </maintainer>
                   54859:   <maintainer>
                   54860:    <user>dufuz</user>
                   54861:    <name>Helgi Thormar</name>
                   54862:    <email>dufuz@php.net</email>
                   54863:    <role>lead</role>
                   54864:   </maintainer>
                   54865:   <maintainer>
                   54866:    <user>tias</user>
                   54867:    <name>Tias Guns</name>
                   54868:    <email>tias@php.net</email>
                   54869:    <role>developer</role>
                   54870:   </maintainer>
                   54871:   <maintainer>
                   54872:    <user>timj</user>
                   54873:    <name>Tim Jackson</name>
                   54874:    <email>timj@php.net</email>
                   54875:    <role>helper</role>
                   54876:   </maintainer>
                   54877:   <maintainer>
                   54878:    <user>toggg</user>
                   54879:    <name>Bertrand Gugger</name>
                   54880:    <email>toggg@php.net</email>
                   54881:    <role>helper</role>
                   54882:   </maintainer>
                   54883:   <maintainer>
                   54884:    <user>mj</user>
                   54885:    <name>Martin Jansen</name>
                   54886:    <email>mj@php.net</email>
                   54887:    <role>helper</role>
                   54888:   </maintainer>
                   54889:   </maintainers>
                   54890:  <release>
                   54891:   <version>1.9.4</version>
                   54892:   <date>2011-07-06</date>
                   54893:   <license>New BSD License</license>
                   54894:   <state>stable</state>
                   54895:   <notes>Bug Fixes:
                   54896: * Bug #17350: &quot;pear install --force&quot; doesn&apos;t uninstall files from previous pkg versions [dufuz]
                   54897: * Bug #18362: A whitespace TEMP_DIR path breaks install/upgrade functionality [dufuz]
                   54898: * Bug #18440: bad tmp folder path on install : Unable to create path for C:/Program/tmp [dufuz]
                   54899: * Bug #18581: &quot;config-get -c&quot; not returning channel&apos;s configuration when using alias [dufuz]
                   54900: * Bug #18639: regression: installing xdebug fails most likely due to another fix [dufuz]
                   54901: Features
                   54902: * All System (the class) functions can now take in spaced paths as long as they are surrounded in quotes.
                   54903:   Prior to this it was possible to do that by passing all values in as an array (by product of #18362, #18440) [dufuz]
                   54904:   </notes>
                   54905:   <deps>
                   54906:    <dep type="php" rel="ge" version="4.4.0"/>
                   54907:    <dep type="pkg" rel="ge" version="1.3.3">PEAR</dep>
                   54908:    <dep type="pkg" rel="ge" version="1.3.7">Archive_Tar</dep>
                   54909:    <dep type="pkg" rel="ge" version="1.2">Console_Getopt</dep>
                   54910:    <dep type="pkg" rel="ge" version="1.0.2">Structures_Graph</dep>
                   54911:    <dep type="pkg" rel="ge" version="0.5.0" optional="yes">PEAR_Frontend_Web</dep>
                   54912:    <dep type="pkg" rel="ge" version="0.4.0" optional="yes">PEAR_Frontend_Gtk</dep>
                   54913:    <dep type="ext" rel="has">xml</dep>
                   54914:    <dep type="ext" rel="has">pcre</dep>
                   54915:   </deps>
                   54916:   <provides type="class" name="OS_Guess" />
                   54917:   <provides type="class" name="System" />
                   54918:   <filelist>
                   54919:    <file role="php" name="OS/Guess.php">
                   54920:     <replace from="@package_version@" to="version" type="package-info"/>
                   54921:    </file>
                   54922:    <file role="php" name="PEAR/ChannelFile/Parser.php">
                   54923:     <replace from="@package_version@" to="version" type="package-info"/>
                   54924:    </file>
                   54925:    <file role="php" name="PEAR/Command/Auth.xml"/>
                   54926:    <file role="php" name="PEAR/Command/Auth.php">
                   54927:     <replace from="@package_version@" to="version" type="package-info"/>
                   54928:    </file>
                   54929:    <file role="php" name="PEAR/Command/Build.xml"/>
                   54930:    <file role="php" name="PEAR/Command/Build.php">
                   54931:     <replace from="@package_version@" to="version" type="package-info"/>
                   54932:    </file>
                   54933:    <file role="php" name="PEAR/Command/Channels.xml"/>
                   54934:    <file role="php" name="PEAR/Command/Channels.php">
                   54935:     <replace from="@package_version@" to="version" type="package-info"/>
                   54936:    </file>
                   54937:    <file role="php" name="PEAR/Command/Common.php">
                   54938:     <replace from="@package_version@" to="version" type="package-info"/>
                   54939:    </file>
                   54940:    <file role="php" name="PEAR/Command/Config.xml"/>
                   54941:    <file role="php" name="PEAR/Command/Config.php">
                   54942:     <replace from="@package_version@" to="version" type="package-info"/>
                   54943:    </file>
                   54944:    <file role="php" name="PEAR/Command/Install.xml"/>
                   54945:    <file role="php" name="PEAR/Command/Install.php">
                   54946:     <replace from="@package_version@" to="version" type="package-info"/>
                   54947:    </file>
                   54948:    <file role="php" name="PEAR/Command/Package.xml"/>
                   54949:    <file role="php" name="PEAR/Command/Package.php">
                   54950:     <replace from="@DATA-DIR@" to="data_dir" type="pear-config"/>
                   54951:     <replace from="@package_version@" to="version" type="package-info"/>
                   54952:    </file>
                   54953:    <file role="php" name="PEAR/Command/Pickle.xml"/>
                   54954:    <file role="php" name="PEAR/Command/Pickle.php">
                   54955:     <replace from="@package_version@" to="version" type="package-info"/>
                   54956:    </file>
                   54957:    <file role="php" name="PEAR/Command/Registry.xml"/>
                   54958:    <file role="php" name="PEAR/Command/Registry.php">
                   54959:     <replace from="@package_version@" to="version" type="package-info"/>
                   54960:    </file>
                   54961:    <file role="php" name="PEAR/Command/Remote.xml"/>
                   54962:    <file role="php" name="PEAR/Command/Remote.php">
                   54963:     <replace from="@package_version@" to="version" type="package-info"/>
                   54964:    </file>
                   54965:    <file role="php" name="PEAR/Command/Mirror.xml"/>
                   54966:    <file role="php" name="PEAR/Command/Mirror.php">
                   54967:     <replace from="@package_version@" to="version" type="package-info"/>
                   54968:    </file>
                   54969:    <file role="php" name="PEAR/Command/Test.xml"/>
                   54970:    <file role="php" name="PEAR/Command/Test.php">
                   54971:     <replace from="@package_version@" to="version" type="package-info"/>
                   54972:    </file>
                   54973:    <file role="php" name="PEAR/Downloader/Package.php">
                   54974:     <replace from="@PEAR-VER@" to="version" type="package-info"/>
                   54975:    </file>
                   54976:    <file role="php" name="PEAR/Frontend/CLI.php">
                   54977:     <replace from="@package_version@" to="version" type="package-info"/>
                   54978:    </file>
                   54979:    <file role="php" name="PEAR/Installer/Role/Common.php">
                   54980:     <replace from="@package_version@" to="version" type="package-info"/>
                   54981:    </file>
                   54982:    <file role="php" name="PEAR/Installer/Role/Cfg.xml"/>
                   54983:    <file role="php" name="PEAR/Installer/Role/Cfg.php">
                   54984:     <replace from="@package_version@" to="version" type="package-info"/>
                   54985:    </file>
                   54986:    <file role="php" name="PEAR/Installer/Role/Data.xml"/>
                   54987:    <file role="php" name="PEAR/Installer/Role/Data.php">
                   54988:     <replace from="@package_version@" to="version" type="package-info"/>
                   54989:    </file>
                   54990:    <file role="php" name="PEAR/Installer/Role/Doc.xml"/>
                   54991:    <file role="php" name="PEAR/Installer/Role/Doc.php">
                   54992:     <replace from="@package_version@" to="version" type="package-info"/>
                   54993:    </file>
                   54994:    <file role="php" name="PEAR/Installer/Role/Ext.xml"/>
                   54995:    <file role="php" name="PEAR/Installer/Role/Ext.php">
                   54996:     <replace from="@package_version@" to="version" type="package-info"/>
                   54997:    </file>
                   54998:    <file role="php" name="PEAR/Installer/Role/Php.xml"/>
                   54999:    <file role="php" name="PEAR/Installer/Role/Php.php">
                   55000:     <replace from="@package_version@" to="version" type="package-info"/>
                   55001:    </file>
                   55002:    <file role="php" name="PEAR/Installer/Role/Script.xml"/>
                   55003:    <file role="php" name="PEAR/Installer/Role/Script.php">
                   55004:     <replace from="@package_version@" to="version" type="package-info"/>
                   55005:    </file>
                   55006:    <file role="php" name="PEAR/Installer/Role/Src.xml"/>
                   55007:    <file role="php" name="PEAR/Installer/Role/Src.php">
                   55008:     <replace from="@package_version@" to="version" type="package-info"/>
                   55009:    </file>
                   55010:    <file role="php" name="PEAR/Installer/Role/Test.xml"/>
                   55011:    <file role="php" name="PEAR/Installer/Role/Test.php">
                   55012:     <replace from="@package_version@" to="version" type="package-info"/>
                   55013:    </file>
                   55014:    <file role="php" name="PEAR/Installer/Role/Www.xml"/>
                   55015:    <file role="php" name="PEAR/Installer/Role/Www.php">
                   55016:     <replace from="@package_version@" to="version" type="package-info"/>
                   55017:    </file>
                   55018:    <file role="php" name="PEAR/Installer/Role.php">
                   55019:     <replace from="@package_version@" to="version" type="package-info"/>
                   55020:    </file>
                   55021:    <file role="php" name="PEAR/PackageFile/Generator/v1.php">
                   55022:     <replace from="@PEAR-VER@" to="version" type="package-info"/>
                   55023:    </file>
                   55024:    <file role="php" name="PEAR/PackageFile/Generator/v2.php">
                   55025:     <replace from="@PEAR-VER@" to="version" type="package-info"/>
                   55026:    </file>
                   55027:    <file role="php" name="PEAR/PackageFile/Parser/v1.php">
                   55028:     <replace from="@package_version@" to="version" type="package-info"/>
                   55029:    </file>
                   55030:    <file role="php" name="PEAR/PackageFile/Parser/v2.php">
                   55031:     <replace from="@package_version@" to="version" type="package-info"/>
                   55032:    </file>
                   55033:    <file role="php" name="PEAR/PackageFile/v2/rw.php">
                   55034:     <replace from="@package_version@" to="version" type="package-info"/>
                   55035:    </file>
                   55036:    <file role="php" name="PEAR/PackageFile/v2/Validator.php">
                   55037:     <replace from="@package_version@" to="version" type="package-info"/>
                   55038:    </file>
                   55039:    <file role="php" name="PEAR/PackageFile/v1.php">
                   55040:     <replace from="@package_version@" to="version" type="package-info"/>
                   55041:    </file>
                   55042:    <file role="php" name="PEAR/PackageFile/v2.php">
                   55043:     <replace from="@package_version@" to="version" type="package-info"/>
                   55044:    </file>
                   55045:    <file role="php" name="PEAR/REST/10.php">
                   55046:     <replace from="@package_version@" to="version" type="package-info"/>
                   55047:    </file>
                   55048:    <file role="php" name="PEAR/REST/11.php">
                   55049:     <replace from="@package_version@" to="version" type="package-info"/>
                   55050:    </file>
                   55051:    <file role="php" name="PEAR/REST/13.php">
                   55052:     <replace from="@package_version@" to="version" type="package-info"/>
                   55053:    </file>
                   55054:    <file role="php" name="PEAR/Task/Postinstallscript/rw.php">
                   55055:     <replace from="@package_version@" to="version" type="package-info"/>
                   55056:    </file>
                   55057:    <file role="php" name="PEAR/Task/Replace/rw.php">
                   55058:     <replace from="@package_version@" to="version" type="package-info"/>
                   55059:    </file>
                   55060:    <file role="php" name="PEAR/Task/Unixeol/rw.php">
                   55061:     <replace from="@package_version@" to="version" type="package-info"/>
                   55062:    </file>
                   55063:    <file role="php" name="PEAR/Task/Windowseol/rw.php">
                   55064:     <replace from="@package_version@" to="version" type="package-info"/>
                   55065:    </file>
                   55066:    <file role="php" name="PEAR/Task/Common.php">
                   55067:     <replace from="@package_version@" to="version" type="package-info"/>
                   55068:    </file>
                   55069:    <file role="php" name="PEAR/Task/Postinstallscript.php">
                   55070:     <replace from="@package_version@" to="version" type="package-info"/>
                   55071:    </file>
                   55072:    <file role="php" name="PEAR/Task/Replace.php">
                   55073:     <replace from="@package_version@" to="version" type="package-info"/>
                   55074:    </file>
                   55075:    <file role="php" name="PEAR/Task/Unixeol.php">
                   55076:     <replace from="@package_version@" to="version" type="package-info"/>
                   55077:    </file>
                   55078:    <file role="php" name="PEAR/Task/Windowseol.php">
                   55079:     <replace from="@package_version@" to="version" type="package-info"/>
                   55080:    </file>
                   55081:    <file role="php" name="PEAR/Validator/PECL.php">
                   55082:     <replace from="@package_version@" to="version" type="package-info"/>
                   55083:    </file>
                   55084:    <file role="php" name="PEAR/Autoloader.php">
                   55085:     <replace from="@package_version@" to="version" type="package-info"/>
                   55086:    </file>
                   55087:    <file role="php" name="PEAR/Builder.php">
                   55088:     <replace from="@PEAR-VER@" to="version" type="package-info"/>
                   55089:    </file>
                   55090:    <file role="php" name="PEAR/ChannelFile.php">
                   55091:     <replace from="@package_version@" to="version" type="package-info"/>
                   55092:    </file>
                   55093:    <file role="php" name="PEAR/Command.php">
                   55094:     <replace from="@package_version@" to="version" type="package-info"/>
                   55095:    </file>
                   55096:    <file role="php" name="PEAR/Common.php">
                   55097:     <replace from="@package_version@" to="version" type="package-info"/>
                   55098:    </file>
                   55099:    <file role="php" name="PEAR/Config.php">
                   55100:     <replace from="@package_version@" to="version" type="package-info"/>
                   55101:    </file>
                   55102:    <file role="php" name="PEAR/DependencyDB.php">
                   55103:     <replace from="@package_version@" to="version" type="package-info"/>
                   55104:    </file>
                   55105:    <file role="php" name="PEAR/Dependency2.php">
                   55106:     <replace from="@PEAR-VER@" to="version" type="package-info"/>
                   55107:    </file>
                   55108:    <file role="php" name="PEAR/Downloader.php">
                   55109:     <replace from="@package_version@" to="version" type="package-info"/>
                   55110:    </file>
                   55111:    <file role="php" name="PEAR/ErrorStack.php">
                   55112:     <replace from="@package_version@" to="version" type="package-info"/>
                   55113:    </file>
                   55114:    <file role="php" name="PEAR/Exception.php">
                   55115:     <replace from="@package_version@" to="version" type="package-info"/>
                   55116:    </file>
                   55117:    <file role="php" name="PEAR/FixPHP5PEARWarnings.php"/>
                   55118:    <file role="php" name="PEAR/Frontend.php">
                   55119:     <replace from="@package_version@" to="version" type="package-info"/>
                   55120:    </file>
                   55121:    <file role="php" name="PEAR/Installer.php">
                   55122:     <replace from="@package_version@" to="version" type="package-info"/>
                   55123:    </file>
                   55124:    <file role="php" name="PEAR/Packager.php">
                   55125:     <replace from="@package_version@" to="version" type="package-info"/>
                   55126:    </file>
                   55127:    <file role="php" name="PEAR/PackageFile.php">
                   55128:     <replace from="@PEAR-VER@" to="version" type="package-info"/>
                   55129:    </file>
                   55130:    <file role="php" name="PEAR/Registry.php">
                   55131:     <replace from="@package_version@" to="version" type="package-info"/>
                   55132:    </file>
                   55133:    <file role="php" name="PEAR/REST.php">
                   55134:     <replace from="@package_version@" to="version" type="package-info"/>
                   55135:    </file>
                   55136:    <file role="php" name="PEAR/RunTest.php">
                   55137:     <replace from="@package_version@" to="version" type="package-info"/>
                   55138:    </file>
                   55139:    <file role="php" name="PEAR/Validate.php">
                   55140:     <replace from="@package_version@" to="version" type="package-info"/>
                   55141:    </file>
                   55142:    <file role="php" name="PEAR/XMLParser.php">
                   55143:     <replace from="@package_version@" to="version" type="package-info"/>
                   55144:    </file>
                   55145:    <file role="script" baseinstalldir="/" platform="!windows" install-as="pear" name="scripts/pear.sh">
                   55146:     <replace from="@php_bin@" to="php_bin" type="pear-config"/>
                   55147:     <replace from="@php_dir@" to="php_dir" type="pear-config"/>
                   55148:     <replace from="@pear_version@" to="version" type="package-info"/>
                   55149:     <replace from="@include_path@" to="php_dir" type="pear-config"/>
                   55150:    </file>
                   55151:    <file role="script" baseinstalldir="/" platform="!windows" install-as="peardev" name="scripts/peardev.sh">
                   55152:     <replace from="@php_bin@" to="php_bin" type="pear-config"/>
                   55153:     <replace from="@php_dir@" to="php_dir" type="pear-config"/>
                   55154:     <replace from="@pear_version@" to="version" type="package-info"/>
                   55155:     <replace from="@include_path@" to="php_dir" type="pear-config"/>
                   55156:    </file>
                   55157:    <file role="script" baseinstalldir="/" platform="!windows" install-as="pecl" name="scripts/pecl.sh">
                   55158:     <replace from="@php_bin@" to="php_bin" type="pear-config"/>
                   55159:     <replace from="@php_dir@" to="php_dir" type="pear-config"/>
                   55160:     <replace from="@pear_version@" to="version" type="package-info"/>
                   55161:     <replace from="@include_path@" to="php_dir" type="pear-config"/>
                   55162:    </file>
                   55163:    <file role="script" baseinstalldir="/" platform="windows" install-as="peardev.bat" name="scripts/peardev.bat">
                   55164:     <replace from="@bin_dir@" to="bin_dir" type="pear-config"/>
                   55165:     <replace from="@php_bin@" to="php_bin" type="pear-config"/>
                   55166:     <replace from="@include_path@" to="php_dir" type="pear-config"/>
                   55167:    </file>
                   55168:    <file role="script" baseinstalldir="/" platform="windows" install-as="pear.bat" name="scripts/pear.bat">
                   55169:     <replace from="@bin_dir@" to="bin_dir" type="pear-config"/>
                   55170:     <replace from="@php_bin@" to="php_bin" type="pear-config"/>
                   55171:     <replace from="@include_path@" to="php_dir" type="pear-config"/>
                   55172:    </file>
                   55173:    <file role="script" baseinstalldir="/" platform="windows" install-as="pecl.bat" name="scripts/pecl.bat">
                   55174:     <replace from="@bin_dir@" to="bin_dir" type="pear-config"/>
                   55175:     <replace from="@php_bin@" to="php_bin" type="pear-config"/>
                   55176:     <replace from="@include_path@" to="php_dir" type="pear-config"/>
                   55177:    </file>
                   55178:    <file role="php" baseinstalldir="/" install-as="pearcmd.php" name="scripts/pearcmd.php">
                   55179:     <replace from="@php_bin@" to="php_bin" type="pear-config"/>
                   55180:     <replace from="@php_dir@" to="php_dir" type="pear-config"/>
                   55181:     <replace from="@pear_version@" to="version" type="package-info"/>
                   55182:     <replace from="@include_path@" to="php_dir" type="pear-config"/>
                   55183:    </file>
                   55184:    <file role="php" baseinstalldir="/" install-as="peclcmd.php" name="scripts/peclcmd.php">
                   55185:     <replace from="@php_bin@" to="php_bin" type="pear-config"/>
                   55186:     <replace from="@php_dir@" to="php_dir" type="pear-config"/>
                   55187:     <replace from="@pear_version@" to="version" type="package-info"/>
                   55188:     <replace from="@include_path@" to="php_dir" type="pear-config"/>
                   55189:    </file>
                   55190:    <file role="doc" baseinstalldir="/" name="LICENSE"/>
                   55191:    <file role="doc" baseinstalldir="/" name="INSTALL"/>
                   55192:    <file role="data" baseinstalldir="/" name="package.dtd"/>
                   55193:    <file role="data" baseinstalldir="/" name="template.spec"/>
                   55194:    <file role="php" baseinstalldir="/" name="PEAR.php">
                   55195:     <replace from="@package_version@" to="version" type="package-info"/>
                   55196:    </file>
                   55197:    <file role="php" baseinstalldir="/" name="PEAR5.php"/>
                   55198:    <file role="doc" baseinstalldir="/" name="README"/>
                   55199:    <file role="php" baseinstalldir="/" name="System.php">
                   55200:     <replace from="@package_version@" to="version" type="package-info"/>
                   55201:    </file>
                   55202:   </filelist>
                   55203:  </release>
                   55204:  <changelog>
                   55205:    <release>
                   55206:     <version>1.8.0alpha1</version>
                   55207:     <date>2009-03-09</date>
                   55208:     <license>New BSD License</license>
                   55209:     <state>alpha</state>
                   55210:     <notes>* Implement Request #10373: if pref_state=stable and installed package=beta, allow up to latest beta version [dufuz]
                   55211: * Implement Request #10581: login / logout should map to channel-login / channel-logout [dufuz]
                   55212: * Implement Request #10825: Only display the &quot;invalid or missing package file&quot;-error if it makes sense [dufuz]
                   55213: * Implement Request #11170: script to generate Command/[command].xml [dufuz]
                   55214: * Implement Request #11176: improve channel ... has updated its protocols message [dufuz]
                   55215: * Implement Request #12706: pear list -a hard to read [dufuz]
                   55216: * Implement Request #11353: upgrade-all and upgrade commands to upgrade within the same stability level [dufuz]
                   55217: * Implement Request #13015: Add https discovery for channel.xml [dufuz / initial patch by Martin Roos]
                   55218: * Implement Request #13927: install-pear.php should have option to set www_dir [timj]
                   55219: * Implement Request #14324: Make the pear install command behave similar to apt-get [dufuz]
                   55220: * Implement Request #14325: make pear upgrade with no params behave like pear upgrade-all [dufuz]
                   55221:   - upgrade-all can be considered deprecated in favor of calling upgrade with no parameters to replicate
                   55222:     better what other package managers are doing. upgrade-all will still work as intended.
                   55223: * Implement Request #14504: add a channel parameter support to the upgrade function [dufuz]
                   55224:   - Options -c ezc and --channel=ezc got added to upgrade and upgrade-all to allow for
                   55225:     channel specific upgrades
                   55226: * Implement Request #14556: install-pear-nozlib.phar should get download_dir config and other options [cweiske]
                   55227: * Implement Request #15566: Add doc.php.net as a default channel [dufuz / saltybeagle]
                   55228: * Fix PHP Bug #43857: --program-suffix not always reflected everywhere [cellog]
                   55229: * Fix PHP Bug #47323: strotime warnings in make install [dufuz]
                   55230: * Fix Bug #13908: pear info command and maintainers inactive not mentioned [dufuz]
                   55231: * Fix Bug #13926: install-pear.php does not set cfg_dir if -d option set with no -c option [timj]
                   55232: * Fix Bug #13943: tests fail when php.exe path contains spaces [dufuz / jorrit]
                   55233: * Fix Bug #13953: config-set/config-show with channel alias fail [cellog]
                   55234: * Fix Bug #13958: When a phpt tests exit() or die() xdebug coverage is not generated, patch by izi (David Jean Louis) [izi / dufuz]
                   55235: * Fix Bug #14041: Unpredictable unit test processing sequence [dufuz]
                   55236: * Fix Bug #14140: Strict warning not suppressed in the shutdown function [dufuz]
                   55237: * Fix Bug #14210: pear list -ia brings warnings [dufuz]
                   55238: * Fix Bug #14274: PEAR packager mangles package.xml encoding, then complains about it [dufuz]
                   55239: * Fix Bug #14287: cannot upgrade from stable to beta via -beta when config is set to stable [dufuz]
                   55240: * Fix Bug #14300: Package files themselves can not be served over https [dufuz / initial patch by Martin Roos]
                   55241: * Fix Bug #14437: openbasedir warning when loading config [dufuz]
                   55242: * Fix Bug #14558: PackageFile.php creates tmp directory outside configured temp_dir [cweiske]
                   55243: * Fix Bug #14947: downloadHttp() is missing Host part of the HTTP Request when using Proxy [ifeghali]
                   55244: * Fix Bug #14977: PEAR/Frontend.php doesn&apos;t require_once PEAR.php [dufuz]
                   55245: * Fix Bug #15750: Unreachable code in PEAR_Downloader [dufuz]
                   55246: * Fix Bug #15979: Package files incorrectly removed when splitting a package into multiple pkgs [dufuz]
                   55247: * Fix Bug #15914: pear upgrade installs different version if desired version not found [dufuz]
                   55248: NOTE!
                   55249: Functions that have been deprecated for 3+ years in PEAR_Common, please take a moment
                   55250: to migrate over to one of the alternatives that have ben provided:
                   55251: * PEAR_Common-&gt;downloadHttp (use PEAR_Downloader-&gt;downloadHttp instead)
                   55252: * PEAR_Common-&gt;infoFromTgzFile (use PEAR_PackageFile-&gt;fromTgzFile instead)
                   55253: * PEAR_Common-&gt;infoFromDescriptionFile (use PEAR_PackageFile-&gt;fromPackageFile instead)
                   55254: * PEAR_Common-&gt;infoFromString (use PEAR_PackageFile-&gt;fromXmlstring instead)
                   55255: * PEAR_Common-&gt;infoFromArray (use PEAR_PackageFile-&gt;fromAnyFile instead)
                   55256: * PEAR_Common-&gt;xmlFromInfo (use a PEAR_PackageFile_v* object&apos;s generator instead)
                   55257: * PEAR_Common-&gt;validatePackageInfo (use the validation of PEAR_PackageFile objects)
                   55258: * PEAR_Common-&gt;analyzeSourceCode (use a PEAR_PackageFile_v* object instead)
                   55259: * PEAR_Common-&gt;detectDependencies (use PEAR_Downloader_Package-&gt;detectDependencies instead)
                   55260: * PEAR_Common-&gt;buildProvidesArray (use PEAR_PackageFile_v1-&gt;_buildProvidesArray or
                   55261:   PEAR_PackageFile_v2_Validator-&gt;_buildProvidesArray)
                   55262: PHP 4.4 and 5.1.6 are now the minimum PHP requirements, for brave souls
                   55263: pear upgrade -f PEAR will allow people with lower versions
                   55264: to upgrade to this release but no guarantees will be made that it will work properly.
                   55265: Support for XML RPC channels has been dropped - The only ones that used it
                   55266: (pear.php.net and pecl.php.net) have used the REST interface for years now.
                   55267: SOAP support also removed as it was only proof of concept.
                   55268: Move codebase from the PHP License to New BSD 2 clause license
                   55269:     </notes>
                   55270:    </release>
                   55271:    <release>
                   55272:     <version>1.8.0RC1</version>
                   55273:     <date>2009-03-27</date>
                   55274:     <license>New BSD License</license>
                   55275:     <state>beta</state>
                   55276:     <notes>* Fix Bug #14331: pear cvstag only works from inside the package directory [dufuz]
                   55277: * Fix Bug #16045: E_Notice: Undefined index: channel in PEAR/DependencyDB.php [dufuz]
                   55278: * Implemented Request #11230: better error message when mirror not in channel.xml file [dufuz]
                   55279: * Implemented Request #13150: Add support for following HTTP 302 redirects [dufuz]
                   55280:     </notes>
                   55281:    </release>
                   55282:    <release>
                   55283:    </release>
                   55284:    <release>
                   55285:     <license>New BSD License</license>
                   55286:     <notes>Changes since RC1:
                   55287:   * Fix Bug #14792: Bad md5sum for files with replaced content [dufuz]
                   55288:   * Fix Bug #16057:-r is limited to 4 directories in depth [dufuz]
                   55289:   * Fix Bug #16077: PEAR5::getStaticProperty does not return a reference to the property [dufuz]
                   55290: 
                   55291:   Remove custom XML_Util class in favor of using upstream XML_Util package as dependency
                   55292: 
                   55293: RC1 Release Notes:
                   55294:   * Fix Bug #14331: pear cvstag only works from inside the package directory [dufuz]
                   55295:   * Fix Bug #16045: E_Notice: Undefined index: channel in PEAR/DependencyDB.php [dufuz]
                   55296: 
                   55297:   * Implemented Request #11230: better error message when mirror not in channel.xml file [dufuz]
                   55298:   * Implemented Request #13150: Add support for following HTTP 302 redirects [dufuz]
                   55299: 
                   55300: Alpha1 Release Notes:
                   55301:   * Implement Request #10373: if pref_state=stable and installed package=beta, allow up to latest beta version [dufuz]
                   55302:   * Implement Request #10581: login / logout should map to channel-login / channel-logout [dufuz]
                   55303:   * Implement Request #10825: Only display the &quot;invalid or missing package file&quot;-error if it makes sense [dufuz]
                   55304:   * Implement Request #11170: script to generate Command/[command].xml [dufuz]
                   55305:   * Implement Request #11176: improve channel ... has updated its protocols message [dufuz]
                   55306:   * Implement Request #12706: pear list -a hard to read [dufuz]
                   55307:   * Implement Request #11353: upgrade-all and upgrade commands to upgrade within the same stability level [dufuz]
                   55308:   * Implement Request #13015: Add https discovery for channel.xml [dufuz / initial patch by Martin Roos]
                   55309:   * Implement Request #13927: install-pear.php should have option to set www_dir [timj]
                   55310:   * Implement Request #14324: Make the pear install command behave similar to apt-get [dufuz]
                   55311:   * Implement Request #14325: make pear upgrade with no params behave like pear upgrade-all [dufuz]
                   55312:     - upgrade-all can be considered deprecated in favor of calling upgrade with no parameters to replicate
                   55313:       better what other package managers are doing. upgrade-all will still work as intended.
                   55314:   * Implement Request #14504: add a channel parameter support to the upgrade function [dufuz]
                   55315:     - Options -c ezc and --channel=ezc got added to upgrade and upgrade-all to allow for
                   55316:       channel specific upgrades
                   55317:   * Implement Request #14556: install-pear-nozlib.phar should get download_dir config and other options [cweiske]
                   55318:   * Implement Request #15566: Add doc.php.net as a default channel [dufuz / saltybeagle]
                   55319: 
                   55320:   * Fix PHP Bug #43857: --program-suffix not always reflected everywhere [cellog]
                   55321:   * Fix PHP Bug #47323: strotime warnings in make install [dufuz]
                   55322: 
                   55323:   * Fix Bug #13908: pear info command and maintainers inactive not mentioned [dufuz]
                   55324:   * Fix Bug #13926: install-pear.php does not set cfg_dir if -d option set with no -c option [timj]
                   55325:   * Fix Bug #13943: tests fail when php.exe path contains spaces [dufuz / jorrit]
                   55326:   * Fix Bug #13953: config-set/config-show with channel alias fail [cellog]
                   55327:   * Fix Bug #13958: When a phpt tests exit() or die() xdebug coverage is not generated, patch by izi (David Jean Louis) [izi / dufuz]
                   55328:   * Fix Bug #14041: Unpredictable unit test processing sequence [dufuz]
                   55329:   * Fix Bug #14140: Strict warning not suppressed in the shutdown function [dufuz]
                   55330:   * Fix Bug #14210: pear list -ia brings warnings [dufuz]
                   55331:   * Fix Bug #14274: PEAR packager mangles package.xml encoding, then complains about it [dufuz]
                   55332:   * Fix Bug #14287: cannot upgrade from stable to beta via -beta when config is set to stable [dufuz]
                   55333:   * Fix Bug #14300: Package files themselves can not be served over https [dufuz / initial patch by Martin Roos]
                   55334:   * Fix Bug #14437: openbasedir warning when loading config [dufuz]
                   55335:   * Fix Bug #14558: PackageFile.php creates tmp directory outside configured temp_dir [cweiske]
                   55336:   * Fix Bug #14947: downloadHttp() is missing Host part of the HTTP Request when using Proxy [ifeghali]
                   55337:   * Fix Bug #14977: PEAR/Frontend.php doesn&apos;t require_once PEAR.php [dufuz]
                   55338:   * Fix Bug #15750: Unreachable code in PEAR_Downloader [dufuz]
                   55339:   * Fix Bug #15979: Package files incorrectly removed when splitting a package into multiple pkgs [dufuz]
                   55340:   * Fix Bug #15914: pear upgrade installs different version if desired version not found [dufuz]
                   55341: 
                   55342:   NOTE!
                   55343:   Functions that have been deprecated for 3+ years in PEAR_Common, please take a moment
                   55344:   to migrate over to one of the alternatives that have ben provided:
                   55345:   * PEAR_Common-&gt;downloadHttp (use PEAR_Downloader-&gt;downloadHttp instead)
                   55346:   * PEAR_Common-&gt;infoFromTgzFile (use PEAR_PackageFile-&gt;fromTgzFile instead)
                   55347:   * PEAR_Common-&gt;infoFromDescriptionFile (use PEAR_PackageFile-&gt;fromPackageFile instead)
                   55348:   * PEAR_Common-&gt;infoFromString (use PEAR_PackageFile-&gt;fromXmlstring instead)
                   55349:   * PEAR_Common-&gt;infoFromArray (use PEAR_PackageFile-&gt;fromAnyFile instead)
                   55350:   * PEAR_Common-&gt;xmlFromInfo (use a PEAR_PackageFile_v* object&apos;s generator instead)
                   55351:   * PEAR_Common-&gt;validatePackageInfo (use the validation of PEAR_PackageFile objects)
                   55352:   * PEAR_Common-&gt;analyzeSourceCode (use a PEAR_PackageFile_v* object instead)
                   55353:   * PEAR_Common-&gt;detectDependencies (use PEAR_Downloader_Package-&gt;detectDependencies instead)
                   55354:   * PEAR_Common-&gt;buildProvidesArray (use PEAR_PackageFile_v1-&gt;_buildProvidesArray or
                   55355:     PEAR_PackageFile_v2_Validator-&gt;_buildProvidesArray)
                   55356: 
                   55357:   PHP 4.4 and 5.1.6 are now the minimum PHP requirements, for brave souls
                   55358:   pear upgrade -f PEAR will allow people with lower versions
                   55359:   to upgrade to this release but no guarantees will be made that it will work properly.
                   55360: 
                   55361:   Support for XML RPC channels has been dropped - The only ones that used it
                   55362:   (pear.php.net and pecl.php.net) have used the REST interface for years now.
                   55363:   SOAP support also removed as it was only proof of concept.
                   55364: 
                   55365:   Move codebase from the PHP License to New BSD 2 clause license
                   55366:     </notes>
                   55367:    </release>
                   55368:    <release>
                   55369:     <version>1.8.1</version>
                   55370:     <date>2009-04-15</date>
                   55371:     <license>New BSD License</license>
                   55372:     <state>stable</state>
                   55373:     <notes>* Fix Bug #16099    PEAR crash on PHP4 (parse error) [dufuz]
                   55374:     </notes>
                   55375:    </release>
                   55376:    <release>
                   55377:     <version>1.9.0RC1</version>
                   55378:     <date>2009-08-18</date>
                   55379:     <license>New BSD License</license>
                   55380:     <state>beta</state>
                   55381:     <notes>* Implement Request #16213: add alias to list-channels output [dufuz]
                   55382: * Implement Request #16378: pear svntag [dufuz]
                   55383: * Implement Request #16386: PEAR_Config::remove() does not support specifying a channel [timj]
                   55384: * Implement Request #16396: package-dependencies should allow package names [dufuz]
                   55385: * Fix Bug #11181: pear requests channel.xml from main server instead from mirror [dufuz]
                   55386: * Fix Bug #14493: pear install --offline doesn&apos;t print out errors [dufuz]
                   55387: * Fix Bug #11348: pear package-dependencies isn&apos;t well explained [dufuz]
                   55388: * Fix Bug #16108: PEAR_PackageFile_Generator_v2 PHP4 parse error when running upgrade-all [dufuz]
                   55389: * Fix Bug #16113: Installing certain packages fails due incorrect encoding handling [dufuz]
                   55390: * Fix Bug #16122: PEAR RunTest failed to run as expected [dufuz]
                   55391: * Fix Bug #16366: compiling 5.2.10 leads to non-functioning pear [dufuz]
                   55392: * Fix Bug #16387: channel-logout does not support logging out from a non-default channel [timj]
                   55393: * Fix Bug #16444: Setting preferred mirror fails [dufuz]
                   55394: * Fix the shutdown functions where a index might not exist and thus raise a notice [derick]
                   55395:     </notes>
                   55396:    </release>
                   55397:    <release>
                   55398:     <version>1.9.0RC2</version>
                   55399:     <date>2009-08-20</date>
                   55400:     <license>New BSD License</license>
                   55401:     <state>beta</state>
                   55402:     <notes>* REST 1.4 file was occasionally being included but REST 1.4 is not intended for this release cycle [dufuz]
                   55403:     </notes>
                   55404:    </release>
                   55405:    <release>
                   55406:     <version>1.9.0RC3</version>
                   55407:     <date>2009-08-21</date>
                   55408:     <license>New BSD License</license>
                   55409:     <state>beta</state>
                   55410:     <notes>* Improved svntag support to handle packages like PEAR it self [dufuz]
                   55411:     </notes>
                   55412:    </release>
                   55413:    <release>
                   55414:     <version>1.9.0RC4</version>
                   55415:     <date>2009-08-23</date>
                   55416:     <license>New BSD License</license>
                   55417:     <state>beta</state>
                   55418:     <notes>* Fixed a problem where the original channel could not be set as a preferred_mirror again [dufuz]
                   55419: * Make sure channel aliases can&apos;t be made to start with - [dufuz]
                   55420: * Output issues with pear search [dufuz]
                   55421: * Fixed couple of stray notices [dufuz]
                   55422:     </notes>
                   55423:    </release>
                   55424:    <release>
                   55425:     <version>1.9.0</version>
                   55426:     <date>2009-09-03</date>
                   55427:     <license>New BSD License</license>
                   55428:     <state>stable</state>
                   55429:     <notes>* Fix  Bug #16547: The phar for PEAR installer uses ereg() which is deprecated [dufuz]
                   55430:     </notes>
                   55431:    </release>
                   55432:    <release>
                   55433:     <version>1.9.1</version>
                   55434:     <date>2010-05-26</date>
                   55435:     <license>New BSD License</license>
                   55436:     <state>stable</state>
                   55437:     <notes>* svntag improvements, tag package files passed into the command and better directory checks [dufuz]
                   55438: * rely on Structures_Graph minimum version instead of recommended version [saltybeagle]
                   55439: * Fix Bug #12613: running go-pear.phar from C:\ fails [dufuz]
                   55440: * Fix Bug #14841: Installing pear into directory with space fails [dufuz]
                   55441: * Fix Bug #16644: pear.bat returns syntax error when parenthesis are in install path. [dufuz] [patch by bwaters (Bryan Waters)]
                   55442: * Fix Bug #16767: Use of Depreciated HTML Attributes in the Exception class [dufuz] [patch by fuhrysteve (Stephen J. Fuhry)]
                   55443: * Fix Bug #16864: &quot;pear list-upgrades -i&quot; issues E_WARNINGS [dufuz] [patch by rquadling (Richard Quadling)]
                   55444: * Fix Bug #17220: command `pear help` outputs to stderr instead of stdout [dufuz]
                   55445: * Fix Bug #17234: channel-discover adds port to HTTP Host header [dufuz]
                   55446: * Fix Bug #17292: Code Coverage in PEAR_RunTest does not work with namespaces [sebastian]
                   55447: * Fix Bug #17359: loadExtension() fails over missing dl() when used in multithread env [dufuz]
                   55448: * Fix Bug #17378: pear info $package fails if directory with that name exists [dufuz]
                   55449:     </notes>
                   55450:    </release>
                   55451:    <release>
                   55452:     <version>1.9.2</version>
                   55453:     <date>2011-02-28</date>
                   55454:     <license>New BSD License</license>
                   55455:     <state>stable</state>
                   55456:     <notes>Important! This is a security fix release. The advisory can be found at
                   55457: http://pear.php.net/advisory-20110228.txt
                   55458: 
                   55459:     Bugs:
                   55460:     * Fixed Bug #17463: Regression: On Windows, svntag [patch by doconnor]
                   55461:     * Fixed Bug #17641: pecl-list doesn&apos;t sort packages by name [dufuz]
                   55462:     * Fixed Bug #17781: invalid argument warning on foreach due to an empty optional dependencie [dufuz]
                   55463:     * Fixed Bug #17801: PEAR run-tests wrongly detects php-cgi [patch by David Jean Louis (izi)]
                   55464:     * Fixed Bug #17839: pear svntag does not tag package.xml file [dufuz]
                   55465:     * Fixed Bug #17986: PEAR Installer cannot handle files moved between packages [dufuz]
                   55466:     * Fixed Bug #17997: Strange output if directories are not writeable [dufuz]
                   55467:     * Fixed Bug #18001: PEAR/RunTest coverage fails [dufuz]
                   55468:     * Fixed Bug #18056 [SECURITY]: Symlink attack in PEAR install [dufuz]
                   55469:     * Fixed Bug #18218: &quot;pear package&quot; does not allow the use of late static binding [dufuz and Christer Edvartsen]
                   55470:     * Fixed Bug #18238: Wrong return code from &quot;pear help&quot; [till]
                   55471:     * Fixed Bug #18308: Broken error message about missing channel validator [yunosh]
                   55472: 
                   55473:     This feature is implemented as a result of #18056
                   55474:     * Implemented Request #16648: Use TMPDIR for builds instead of /var/tmp [dufuz]
                   55475:     </notes>
                   55476:    </release>
                   55477:    <release>
                   55478:     <version>1.9.3</version>
                   55479:     <date>2011-06-04</date>
                   55480:     <license>New BSD License</license>
                   55481:     <state>stable</state>
                   55482:     <notes>* Fixed Bug #17744: Empty changelog causes fatal error in setChangelogentry [dufuz]
                   55483: * Fixed Bug #18340: raiseErro typo [doconnor]
                   55484: * Fixed Bug #18349: package.xml version not recognized when single quoted [dufuz]
                   55485: * Fixed Bug #18364: date.timezone errors for sh/bat files when TZ is not set in php.ini [dufuz]
                   55486: * Fixed Bug #18388: Parentheses error in REST.php line 232 [dufuz]
                   55487: * Fixed Bug #18428: invalid preg_match patterns [glen]
                   55488: * Fixed Bug #18486: REST/10.php does not check error condition [dufuz]
                   55489: * Fixed a problem in RunTest and code coverage. Correctly register the
                   55490:   code coverage shutdown function in case we are inside a namespace. [sebastian]
                   55491: * Fixed a bug with extensions not providing their config.m4 and co in the root directory
                   55492:   of their pecl package but rather in a sub directory, such as xhprof. [dufuz]
                   55493:     </notes>
                   55494:    </release>
                   55495:  </changelog>
                   55496: </package>
                   55497: <?php
                   55498: /**
                   55499:  * PEAR, the PHP Extension and Application Repository
                   55500:  *
                   55501:  * PEAR class and PEAR_Error class
                   55502:  *
                   55503:  * PHP versions 4 and 5
                   55504:  *
                   55505:  * @category   pear
                   55506:  * @package    PEAR
                   55507:  * @author     Sterling Hughes <sterling@php.net>
                   55508:  * @author     Stig Bakken <ssb@php.net>
                   55509:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   55510:  * @author     Greg Beaver <cellog@php.net>
                   55511:  * @copyright  1997-2010 The Authors
                   55512:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    55513:  * @version    CVS: $Id: PEAR.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    55514:  * @link       http://pear.php.net/package/PEAR
                   55515:  * @since      File available since Release 0.1
                   55516:  */
                   55517: 
                   55518: /**#@+
                   55519:  * ERROR constants
                   55520:  */
                   55521: define('PEAR_ERROR_RETURN',     1);
                   55522: define('PEAR_ERROR_PRINT',      2);
                   55523: define('PEAR_ERROR_TRIGGER',    4);
                   55524: define('PEAR_ERROR_DIE',        8);
                   55525: define('PEAR_ERROR_CALLBACK',  16);
                   55526: /**
                   55527:  * WARNING: obsolete
                   55528:  * @deprecated
                   55529:  */
                   55530: define('PEAR_ERROR_EXCEPTION', 32);
                   55531: /**#@-*/
                   55532: define('PEAR_ZE2', (function_exists('version_compare') &&
                   55533:                     version_compare(zend_version(), "2-dev", "ge")));
                   55534: 
                   55535: if (substr(PHP_OS, 0, 3) == 'WIN') {
                   55536:     define('OS_WINDOWS', true);
                   55537:     define('OS_UNIX',    false);
                   55538:     define('PEAR_OS',    'Windows');
                   55539: } else {
                   55540:     define('OS_WINDOWS', false);
                   55541:     define('OS_UNIX',    true);
                   55542:     define('PEAR_OS',    'Unix'); // blatant assumption
                   55543: }
                   55544: 
                   55545: $GLOBALS['_PEAR_default_error_mode']     = PEAR_ERROR_RETURN;
                   55546: $GLOBALS['_PEAR_default_error_options']  = E_USER_NOTICE;
                   55547: $GLOBALS['_PEAR_destructor_object_list'] = array();
                   55548: $GLOBALS['_PEAR_shutdown_funcs']         = array();
                   55549: $GLOBALS['_PEAR_error_handler_stack']    = array();
                   55550: 
                   55551: @ini_set('track_errors', true);
                   55552: 
                   55553: /**
                   55554:  * Base class for other PEAR classes.  Provides rudimentary
                   55555:  * emulation of destructors.
                   55556:  *
                   55557:  * If you want a destructor in your class, inherit PEAR and make a
                   55558:  * destructor method called _yourclassname (same name as the
                   55559:  * constructor, but with a "_" prefix).  Also, in your constructor you
                   55560:  * have to call the PEAR constructor: $this->PEAR();.
                   55561:  * The destructor method will be called without parameters.  Note that
                   55562:  * at in some SAPI implementations (such as Apache), any output during
                   55563:  * the request shutdown (in which destructors are called) seems to be
                   55564:  * discarded.  If you need to get any debug information from your
                   55565:  * destructor, use error_log(), syslog() or something similar.
                   55566:  *
                   55567:  * IMPORTANT! To use the emulated destructors you need to create the
                   55568:  * objects by reference: $obj =& new PEAR_child;
                   55569:  *
                   55570:  * @category   pear
                   55571:  * @package    PEAR
                   55572:  * @author     Stig Bakken <ssb@php.net>
                   55573:  * @author     Tomas V.V. Cox <cox@idecnet.com>
                   55574:  * @author     Greg Beaver <cellog@php.net>
                   55575:  * @copyright  1997-2006 The PHP Group
                   55576:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    55577:  * @version    Release: 1.9.4
1.1       misho    55578:  * @link       http://pear.php.net/package/PEAR
                   55579:  * @see        PEAR_Error
                   55580:  * @since      Class available since PHP 4.0.2
                   55581:  * @link        http://pear.php.net/manual/en/core.pear.php#core.pear.pear
                   55582:  */
                   55583: class PEAR
                   55584: {
                   55585:     /**
                   55586:      * Whether to enable internal debug messages.
                   55587:      *
                   55588:      * @var     bool
                   55589:      * @access  private
                   55590:      */
                   55591:     var $_debug = false;
                   55592: 
                   55593:     /**
                   55594:      * Default error mode for this object.
                   55595:      *
                   55596:      * @var     int
                   55597:      * @access  private
                   55598:      */
                   55599:     var $_default_error_mode = null;
                   55600: 
                   55601:     /**
                   55602:      * Default error options used for this object when error mode
                   55603:      * is PEAR_ERROR_TRIGGER.
                   55604:      *
                   55605:      * @var     int
                   55606:      * @access  private
                   55607:      */
                   55608:     var $_default_error_options = null;
                   55609: 
                   55610:     /**
                   55611:      * Default error handler (callback) for this object, if error mode is
                   55612:      * PEAR_ERROR_CALLBACK.
                   55613:      *
                   55614:      * @var     string
                   55615:      * @access  private
                   55616:      */
                   55617:     var $_default_error_handler = '';
                   55618: 
                   55619:     /**
                   55620:      * Which class to use for error objects.
                   55621:      *
                   55622:      * @var     string
                   55623:      * @access  private
                   55624:      */
                   55625:     var $_error_class = 'PEAR_Error';
                   55626: 
                   55627:     /**
                   55628:      * An array of expected errors.
                   55629:      *
                   55630:      * @var     array
                   55631:      * @access  private
                   55632:      */
                   55633:     var $_expected_errors = array();
                   55634: 
                   55635:     /**
                   55636:      * Constructor.  Registers this object in
                   55637:      * $_PEAR_destructor_object_list for destructor emulation if a
                   55638:      * destructor object exists.
                   55639:      *
                   55640:      * @param string $error_class  (optional) which class to use for
                   55641:      *        error objects, defaults to PEAR_Error.
                   55642:      * @access public
                   55643:      * @return void
                   55644:      */
                   55645:     function PEAR($error_class = null)
                   55646:     {
                   55647:         $classname = strtolower(get_class($this));
                   55648:         if ($this->_debug) {
                   55649:             print "PEAR constructor called, class=$classname\n";
                   55650:         }
                   55651: 
                   55652:         if ($error_class !== null) {
                   55653:             $this->_error_class = $error_class;
                   55654:         }
                   55655: 
                   55656:         while ($classname && strcasecmp($classname, "pear")) {
                   55657:             $destructor = "_$classname";
                   55658:             if (method_exists($this, $destructor)) {
                   55659:                 global $_PEAR_destructor_object_list;
                   55660:                 $_PEAR_destructor_object_list[] = &$this;
                   55661:                 if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
                   55662:                     register_shutdown_function("_PEAR_call_destructors");
                   55663:                     $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
                   55664:                 }
                   55665:                 break;
                   55666:             } else {
                   55667:                 $classname = get_parent_class($classname);
                   55668:             }
                   55669:         }
                   55670:     }
                   55671: 
                   55672:     /**
                   55673:      * Destructor (the emulated type of...).  Does nothing right now,
                   55674:      * but is included for forward compatibility, so subclass
                   55675:      * destructors should always call it.
                   55676:      *
                   55677:      * See the note in the class desciption about output from
                   55678:      * destructors.
                   55679:      *
                   55680:      * @access public
                   55681:      * @return void
                   55682:      */
                   55683:     function _PEAR() {
                   55684:         if ($this->_debug) {
                   55685:             printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));
                   55686:         }
                   55687:     }
                   55688: 
                   55689:     /**
                   55690:     * If you have a class that's mostly/entirely static, and you need static
                   55691:     * properties, you can use this method to simulate them. Eg. in your method(s)
                   55692:     * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
                   55693:     * You MUST use a reference, or they will not persist!
                   55694:     *
                   55695:     * @access public
                   55696:     * @param  string $class  The calling classname, to prevent clashes
                   55697:     * @param  string $var    The variable to retrieve.
                   55698:     * @return mixed   A reference to the variable. If not set it will be
                   55699:     *                 auto initialised to NULL.
                   55700:     */
                   55701:     function &getStaticProperty($class, $var)
                   55702:     {
                   55703:         static $properties;
                   55704:         if (!isset($properties[$class])) {
                   55705:             $properties[$class] = array();
                   55706:         }
                   55707: 
                   55708:         if (!array_key_exists($var, $properties[$class])) {
                   55709:             $properties[$class][$var] = null;
                   55710:         }
                   55711: 
                   55712:         return $properties[$class][$var];
                   55713:     }
                   55714: 
                   55715:     /**
                   55716:     * Use this function to register a shutdown method for static
                   55717:     * classes.
                   55718:     *
                   55719:     * @access public
                   55720:     * @param  mixed $func  The function name (or array of class/method) to call
                   55721:     * @param  mixed $args  The arguments to pass to the function
                   55722:     * @return void
                   55723:     */
                   55724:     function registerShutdownFunc($func, $args = array())
                   55725:     {
                   55726:         // if we are called statically, there is a potential
                   55727:         // that no shutdown func is registered.  Bug #6445
                   55728:         if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
                   55729:             register_shutdown_function("_PEAR_call_destructors");
                   55730:             $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
                   55731:         }
                   55732:         $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
                   55733:     }
                   55734: 
                   55735:     /**
                   55736:      * Tell whether a value is a PEAR error.
                   55737:      *
                   55738:      * @param   mixed $data   the value to test
                   55739:      * @param   int   $code   if $data is an error object, return true
                   55740:      *                        only if $code is a string and
                   55741:      *                        $obj->getMessage() == $code or
                   55742:      *                        $code is an integer and $obj->getCode() == $code
                   55743:      * @access  public
                   55744:      * @return  bool    true if parameter is an error
                   55745:      */
                   55746:     function isError($data, $code = null)
                   55747:     {
                   55748:         if (!is_a($data, 'PEAR_Error')) {
                   55749:             return false;
                   55750:         }
                   55751: 
                   55752:         if (is_null($code)) {
                   55753:             return true;
                   55754:         } elseif (is_string($code)) {
                   55755:             return $data->getMessage() == $code;
                   55756:         }
                   55757: 
                   55758:         return $data->getCode() == $code;
                   55759:     }
                   55760: 
                   55761:     /**
                   55762:      * Sets how errors generated by this object should be handled.
                   55763:      * Can be invoked both in objects and statically.  If called
                   55764:      * statically, setErrorHandling sets the default behaviour for all
                   55765:      * PEAR objects.  If called in an object, setErrorHandling sets
                   55766:      * the default behaviour for that object.
                   55767:      *
                   55768:      * @param int $mode
                   55769:      *        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
                   55770:      *        PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
                   55771:      *        PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
                   55772:      *
                   55773:      * @param mixed $options
                   55774:      *        When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
                   55775:      *        of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
                   55776:      *
                   55777:      *        When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
                   55778:      *        to be the callback function or method.  A callback
                   55779:      *        function is a string with the name of the function, a
                   55780:      *        callback method is an array of two elements: the element
                   55781:      *        at index 0 is the object, and the element at index 1 is
                   55782:      *        the name of the method to call in the object.
                   55783:      *
                   55784:      *        When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
                   55785:      *        a printf format string used when printing the error
                   55786:      *        message.
                   55787:      *
                   55788:      * @access public
                   55789:      * @return void
                   55790:      * @see PEAR_ERROR_RETURN
                   55791:      * @see PEAR_ERROR_PRINT
                   55792:      * @see PEAR_ERROR_TRIGGER
                   55793:      * @see PEAR_ERROR_DIE
                   55794:      * @see PEAR_ERROR_CALLBACK
                   55795:      * @see PEAR_ERROR_EXCEPTION
                   55796:      *
                   55797:      * @since PHP 4.0.5
                   55798:      */
                   55799:     function setErrorHandling($mode = null, $options = null)
                   55800:     {
                   55801:         if (isset($this) && is_a($this, 'PEAR')) {
                   55802:             $setmode     = &$this->_default_error_mode;
                   55803:             $setoptions  = &$this->_default_error_options;
                   55804:         } else {
                   55805:             $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
                   55806:             $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
                   55807:         }
                   55808: 
                   55809:         switch ($mode) {
                   55810:             case PEAR_ERROR_EXCEPTION:
                   55811:             case PEAR_ERROR_RETURN:
                   55812:             case PEAR_ERROR_PRINT:
                   55813:             case PEAR_ERROR_TRIGGER:
                   55814:             case PEAR_ERROR_DIE:
                   55815:             case null:
                   55816:                 $setmode = $mode;
                   55817:                 $setoptions = $options;
                   55818:                 break;
                   55819: 
                   55820:             case PEAR_ERROR_CALLBACK:
                   55821:                 $setmode = $mode;
                   55822:                 // class/object method callback
                   55823:                 if (is_callable($options)) {
                   55824:                     $setoptions = $options;
                   55825:                 } else {
                   55826:                     trigger_error("invalid error callback", E_USER_WARNING);
                   55827:                 }
                   55828:                 break;
                   55829: 
                   55830:             default:
                   55831:                 trigger_error("invalid error mode", E_USER_WARNING);
                   55832:                 break;
                   55833:         }
                   55834:     }
                   55835: 
                   55836:     /**
                   55837:      * This method is used to tell which errors you expect to get.
                   55838:      * Expected errors are always returned with error mode
                   55839:      * PEAR_ERROR_RETURN.  Expected error codes are stored in a stack,
                   55840:      * and this method pushes a new element onto it.  The list of
                   55841:      * expected errors are in effect until they are popped off the
                   55842:      * stack with the popExpect() method.
                   55843:      *
                   55844:      * Note that this method can not be called statically
                   55845:      *
                   55846:      * @param mixed $code a single error code or an array of error codes to expect
                   55847:      *
                   55848:      * @return int     the new depth of the "expected errors" stack
                   55849:      * @access public
                   55850:      */
                   55851:     function expectError($code = '*')
                   55852:     {
                   55853:         if (is_array($code)) {
                   55854:             array_push($this->_expected_errors, $code);
                   55855:         } else {
                   55856:             array_push($this->_expected_errors, array($code));
                   55857:         }
                   55858:         return count($this->_expected_errors);
                   55859:     }
                   55860: 
                   55861:     /**
                   55862:      * This method pops one element off the expected error codes
                   55863:      * stack.
                   55864:      *
                   55865:      * @return array   the list of error codes that were popped
                   55866:      */
                   55867:     function popExpect()
                   55868:     {
                   55869:         return array_pop($this->_expected_errors);
                   55870:     }
                   55871: 
                   55872:     /**
                   55873:      * This method checks unsets an error code if available
                   55874:      *
                   55875:      * @param mixed error code
                   55876:      * @return bool true if the error code was unset, false otherwise
                   55877:      * @access private
                   55878:      * @since PHP 4.3.0
                   55879:      */
                   55880:     function _checkDelExpect($error_code)
                   55881:     {
                   55882:         $deleted = false;
                   55883:         foreach ($this->_expected_errors as $key => $error_array) {
                   55884:             if (in_array($error_code, $error_array)) {
                   55885:                 unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
                   55886:                 $deleted = true;
                   55887:             }
                   55888: 
                   55889:             // clean up empty arrays
                   55890:             if (0 == count($this->_expected_errors[$key])) {
                   55891:                 unset($this->_expected_errors[$key]);
                   55892:             }
                   55893:         }
                   55894: 
                   55895:         return $deleted;
                   55896:     }
                   55897: 
                   55898:     /**
                   55899:      * This method deletes all occurences of the specified element from
                   55900:      * the expected error codes stack.
                   55901:      *
                   55902:      * @param  mixed $error_code error code that should be deleted
                   55903:      * @return mixed list of error codes that were deleted or error
                   55904:      * @access public
                   55905:      * @since PHP 4.3.0
                   55906:      */
                   55907:     function delExpect($error_code)
                   55908:     {
                   55909:         $deleted = false;
                   55910:         if ((is_array($error_code) && (0 != count($error_code)))) {
                   55911:             // $error_code is a non-empty array here; we walk through it trying
                   55912:             // to unset all values
                   55913:             foreach ($error_code as $key => $error) {
                   55914:                 $deleted =  $this->_checkDelExpect($error) ? true : false;
                   55915:             }
                   55916: 
                   55917:             return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
                   55918:         } elseif (!empty($error_code)) {
                   55919:             // $error_code comes alone, trying to unset it
                   55920:             if ($this->_checkDelExpect($error_code)) {
                   55921:                 return true;
                   55922:             }
                   55923: 
                   55924:             return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
                   55925:         }
                   55926: 
                   55927:         // $error_code is empty
                   55928:         return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
                   55929:     }
                   55930: 
                   55931:     /**
                   55932:      * This method is a wrapper that returns an instance of the
                   55933:      * configured error class with this object's default error
                   55934:      * handling applied.  If the $mode and $options parameters are not
                   55935:      * specified, the object's defaults are used.
                   55936:      *
                   55937:      * @param mixed $message a text error message or a PEAR error object
                   55938:      *
                   55939:      * @param int $code      a numeric error code (it is up to your class
                   55940:      *                  to define these if you want to use codes)
                   55941:      *
                   55942:      * @param int $mode      One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
                   55943:      *                  PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
                   55944:      *                  PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
                   55945:      *
                   55946:      * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter
                   55947:      *                  specifies the PHP-internal error level (one of
                   55948:      *                  E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
                   55949:      *                  If $mode is PEAR_ERROR_CALLBACK, this
                   55950:      *                  parameter specifies the callback function or
                   55951:      *                  method.  In other error modes this parameter
                   55952:      *                  is ignored.
                   55953:      *
                   55954:      * @param string $userinfo If you need to pass along for example debug
                   55955:      *                  information, this parameter is meant for that.
                   55956:      *
                   55957:      * @param string $error_class The returned error object will be
                   55958:      *                  instantiated from this class, if specified.
                   55959:      *
                   55960:      * @param bool $skipmsg If true, raiseError will only pass error codes,
                   55961:      *                  the error message parameter will be dropped.
                   55962:      *
                   55963:      * @access public
                   55964:      * @return object   a PEAR error object
                   55965:      * @see PEAR::setErrorHandling
                   55966:      * @since PHP 4.0.5
                   55967:      */
                   55968:     function &raiseError($message = null,
                   55969:                          $code = null,
                   55970:                          $mode = null,
                   55971:                          $options = null,
                   55972:                          $userinfo = null,
                   55973:                          $error_class = null,
                   55974:                          $skipmsg = false)
                   55975:     {
                   55976:         // The error is yet a PEAR error object
                   55977:         if (is_object($message)) {
                   55978:             $code        = $message->getCode();
                   55979:             $userinfo    = $message->getUserInfo();
                   55980:             $error_class = $message->getType();
                   55981:             $message->error_message_prefix = '';
                   55982:             $message     = $message->getMessage();
                   55983:         }
                   55984: 
                   55985:         if (
                   55986:             isset($this) &&
                   55987:             isset($this->_expected_errors) &&
                   55988:             count($this->_expected_errors) > 0 &&
                   55989:             count($exp = end($this->_expected_errors))
                   55990:         ) {
                   55991:             if ($exp[0] == "*" ||
                   55992:                 (is_int(reset($exp)) && in_array($code, $exp)) ||
                   55993:                 (is_string(reset($exp)) && in_array($message, $exp))
                   55994:             ) {
                   55995:                 $mode = PEAR_ERROR_RETURN;
                   55996:             }
                   55997:         }
                   55998: 
                   55999:         // No mode given, try global ones
                   56000:         if ($mode === null) {
                   56001:             // Class error handler
                   56002:             if (isset($this) && isset($this->_default_error_mode)) {
                   56003:                 $mode    = $this->_default_error_mode;
                   56004:                 $options = $this->_default_error_options;
                   56005:             // Global error handler
                   56006:             } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
                   56007:                 $mode    = $GLOBALS['_PEAR_default_error_mode'];
                   56008:                 $options = $GLOBALS['_PEAR_default_error_options'];
                   56009:             }
                   56010:         }
                   56011: 
                   56012:         if ($error_class !== null) {
                   56013:             $ec = $error_class;
                   56014:         } elseif (isset($this) && isset($this->_error_class)) {
                   56015:             $ec = $this->_error_class;
                   56016:         } else {
                   56017:             $ec = 'PEAR_Error';
                   56018:         }
                   56019: 
                   56020:         if (intval(PHP_VERSION) < 5) {
                   56021:             // little non-eval hack to fix bug #12147
                   56022:             include 'phar://install-pear-nozlib.phar/' . 'PEAR/FixPHP5PEARWarnings.php';
                   56023:             return $a;
                   56024:         }
                   56025: 
                   56026:         if ($skipmsg) {
                   56027:             $a = new $ec($code, $mode, $options, $userinfo);
                   56028:         } else {
                   56029:             $a = new $ec($message, $code, $mode, $options, $userinfo);
                   56030:         }
                   56031: 
                   56032:         return $a;
                   56033:     }
                   56034: 
                   56035:     /**
                   56036:      * Simpler form of raiseError with fewer options.  In most cases
                   56037:      * message, code and userinfo are enough.
                   56038:      *
                   56039:      * @param mixed $message a text error message or a PEAR error object
                   56040:      *
                   56041:      * @param int $code      a numeric error code (it is up to your class
                   56042:      *                  to define these if you want to use codes)
                   56043:      *
                   56044:      * @param string $userinfo If you need to pass along for example debug
                   56045:      *                  information, this parameter is meant for that.
                   56046:      *
                   56047:      * @access public
                   56048:      * @return object   a PEAR error object
                   56049:      * @see PEAR::raiseError
                   56050:      */
                   56051:     function &throwError($message = null, $code = null, $userinfo = null)
                   56052:     {
                   56053:         if (isset($this) && is_a($this, 'PEAR')) {
                   56054:             $a = &$this->raiseError($message, $code, null, null, $userinfo);
                   56055:             return $a;
                   56056:         }
                   56057: 
                   56058:         $a = &PEAR::raiseError($message, $code, null, null, $userinfo);
                   56059:         return $a;
                   56060:     }
                   56061: 
                   56062:     function staticPushErrorHandling($mode, $options = null)
                   56063:     {
                   56064:         $stack       = &$GLOBALS['_PEAR_error_handler_stack'];
                   56065:         $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
                   56066:         $def_options = &$GLOBALS['_PEAR_default_error_options'];
                   56067:         $stack[] = array($def_mode, $def_options);
                   56068:         switch ($mode) {
                   56069:             case PEAR_ERROR_EXCEPTION:
                   56070:             case PEAR_ERROR_RETURN:
                   56071:             case PEAR_ERROR_PRINT:
                   56072:             case PEAR_ERROR_TRIGGER:
                   56073:             case PEAR_ERROR_DIE:
                   56074:             case null:
                   56075:                 $def_mode = $mode;
                   56076:                 $def_options = $options;
                   56077:                 break;
                   56078: 
                   56079:             case PEAR_ERROR_CALLBACK:
                   56080:                 $def_mode = $mode;
                   56081:                 // class/object method callback
                   56082:                 if (is_callable($options)) {
                   56083:                     $def_options = $options;
                   56084:                 } else {
                   56085:                     trigger_error("invalid error callback", E_USER_WARNING);
                   56086:                 }
                   56087:                 break;
                   56088: 
                   56089:             default:
                   56090:                 trigger_error("invalid error mode", E_USER_WARNING);
                   56091:                 break;
                   56092:         }
                   56093:         $stack[] = array($mode, $options);
                   56094:         return true;
                   56095:     }
                   56096: 
                   56097:     function staticPopErrorHandling()
                   56098:     {
                   56099:         $stack = &$GLOBALS['_PEAR_error_handler_stack'];
                   56100:         $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
                   56101:         $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
                   56102:         array_pop($stack);
                   56103:         list($mode, $options) = $stack[sizeof($stack) - 1];
                   56104:         array_pop($stack);
                   56105:         switch ($mode) {
                   56106:             case PEAR_ERROR_EXCEPTION:
                   56107:             case PEAR_ERROR_RETURN:
                   56108:             case PEAR_ERROR_PRINT:
                   56109:             case PEAR_ERROR_TRIGGER:
                   56110:             case PEAR_ERROR_DIE:
                   56111:             case null:
                   56112:                 $setmode = $mode;
                   56113:                 $setoptions = $options;
                   56114:                 break;
                   56115: 
                   56116:             case PEAR_ERROR_CALLBACK:
                   56117:                 $setmode = $mode;
                   56118:                 // class/object method callback
                   56119:                 if (is_callable($options)) {
                   56120:                     $setoptions = $options;
                   56121:                 } else {
                   56122:                     trigger_error("invalid error callback", E_USER_WARNING);
                   56123:                 }
                   56124:                 break;
                   56125: 
                   56126:             default:
                   56127:                 trigger_error("invalid error mode", E_USER_WARNING);
                   56128:                 break;
                   56129:         }
                   56130:         return true;
                   56131:     }
                   56132: 
                   56133:     /**
                   56134:      * Push a new error handler on top of the error handler options stack. With this
                   56135:      * you can easily override the actual error handler for some code and restore
                   56136:      * it later with popErrorHandling.
                   56137:      *
                   56138:      * @param mixed $mode (same as setErrorHandling)
                   56139:      * @param mixed $options (same as setErrorHandling)
                   56140:      *
                   56141:      * @return bool Always true
                   56142:      *
                   56143:      * @see PEAR::setErrorHandling
                   56144:      */
                   56145:     function pushErrorHandling($mode, $options = null)
                   56146:     {
                   56147:         $stack = &$GLOBALS['_PEAR_error_handler_stack'];
                   56148:         if (isset($this) && is_a($this, 'PEAR')) {
                   56149:             $def_mode    = &$this->_default_error_mode;
                   56150:             $def_options = &$this->_default_error_options;
                   56151:         } else {
                   56152:             $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
                   56153:             $def_options = &$GLOBALS['_PEAR_default_error_options'];
                   56154:         }
                   56155:         $stack[] = array($def_mode, $def_options);
                   56156: 
                   56157:         if (isset($this) && is_a($this, 'PEAR')) {
                   56158:             $this->setErrorHandling($mode, $options);
                   56159:         } else {
                   56160:             PEAR::setErrorHandling($mode, $options);
                   56161:         }
                   56162:         $stack[] = array($mode, $options);
                   56163:         return true;
                   56164:     }
                   56165: 
                   56166:     /**
                   56167:     * Pop the last error handler used
                   56168:     *
                   56169:     * @return bool Always true
                   56170:     *
                   56171:     * @see PEAR::pushErrorHandling
                   56172:     */
                   56173:     function popErrorHandling()
                   56174:     {
                   56175:         $stack = &$GLOBALS['_PEAR_error_handler_stack'];
                   56176:         array_pop($stack);
                   56177:         list($mode, $options) = $stack[sizeof($stack) - 1];
                   56178:         array_pop($stack);
                   56179:         if (isset($this) && is_a($this, 'PEAR')) {
                   56180:             $this->setErrorHandling($mode, $options);
                   56181:         } else {
                   56182:             PEAR::setErrorHandling($mode, $options);
                   56183:         }
                   56184:         return true;
                   56185:     }
                   56186: 
                   56187:     /**
                   56188:     * OS independant PHP extension load. Remember to take care
                   56189:     * on the correct extension name for case sensitive OSes.
                   56190:     *
                   56191:     * @param string $ext The extension name
                   56192:     * @return bool Success or not on the dl() call
                   56193:     */
                   56194:     function loadExtension($ext)
                   56195:     {
                   56196:         if (extension_loaded($ext)) {
                   56197:             return true;
                   56198:         }
                   56199: 
                   56200:         // if either returns true dl() will produce a FATAL error, stop that
                   56201:         if (
                   56202:             function_exists('dl') === false ||
                   56203:             ini_get('enable_dl') != 1 ||
                   56204:             ini_get('safe_mode') == 1
                   56205:         ) {
                   56206:             return false;
                   56207:         }
                   56208: 
                   56209:         if (OS_WINDOWS) {
                   56210:             $suffix = '.dll';
                   56211:         } elseif (PHP_OS == 'HP-UX') {
                   56212:             $suffix = '.sl';
                   56213:         } elseif (PHP_OS == 'AIX') {
                   56214:             $suffix = '.a';
                   56215:         } elseif (PHP_OS == 'OSX') {
                   56216:             $suffix = '.bundle';
                   56217:         } else {
                   56218:             $suffix = '.so';
                   56219:         }
                   56220: 
                   56221:         return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
                   56222:     }
                   56223: }
                   56224: 
                   56225: if (PEAR_ZE2) {
                   56226:     include_once 'phar://install-pear-nozlib.phar/' . 'PEAR5.php';
                   56227: }
                   56228: 
                   56229: function _PEAR_call_destructors()
                   56230: {
                   56231:     global $_PEAR_destructor_object_list;
                   56232:     if (is_array($_PEAR_destructor_object_list) &&
                   56233:         sizeof($_PEAR_destructor_object_list))
                   56234:     {
                   56235:         reset($_PEAR_destructor_object_list);
                   56236:         if (PEAR_ZE2) {
                   56237:             $destructLifoExists = PEAR5::getStaticProperty('PEAR', 'destructlifo');
                   56238:         } else {
                   56239:             $destructLifoExists = PEAR::getStaticProperty('PEAR', 'destructlifo');
                   56240:         }
                   56241: 
                   56242:         if ($destructLifoExists) {
                   56243:             $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
                   56244:         }
                   56245: 
                   56246:         while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
                   56247:             $classname = get_class($objref);
                   56248:             while ($classname) {
                   56249:                 $destructor = "_$classname";
                   56250:                 if (method_exists($objref, $destructor)) {
                   56251:                     $objref->$destructor();
                   56252:                     break;
                   56253:                 } else {
                   56254:                     $classname = get_parent_class($classname);
                   56255:                 }
                   56256:             }
                   56257:         }
                   56258:         // Empty the object list to ensure that destructors are
                   56259:         // not called more than once.
                   56260:         $_PEAR_destructor_object_list = array();
                   56261:     }
                   56262: 
                   56263:     // Now call the shutdown functions
                   56264:     if (
                   56265:         isset($GLOBALS['_PEAR_shutdown_funcs']) &&
                   56266:         is_array($GLOBALS['_PEAR_shutdown_funcs']) &&
                   56267:         !empty($GLOBALS['_PEAR_shutdown_funcs'])
                   56268:     ) {
                   56269:         foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
                   56270:             call_user_func_array($value[0], $value[1]);
                   56271:         }
                   56272:     }
                   56273: }
                   56274: 
                   56275: /**
                   56276:  * Standard PEAR error class for PHP 4
                   56277:  *
                   56278:  * This class is supserseded by {@link PEAR_Exception} in PHP 5
                   56279:  *
                   56280:  * @category   pear
                   56281:  * @package    PEAR
                   56282:  * @author     Stig Bakken <ssb@php.net>
                   56283:  * @author     Tomas V.V. Cox <cox@idecnet.com>
                   56284:  * @author     Gregory Beaver <cellog@php.net>
                   56285:  * @copyright  1997-2006 The PHP Group
                   56286:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    56287:  * @version    Release: 1.9.4
1.1       misho    56288:  * @link       http://pear.php.net/manual/en/core.pear.pear-error.php
                   56289:  * @see        PEAR::raiseError(), PEAR::throwError()
                   56290:  * @since      Class available since PHP 4.0.2
                   56291:  */
                   56292: class PEAR_Error
                   56293: {
                   56294:     var $error_message_prefix = '';
                   56295:     var $mode                 = PEAR_ERROR_RETURN;
                   56296:     var $level                = E_USER_NOTICE;
                   56297:     var $code                 = -1;
                   56298:     var $message              = '';
                   56299:     var $userinfo             = '';
                   56300:     var $backtrace            = null;
                   56301: 
                   56302:     /**
                   56303:      * PEAR_Error constructor
                   56304:      *
                   56305:      * @param string $message  message
                   56306:      *
                   56307:      * @param int $code     (optional) error code
                   56308:      *
                   56309:      * @param int $mode     (optional) error mode, one of: PEAR_ERROR_RETURN,
                   56310:      * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
                   56311:      * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
                   56312:      *
                   56313:      * @param mixed $options   (optional) error level, _OR_ in the case of
                   56314:      * PEAR_ERROR_CALLBACK, the callback function or object/method
                   56315:      * tuple.
                   56316:      *
                   56317:      * @param string $userinfo (optional) additional user/debug info
                   56318:      *
                   56319:      * @access public
                   56320:      *
                   56321:      */
                   56322:     function PEAR_Error($message = 'unknown error', $code = null,
                   56323:                         $mode = null, $options = null, $userinfo = null)
                   56324:     {
                   56325:         if ($mode === null) {
                   56326:             $mode = PEAR_ERROR_RETURN;
                   56327:         }
                   56328:         $this->message   = $message;
                   56329:         $this->code      = $code;
                   56330:         $this->mode      = $mode;
                   56331:         $this->userinfo  = $userinfo;
                   56332: 
                   56333:         if (PEAR_ZE2) {
                   56334:             $skiptrace = PEAR5::getStaticProperty('PEAR_Error', 'skiptrace');
                   56335:         } else {
                   56336:             $skiptrace = PEAR::getStaticProperty('PEAR_Error', 'skiptrace');
                   56337:         }
                   56338: 
                   56339:         if (!$skiptrace) {
                   56340:             $this->backtrace = debug_backtrace();
                   56341:             if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) {
                   56342:                 unset($this->backtrace[0]['object']);
                   56343:             }
                   56344:         }
                   56345: 
                   56346:         if ($mode & PEAR_ERROR_CALLBACK) {
                   56347:             $this->level = E_USER_NOTICE;
                   56348:             $this->callback = $options;
                   56349:         } else {
                   56350:             if ($options === null) {
                   56351:                 $options = E_USER_NOTICE;
                   56352:             }
                   56353: 
                   56354:             $this->level = $options;
                   56355:             $this->callback = null;
                   56356:         }
                   56357: 
                   56358:         if ($this->mode & PEAR_ERROR_PRINT) {
                   56359:             if (is_null($options) || is_int($options)) {
                   56360:                 $format = "%s";
                   56361:             } else {
                   56362:                 $format = $options;
                   56363:             }
                   56364: 
                   56365:             printf($format, $this->getMessage());
                   56366:         }
                   56367: 
                   56368:         if ($this->mode & PEAR_ERROR_TRIGGER) {
                   56369:             trigger_error($this->getMessage(), $this->level);
                   56370:         }
                   56371: 
                   56372:         if ($this->mode & PEAR_ERROR_DIE) {
                   56373:             $msg = $this->getMessage();
                   56374:             if (is_null($options) || is_int($options)) {
                   56375:                 $format = "%s";
                   56376:                 if (substr($msg, -1) != "\n") {
                   56377:                     $msg .= "\n";
                   56378:                 }
                   56379:             } else {
                   56380:                 $format = $options;
                   56381:             }
                   56382:             die(sprintf($format, $msg));
                   56383:         }
                   56384: 
                   56385:         if ($this->mode & PEAR_ERROR_CALLBACK && is_callable($this->callback)) {
                   56386:             call_user_func($this->callback, $this);
                   56387:         }
                   56388: 
                   56389:         if ($this->mode & PEAR_ERROR_EXCEPTION) {
                   56390:             trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING);
                   56391:             eval('$e = new Exception($this->message, $this->code);throw($e);');
                   56392:         }
                   56393:     }
                   56394: 
                   56395:     /**
                   56396:      * Get the error mode from an error object.
                   56397:      *
                   56398:      * @return int error mode
                   56399:      * @access public
                   56400:      */
                   56401:     function getMode()
                   56402:     {
                   56403:         return $this->mode;
                   56404:     }
                   56405: 
                   56406:     /**
                   56407:      * Get the callback function/method from an error object.
                   56408:      *
                   56409:      * @return mixed callback function or object/method array
                   56410:      * @access public
                   56411:      */
                   56412:     function getCallback()
                   56413:     {
                   56414:         return $this->callback;
                   56415:     }
                   56416: 
                   56417:     /**
                   56418:      * Get the error message from an error object.
                   56419:      *
                   56420:      * @return  string  full error message
                   56421:      * @access public
                   56422:      */
                   56423:     function getMessage()
                   56424:     {
                   56425:         return ($this->error_message_prefix . $this->message);
                   56426:     }
                   56427: 
                   56428:     /**
                   56429:      * Get error code from an error object
                   56430:      *
                   56431:      * @return int error code
                   56432:      * @access public
                   56433:      */
                   56434:      function getCode()
                   56435:      {
                   56436:         return $this->code;
                   56437:      }
                   56438: 
                   56439:     /**
                   56440:      * Get the name of this error/exception.
                   56441:      *
                   56442:      * @return string error/exception name (type)
                   56443:      * @access public
                   56444:      */
                   56445:     function getType()
                   56446:     {
                   56447:         return get_class($this);
                   56448:     }
                   56449: 
                   56450:     /**
                   56451:      * Get additional user-supplied information.
                   56452:      *
                   56453:      * @return string user-supplied information
                   56454:      * @access public
                   56455:      */
                   56456:     function getUserInfo()
                   56457:     {
                   56458:         return $this->userinfo;
                   56459:     }
                   56460: 
                   56461:     /**
                   56462:      * Get additional debug information supplied by the application.
                   56463:      *
                   56464:      * @return string debug information
                   56465:      * @access public
                   56466:      */
                   56467:     function getDebugInfo()
                   56468:     {
                   56469:         return $this->getUserInfo();
                   56470:     }
                   56471: 
                   56472:     /**
                   56473:      * Get the call backtrace from where the error was generated.
                   56474:      * Supported with PHP 4.3.0 or newer.
                   56475:      *
                   56476:      * @param int $frame (optional) what frame to fetch
                   56477:      * @return array Backtrace, or NULL if not available.
                   56478:      * @access public
                   56479:      */
                   56480:     function getBacktrace($frame = null)
                   56481:     {
                   56482:         if (defined('PEAR_IGNORE_BACKTRACE')) {
                   56483:             return null;
                   56484:         }
                   56485:         if ($frame === null) {
                   56486:             return $this->backtrace;
                   56487:         }
                   56488:         return $this->backtrace[$frame];
                   56489:     }
                   56490: 
                   56491:     function addUserInfo($info)
                   56492:     {
                   56493:         if (empty($this->userinfo)) {
                   56494:             $this->userinfo = $info;
                   56495:         } else {
                   56496:             $this->userinfo .= " ** $info";
                   56497:         }
                   56498:     }
                   56499: 
                   56500:     function __toString()
                   56501:     {
                   56502:         return $this->getMessage();
                   56503:     }
                   56504: 
                   56505:     /**
                   56506:      * Make a string representation of this object.
                   56507:      *
                   56508:      * @return string a string with an object summary
                   56509:      * @access public
                   56510:      */
                   56511:     function toString()
                   56512:     {
                   56513:         $modes = array();
                   56514:         $levels = array(E_USER_NOTICE  => 'notice',
                   56515:                         E_USER_WARNING => 'warning',
                   56516:                         E_USER_ERROR   => 'error');
                   56517:         if ($this->mode & PEAR_ERROR_CALLBACK) {
                   56518:             if (is_array($this->callback)) {
                   56519:                 $callback = (is_object($this->callback[0]) ?
                   56520:                     strtolower(get_class($this->callback[0])) :
                   56521:                     $this->callback[0]) . '::' .
                   56522:                     $this->callback[1];
                   56523:             } else {
                   56524:                 $callback = $this->callback;
                   56525:             }
                   56526:             return sprintf('[%s: message="%s" code=%d mode=callback '.
                   56527:                            'callback=%s prefix="%s" info="%s"]',
                   56528:                            strtolower(get_class($this)), $this->message, $this->code,
                   56529:                            $callback, $this->error_message_prefix,
                   56530:                            $this->userinfo);
                   56531:         }
                   56532:         if ($this->mode & PEAR_ERROR_PRINT) {
                   56533:             $modes[] = 'print';
                   56534:         }
                   56535:         if ($this->mode & PEAR_ERROR_TRIGGER) {
                   56536:             $modes[] = 'trigger';
                   56537:         }
                   56538:         if ($this->mode & PEAR_ERROR_DIE) {
                   56539:             $modes[] = 'die';
                   56540:         }
                   56541:         if ($this->mode & PEAR_ERROR_RETURN) {
                   56542:             $modes[] = 'return';
                   56543:         }
                   56544:         return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
                   56545:                        'prefix="%s" info="%s"]',
                   56546:                        strtolower(get_class($this)), $this->message, $this->code,
                   56547:                        implode("|", $modes), $levels[$this->level],
                   56548:                        $this->error_message_prefix,
                   56549:                        $this->userinfo);
                   56550:     }
                   56551: }
                   56552: 
                   56553: /*
                   56554:  * Local Variables:
                   56555:  * mode: php
                   56556:  * tab-width: 4
                   56557:  * c-basic-offset: 4
                   56558:  * End:
                   56559:  */
                   56560: <?php
                   56561: /**
1.1.1.2 ! misho    56562:  * Class auto-loader
1.1       misho    56563:  *
1.1.1.2 ! misho    56564:  * PHP versions 4
        !          56565: 
1.1       misho    56566:  *
                   56567:  * @category   pear
                   56568:  * @package    PEAR
1.1.1.2 ! misho    56569:  * @author     Stig Bakken <ssb@php.net>
1.1       misho    56570:  * @copyright  1997-2009 The Authors
                   56571:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    56572:  * @version    CVS: $Id: Autoloader.php 313023 2011-07-06 19:17:11Z dufuz $
        !          56573:  * @link       http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader
        !          56574:  * @since      File available since Release 0.1
        !          56575:  * @deprecated File deprecated in Release 1.4.0a1
1.1       misho    56576:  */
                   56577: 
1.1.1.2 ! misho    56578: // /* vim: set expandtab tabstop=4 shiftwidth=4: */
1.1       misho    56579: 
1.1.1.2 ! misho    56580: if (!extension_loaded("overload")) {
        !          56581:     // die hard without ext/overload
        !          56582:     die("Rebuild PHP with the `overload' extension to use PEAR_Autoloader");
        !          56583: }
1.1       misho    56584: 
                   56585: /**
1.1.1.2 ! misho    56586:  * Include for PEAR_Error and PEAR classes
1.1       misho    56587:  */
1.1.1.2 ! misho    56588: require_once 'phar://install-pear-nozlib.phar/' . "PEAR.php";
1.1       misho    56589: 
                   56590: /**
1.1.1.2 ! misho    56591:  * This class is for objects where you want to separate the code for
        !          56592:  * some methods into separate classes.  This is useful if you have a
        !          56593:  * class with not-frequently-used methods that contain lots of code
        !          56594:  * that you would like to avoid always parsing.
        !          56595:  *
        !          56596:  * The PEAR_Autoloader class provides autoloading and aggregation.
        !          56597:  * The autoloading lets you set up in which classes the separated
        !          56598:  * methods are found.  Aggregation is the technique used to import new
        !          56599:  * methods, an instance of each class providing separated methods is
        !          56600:  * stored and called every time the aggregated method is called.
1.1       misho    56601:  *
                   56602:  * @category   pear
                   56603:  * @package    PEAR
1.1.1.2 ! misho    56604:  * @author Stig Bakken <ssb@php.net>
1.1       misho    56605:  * @copyright  1997-2009 The Authors
                   56606:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    56607:  * @version    Release: 1.9.4
        !          56608:  * @link       http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader
        !          56609:  * @since      File available since Release 0.1
        !          56610:  * @deprecated File deprecated in Release 1.4.0a1
1.1       misho    56611:  */
1.1.1.2 ! misho    56612: class PEAR_Autoloader extends PEAR
1.1       misho    56613: {
1.1.1.2 ! misho    56614:     // {{{ properties
1.1       misho    56615: 
                   56616:     /**
1.1.1.2 ! misho    56617:      * Map of methods and classes where they are defined
        !          56618:      *
1.1       misho    56619:      * @var array
1.1.1.2 ! misho    56620:      *
1.1       misho    56621:      * @access private
                   56622:      */
1.1.1.2 ! misho    56623:     var $_autoload_map = array();
1.1       misho    56624: 
                   56625:     /**
1.1.1.2 ! misho    56626:      * Map of methods and aggregate objects
        !          56627:      *
1.1       misho    56628:      * @var array
1.1.1.2 ! misho    56629:      *
1.1       misho    56630:      * @access private
                   56631:      */
1.1.1.2 ! misho    56632:     var $_method_map = array();
1.1       misho    56633: 
1.1.1.2 ! misho    56634:     // }}}
        !          56635:     // {{{ addAutoload()
1.1       misho    56636: 
                   56637:     /**
1.1.1.2 ! misho    56638:      * Add one or more autoload entries.
        !          56639:      *
        !          56640:      * @param string $method     which method to autoload
        !          56641:      *
        !          56642:      * @param string $classname  (optional) which class to find the method in.
        !          56643:      *                           If the $method parameter is an array, this
        !          56644:      *                           parameter may be omitted (and will be ignored
        !          56645:      *                           if not), and the $method parameter will be
        !          56646:      *                           treated as an associative array with method
        !          56647:      *                           names as keys and class names as values.
        !          56648:      *
        !          56649:      * @return void
        !          56650:      *
        !          56651:      * @access public
1.1       misho    56652:      */
1.1.1.2 ! misho    56653:     function addAutoload($method, $classname = null)
1.1       misho    56654:     {
1.1.1.2 ! misho    56655:         if (is_array($method)) {
        !          56656:             array_walk($method, create_function('$a,&$b', '$b = strtolower($b);'));
        !          56657:             $this->_autoload_map = array_merge($this->_autoload_map, $method);
        !          56658:         } else {
        !          56659:             $this->_autoload_map[strtolower($method)] = $classname;
        !          56660:         }
1.1       misho    56661:     }
                   56662: 
1.1.1.2 ! misho    56663:     // }}}
        !          56664:     // {{{ removeAutoload()
        !          56665: 
1.1       misho    56666:     /**
1.1.1.2 ! misho    56667:      * Remove an autoload entry.
        !          56668:      *
        !          56669:      * @param string $method  which method to remove the autoload entry for
        !          56670:      *
        !          56671:      * @return bool TRUE if an entry was removed, FALSE if not
        !          56672:      *
        !          56673:      * @access public
1.1       misho    56674:      */
1.1.1.2 ! misho    56675:     function removeAutoload($method)
1.1       misho    56676:     {
1.1.1.2 ! misho    56677:         $method = strtolower($method);
        !          56678:         $ok = isset($this->_autoload_map[$method]);
        !          56679:         unset($this->_autoload_map[$method]);
        !          56680:         return $ok;
1.1       misho    56681:     }
                   56682: 
1.1.1.2 ! misho    56683:     // }}}
        !          56684:     // {{{ addAggregateObject()
        !          56685: 
1.1       misho    56686:     /**
1.1.1.2 ! misho    56687:      * Add an aggregate object to this object.  If the specified class
        !          56688:      * is not defined, loading it will be attempted following PEAR's
        !          56689:      * file naming scheme.  All the methods in the class will be
        !          56690:      * aggregated, except private ones (name starting with an
        !          56691:      * underscore) and constructors.
        !          56692:      *
        !          56693:      * @param string $classname  what class to instantiate for the object.
        !          56694:      *
        !          56695:      * @return void
        !          56696:      *
        !          56697:      * @access public
1.1       misho    56698:      */
1.1.1.2 ! misho    56699:     function addAggregateObject($classname)
1.1       misho    56700:     {
1.1.1.2 ! misho    56701:         $classname = strtolower($classname);
        !          56702:         if (!class_exists($classname)) {
        !          56703:             $include_file = preg_replace('/[^a-z0-9]/i', '_', $classname);
        !          56704:             include_once 'phar://install-pear-nozlib.phar/' . $include_file;
        !          56705:         }
        !          56706:         $obj =& new $classname;
        !          56707:         $methods = get_class_methods($classname);
        !          56708:         foreach ($methods as $method) {
        !          56709:             // don't import priviate methods and constructors
        !          56710:             if ($method{0} != '_' && $method != $classname) {
        !          56711:                 $this->_method_map[$method] = $obj;
1.1       misho    56712:             }
                   56713:         }
                   56714:     }
                   56715: 
1.1.1.2 ! misho    56716:     // }}}
        !          56717:     // {{{ removeAggregateObject()
        !          56718: 
1.1       misho    56719:     /**
1.1.1.2 ! misho    56720:      * Remove an aggregate object.
        !          56721:      *
        !          56722:      * @param string $classname  the class of the object to remove
        !          56723:      *
        !          56724:      * @return bool  TRUE if an object was removed, FALSE if not
        !          56725:      *
        !          56726:      * @access public
1.1       misho    56727:      */
1.1.1.2 ! misho    56728:     function removeAggregateObject($classname)
1.1       misho    56729:     {
1.1.1.2 ! misho    56730:         $ok = false;
        !          56731:         $classname = strtolower($classname);
        !          56732:         reset($this->_method_map);
        !          56733:         while (list($method, $obj) = each($this->_method_map)) {
        !          56734:             if (is_a($obj, $classname)) {
        !          56735:                 unset($this->_method_map[$method]);
        !          56736:                 $ok = true;
        !          56737:             }
1.1       misho    56738:         }
1.1.1.2 ! misho    56739:         return $ok;
1.1       misho    56740:     }
                   56741: 
1.1.1.2 ! misho    56742:     // }}}
        !          56743:     // {{{ __call()
        !          56744: 
1.1       misho    56745:     /**
1.1.1.2 ! misho    56746:      * Overloaded object call handler, called each time an
        !          56747:      * undefined/aggregated method is invoked.  This method repeats
        !          56748:      * the call in the right aggregate object and passes on the return
        !          56749:      * value.
        !          56750:      *
        !          56751:      * @param string $method  which method that was called
        !          56752:      *
        !          56753:      * @param string $args    An array of the parameters passed in the
        !          56754:      *                        original call
        !          56755:      *
        !          56756:      * @return mixed  The return value from the aggregated method, or a PEAR
        !          56757:      *                error if the called method was unknown.
1.1       misho    56758:      */
1.1.1.2 ! misho    56759:     function __call($method, $args, &$retval)
1.1       misho    56760:     {
1.1.1.2 ! misho    56761:         $method = strtolower($method);
        !          56762:         if (empty($this->_method_map[$method]) && isset($this->_autoload_map[$method])) {
        !          56763:             $this->addAggregateObject($this->_autoload_map[$method]);
1.1       misho    56764:         }
1.1.1.2 ! misho    56765:         if (isset($this->_method_map[$method])) {
        !          56766:             $retval = call_user_func_array(array($this->_method_map[$method], $method), $args);
        !          56767:             return true;
        !          56768:         }
        !          56769:         return false;
1.1       misho    56770:     }
                   56771: 
1.1.1.2 ! misho    56772:     // }}}
        !          56773: }
1.1       misho    56774: 
1.1.1.2 ! misho    56775: overload("PEAR_Autoloader");
1.1       misho    56776: 
1.1.1.2 ! misho    56777: ?>
        !          56778: <?php
        !          56779: /**
        !          56780:  * PEAR_Builder for building PHP extensions (PECL packages)
        !          56781:  *
        !          56782:  * PHP versions 4 and 5
        !          56783:  *
        !          56784:  * @category   pear
        !          56785:  * @package    PEAR
        !          56786:  * @author     Stig Bakken <ssb@php.net>
        !          56787:  * @author     Greg Beaver <cellog@php.net>
        !          56788:  * @copyright  1997-2009 The Authors
        !          56789:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          56790:  * @version    CVS: $Id: Builder.php 313024 2011-07-06 19:51:24Z dufuz $
        !          56791:  * @link       http://pear.php.net/package/PEAR
        !          56792:  * @since      File available since Release 0.1
        !          56793:  *
        !          56794:  * TODO: log output parameters in PECL command line
        !          56795:  * TODO: msdev path in configuration
        !          56796:  */
1.1       misho    56797: 
1.1.1.2 ! misho    56798: /**
        !          56799:  * Needed for extending PEAR_Builder
        !          56800:  */
        !          56801: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
        !          56802: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile.php';
        !          56803: 
        !          56804: /**
        !          56805:  * Class to handle building (compiling) extensions.
        !          56806:  *
        !          56807:  * @category   pear
        !          56808:  * @package    PEAR
        !          56809:  * @author     Stig Bakken <ssb@php.net>
        !          56810:  * @author     Greg Beaver <cellog@php.net>
        !          56811:  * @copyright  1997-2009 The Authors
        !          56812:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          56813:  * @version    Release: 1.9.4
        !          56814:  * @link       http://pear.php.net/package/PEAR
        !          56815:  * @since      Class available since PHP 4.0.2
        !          56816:  * @see        http://pear.php.net/manual/en/core.ppm.pear-builder.php
        !          56817:  */
        !          56818: class PEAR_Builder extends PEAR_Common
        !          56819: {
        !          56820:     var $php_api_version = 0;
        !          56821:     var $zend_module_api_no = 0;
        !          56822:     var $zend_extension_api_no = 0;
        !          56823: 
        !          56824:     var $extensions_built = array();
1.1       misho    56825: 
                   56826:     /**
1.1.1.2 ! misho    56827:      * @var string Used for reporting when it is not possible to pass function
        !          56828:      *             via extra parameter, e.g. log, msdevCallback
1.1       misho    56829:      */
1.1.1.2 ! misho    56830:     var $current_callback = null;
1.1       misho    56831: 
1.1.1.2 ! misho    56832:     // used for msdev builds
        !          56833:     var $_lastline = null;
        !          56834:     var $_firstline = null;
1.1       misho    56835: 
                   56836:     /**
1.1.1.2 ! misho    56837:      * PEAR_Builder constructor.
1.1       misho    56838:      *
1.1.1.2 ! misho    56839:      * @param object $ui user interface object (instance of PEAR_Frontend_*)
1.1       misho    56840:      *
                   56841:      * @access public
                   56842:      */
1.1.1.2 ! misho    56843:     function PEAR_Builder(&$ui)
1.1       misho    56844:     {
1.1.1.2 ! misho    56845:         parent::PEAR_Common();
        !          56846:         $this->setFrontendObject($ui);
1.1       misho    56847:     }
                   56848: 
                   56849:     /**
1.1.1.2 ! misho    56850:      * Build an extension from source on windows.
        !          56851:      * requires msdev
1.1       misho    56852:      */
1.1.1.2 ! misho    56853:     function _build_win32($descfile, $callback = null)
1.1       misho    56854:     {
1.1.1.2 ! misho    56855:         if (is_object($descfile)) {
        !          56856:             $pkg = $descfile;
        !          56857:             $descfile = $pkg->getPackageFile();
        !          56858:         } else {
        !          56859:             $pf = &new PEAR_PackageFile($this->config, $this->debug);
        !          56860:             $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
        !          56861:             if (PEAR::isError($pkg)) {
        !          56862:                 return $pkg;
        !          56863:             }
1.1       misho    56864:         }
1.1.1.2 ! misho    56865:         $dir = dirname($descfile);
        !          56866:         $old_cwd = getcwd();
        !          56867: 
        !          56868:         if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) {
        !          56869:             return $this->raiseError("could not chdir to $dir");
1.1       misho    56870:         }
1.1.1.2 ! misho    56871: 
        !          56872:         // packages that were in a .tar have the packagefile in this directory
        !          56873:         $vdir = $pkg->getPackage() . '-' . $pkg->getVersion();
        !          56874:         if (file_exists($dir) && is_dir($vdir)) {
        !          56875:             if (!chdir($vdir)) {
        !          56876:                 return $this->raiseError("could not chdir to " . realpath($vdir));
        !          56877:             }
        !          56878: 
        !          56879:             $dir = getcwd();
1.1       misho    56880:         }
1.1.1.2 ! misho    56881: 
        !          56882:         $this->log(2, "building in $dir");
        !          56883: 
        !          56884:         $dsp = $pkg->getPackage().'.dsp';
        !          56885:         if (!file_exists("$dir/$dsp")) {
        !          56886:             return $this->raiseError("The DSP $dsp does not exist.");
1.1       misho    56887:         }
1.1.1.2 ! misho    56888:         // XXX TODO: make release build type configurable
        !          56889:         $command = 'msdev '.$dsp.' /MAKE "'.$pkg->getPackage(). ' - Release"';
        !          56890: 
        !          56891:         $err = $this->_runCommand($command, array(&$this, 'msdevCallback'));
        !          56892:         if (PEAR::isError($err)) {
        !          56893:             return $err;
1.1       misho    56894:         }
1.1.1.2 ! misho    56895: 
        !          56896:         // figure out the build platform and type
        !          56897:         $platform = 'Win32';
        !          56898:         $buildtype = 'Release';
        !          56899:         if (preg_match('/.*?'.$pkg->getPackage().'\s-\s(\w+)\s(.*?)-+/i',$this->_firstline,$matches)) {
        !          56900:             $platform = $matches[1];
        !          56901:             $buildtype = $matches[2];
1.1       misho    56902:         }
1.1.1.2 ! misho    56903: 
        !          56904:         if (preg_match('/(.*)?\s-\s(\d+).*?(\d+)/', $this->_lastline, $matches)) {
        !          56905:             if ($matches[2]) {
        !          56906:                 // there were errors in the build
        !          56907:                 return $this->raiseError("There were errors during compilation.");
        !          56908:             }
        !          56909:             $out = $matches[1];
        !          56910:         } else {
        !          56911:             return $this->raiseError("Did not understand the completion status returned from msdev.exe.");
1.1       misho    56912:         }
1.1.1.2 ! misho    56913: 
        !          56914:         // msdev doesn't tell us the output directory :/
        !          56915:         // open the dsp, find /out and use that directory
        !          56916:         $dsptext = join(file($dsp),'');
        !          56917: 
        !          56918:         // this regex depends on the build platform and type having been
        !          56919:         // correctly identified above.
        !          56920:         $regex ='/.*?!IF\s+"\$\(CFG\)"\s+==\s+("'.
        !          56921:                     $pkg->getPackage().'\s-\s'.
        !          56922:                     $platform.'\s'.
        !          56923:                     $buildtype.'").*?'.
        !          56924:                     '\/out:"(.*?)"/is';
        !          56925: 
        !          56926:         if ($dsptext && preg_match($regex, $dsptext, $matches)) {
        !          56927:             // what we get back is a relative path to the output file itself.
        !          56928:             $outfile = realpath($matches[2]);
        !          56929:         } else {
        !          56930:             return $this->raiseError("Could not retrieve output information from $dsp.");
1.1       misho    56931:         }
1.1.1.2 ! misho    56932:         // realpath returns false if the file doesn't exist
        !          56933:         if ($outfile && copy($outfile, "$dir/$out")) {
        !          56934:             $outfile = "$dir/$out";
        !          56935:         }
        !          56936: 
        !          56937:         $built_files[] = array(
        !          56938:             'file' => "$outfile",
        !          56939:             'php_api' => $this->php_api_version,
        !          56940:             'zend_mod_api' => $this->zend_module_api_no,
        !          56941:             'zend_ext_api' => $this->zend_extension_api_no,
        !          56942:             );
        !          56943: 
        !          56944:         return $built_files;
        !          56945:     }
        !          56946:     // }}}
        !          56947: 
        !          56948:     // {{{ msdevCallback()
        !          56949:     function msdevCallback($what, $data)
        !          56950:     {
        !          56951:         if (!$this->_firstline)
        !          56952:             $this->_firstline = $data;
        !          56953:         $this->_lastline = $data;
        !          56954:         call_user_func($this->current_callback, $what, $data);
1.1       misho    56955:     }
                   56956: 
                   56957:     /**
1.1.1.2 ! misho    56958:      * @param string
        !          56959:      * @param string
        !          56960:      * @param array
1.1       misho    56961:      * @access private
                   56962:      */
1.1.1.2 ! misho    56963:     function _harvestInstDir($dest_prefix, $dirname, &$built_files)
1.1       misho    56964:     {
1.1.1.2 ! misho    56965:         $d = opendir($dirname);
        !          56966:         if (!$d)
        !          56967:             return false;
1.1       misho    56968: 
1.1.1.2 ! misho    56969:         $ret = true;
        !          56970:         while (($ent = readdir($d)) !== false) {
        !          56971:             if ($ent{0} == '.')
        !          56972:                 continue;
        !          56973: 
        !          56974:             $full = $dirname . DIRECTORY_SEPARATOR . $ent;
        !          56975:             if (is_dir($full)) {
        !          56976:                 if (!$this->_harvestInstDir(
        !          56977:                         $dest_prefix . DIRECTORY_SEPARATOR . $ent,
        !          56978:                         $full, $built_files)) {
        !          56979:                     $ret = false;
        !          56980:                     break;
        !          56981:                 }
        !          56982:             } else {
        !          56983:                 $dest = $dest_prefix . DIRECTORY_SEPARATOR . $ent;
        !          56984:                 $built_files[] = array(
        !          56985:                         'file' => $full,
        !          56986:                         'dest' => $dest,
        !          56987:                         'php_api' => $this->php_api_version,
        !          56988:                         'zend_mod_api' => $this->zend_module_api_no,
        !          56989:                         'zend_ext_api' => $this->zend_extension_api_no,
        !          56990:                         );
1.1       misho    56991:             }
                   56992:         }
1.1.1.2 ! misho    56993:         closedir($d);
1.1       misho    56994:         return $ret;
                   56995:     }
                   56996: 
                   56997:     /**
1.1.1.2 ! misho    56998:      * Build an extension from source.  Runs "phpize" in the source
        !          56999:      * directory, but compiles in a temporary directory
        !          57000:      * (TMPDIR/pear-build-USER/PACKAGE-VERSION).
        !          57001:      *
        !          57002:      * @param string|PEAR_PackageFile_v* $descfile path to XML package description file, or
        !          57003:      *               a PEAR_PackageFile object
        !          57004:      *
        !          57005:      * @param mixed $callback callback function used to report output,
        !          57006:      * see PEAR_Builder::_runCommand for details
        !          57007:      *
        !          57008:      * @return array an array of associative arrays with built files,
        !          57009:      * format:
        !          57010:      * array( array( 'file' => '/path/to/ext.so',
        !          57011:      *               'php_api' => YYYYMMDD,
        !          57012:      *               'zend_mod_api' => YYYYMMDD,
        !          57013:      *               'zend_ext_api' => YYYYMMDD ),
        !          57014:      *        ... )
1.1       misho    57015:      *
                   57016:      * @access public
1.1.1.2 ! misho    57017:      *
        !          57018:      * @see PEAR_Builder::_runCommand
1.1       misho    57019:      */
1.1.1.2 ! misho    57020:     function build($descfile, $callback = null)
1.1       misho    57021:     {
1.1.1.2 ! misho    57022:         if (preg_match('/(\\/|\\\\|^)([^\\/\\\\]+)?php(.+)?$/',
        !          57023:                        $this->config->get('php_bin'), $matches)) {
        !          57024:             if (isset($matches[2]) && strlen($matches[2]) &&
        !          57025:                 trim($matches[2]) != trim($this->config->get('php_prefix'))) {
        !          57026:                 $this->log(0, 'WARNING: php_bin ' . $this->config->get('php_bin') .
        !          57027:                            ' appears to have a prefix ' . $matches[2] . ', but' .
        !          57028:                            ' config variable php_prefix does not match');
1.1       misho    57029:             }
1.1.1.2 ! misho    57030: 
        !          57031:             if (isset($matches[3]) && strlen($matches[3]) &&
        !          57032:                 trim($matches[3]) != trim($this->config->get('php_suffix'))) {
        !          57033:                 $this->log(0, 'WARNING: php_bin ' . $this->config->get('php_bin') .
        !          57034:                            ' appears to have a suffix ' . $matches[3] . ', but' .
        !          57035:                            ' config variable php_suffix does not match');
1.1       misho    57036:             }
                   57037:         }
                   57038: 
1.1.1.2 ! misho    57039:         $this->current_callback = $callback;
        !          57040:         if (PEAR_OS == "Windows") {
        !          57041:             return $this->_build_win32($descfile, $callback);
1.1       misho    57042:         }
                   57043: 
1.1.1.2 ! misho    57044:         if (PEAR_OS != 'Unix') {
        !          57045:             return $this->raiseError("building extensions not supported on this platform");
1.1       misho    57046:         }
                   57047: 
1.1.1.2 ! misho    57048:         if (is_object($descfile)) {
        !          57049:             $pkg = $descfile;
        !          57050:             $descfile = $pkg->getPackageFile();
        !          57051:             if (is_a($pkg, 'PEAR_PackageFile_v1')) {
        !          57052:                 $dir = dirname($descfile);
        !          57053:             } else {
        !          57054:                 $dir = $pkg->_config->get('temp_dir') . '/' . $pkg->getName();
        !          57055:                 // automatically delete at session end
        !          57056:                 $this->addTempFile($dir);
1.1       misho    57057:             }
1.1.1.2 ! misho    57058:         } else {
        !          57059:             $pf = &new PEAR_PackageFile($this->config);
        !          57060:             $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
        !          57061:             if (PEAR::isError($pkg)) {
        !          57062:                 return $pkg;
1.1       misho    57063:             }
1.1.1.2 ! misho    57064:             $dir = dirname($descfile);
1.1       misho    57065:         }
                   57066: 
1.1.1.2 ! misho    57067:         // Find config. outside of normal path - e.g. config.m4
        !          57068:         foreach (array_keys($pkg->getInstallationFileList()) as $item) {
        !          57069:           if (stristr(basename($item), 'config.m4') && dirname($item) != '.') {
        !          57070:             $dir .= DIRECTORY_SEPARATOR . dirname($item);
        !          57071:             break;
        !          57072:           }
1.1       misho    57073:         }
                   57074: 
1.1.1.2 ! misho    57075:         $old_cwd = getcwd();
        !          57076:         if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) {
        !          57077:             return $this->raiseError("could not chdir to $dir");
1.1       misho    57078:         }
                   57079: 
1.1.1.2 ! misho    57080:         $vdir = $pkg->getPackage() . '-' . $pkg->getVersion();
        !          57081:         if (is_dir($vdir)) {
        !          57082:             chdir($vdir);
1.1       misho    57083:         }
                   57084: 
1.1.1.2 ! misho    57085:         $dir = getcwd();
        !          57086:         $this->log(2, "building in $dir");
        !          57087:         putenv('PATH=' . $this->config->get('bin_dir') . ':' . getenv('PATH'));
        !          57088:         $err = $this->_runCommand($this->config->get('php_prefix')
        !          57089:                                 . "phpize" .
        !          57090:                                 $this->config->get('php_suffix'),
        !          57091:                                 array(&$this, 'phpizeCallback'));
        !          57092:         if (PEAR::isError($err)) {
        !          57093:             return $err;
1.1       misho    57094:         }
                   57095: 
1.1.1.2 ! misho    57096:         if (!$err) {
        !          57097:             return $this->raiseError("`phpize' failed");
1.1       misho    57098:         }
                   57099: 
1.1.1.2 ! misho    57100:         // {{{ start of interactive part
        !          57101:         $configure_command = "$dir/configure";
        !          57102:         $configure_options = $pkg->getConfigureOptions();
        !          57103:         if ($configure_options) {
        !          57104:             foreach ($configure_options as $o) {
        !          57105:                 $default = array_key_exists('default', $o) ? $o['default'] : null;
        !          57106:                 list($r) = $this->ui->userDialog('build',
        !          57107:                                                  array($o['prompt']),
        !          57108:                                                  array('text'),
        !          57109:                                                  array($default));
        !          57110:                 if (substr($o['name'], 0, 5) == 'with-' &&
        !          57111:                     ($r == 'yes' || $r == 'autodetect')) {
        !          57112:                     $configure_command .= " --$o[name]";
        !          57113:                 } else {
        !          57114:                     $configure_command .= " --$o[name]=".trim($r);
1.1       misho    57115:                 }
                   57116:             }
1.1.1.2 ! misho    57117:         }
        !          57118:         // }}} end of interactive part
1.1       misho    57119: 
1.1.1.2 ! misho    57120:         // FIXME make configurable
        !          57121:         if (!$user=getenv('USER')) {
        !          57122:             $user='defaultuser';
1.1       misho    57123:         }
                   57124: 
1.1.1.2 ! misho    57125:         $tmpdir = $this->config->get('temp_dir');
        !          57126:         $build_basedir = System::mktemp(' -t "' . $tmpdir . '" -d "pear-build-' . $user . '"');
        !          57127:         $build_dir = "$build_basedir/$vdir";
        !          57128:         $inst_dir = "$build_basedir/install-$vdir";
        !          57129:         $this->log(1, "building in $build_dir");
        !          57130:         if (is_dir($build_dir)) {
        !          57131:             System::rm(array('-rf', $build_dir));
1.1       misho    57132:         }
                   57133: 
1.1.1.2 ! misho    57134:         if (!System::mkDir(array('-p', $build_dir))) {
        !          57135:             return $this->raiseError("could not create build dir: $build_dir");
1.1       misho    57136:         }
                   57137: 
1.1.1.2 ! misho    57138:         $this->addTempFile($build_dir);
        !          57139:         if (!System::mkDir(array('-p', $inst_dir))) {
        !          57140:             return $this->raiseError("could not create temporary install dir: $inst_dir");
        !          57141:         }
        !          57142:         $this->addTempFile($inst_dir);
1.1       misho    57143: 
1.1.1.2 ! misho    57144:         $make_command = getenv('MAKE') ? getenv('MAKE') : 'make';
1.1       misho    57145: 
1.1.1.2 ! misho    57146:         $to_run = array(
        !          57147:             $configure_command,
        !          57148:             $make_command,
        !          57149:             "$make_command INSTALL_ROOT=\"$inst_dir\" install",
        !          57150:             "find \"$inst_dir\" | xargs ls -dils"
        !          57151:             );
        !          57152:         if (!file_exists($build_dir) || !is_dir($build_dir) || !chdir($build_dir)) {
        !          57153:             return $this->raiseError("could not chdir to $build_dir");
        !          57154:         }
        !          57155:         putenv('PHP_PEAR_VERSION=1.9.4');
        !          57156:         foreach ($to_run as $cmd) {
        !          57157:             $err = $this->_runCommand($cmd, $callback);
        !          57158:             if (PEAR::isError($err)) {
        !          57159:                 chdir($old_cwd);
        !          57160:                 return $err;
        !          57161:             }
        !          57162:             if (!$err) {
        !          57163:                 chdir($old_cwd);
        !          57164:                 return $this->raiseError("`$cmd' failed");
1.1       misho    57165:             }
                   57166:         }
1.1.1.2 ! misho    57167:         if (!($dp = opendir("modules"))) {
        !          57168:             chdir($old_cwd);
        !          57169:             return $this->raiseError("no `modules' directory found");
1.1       misho    57170:         }
1.1.1.2 ! misho    57171:         $built_files = array();
        !          57172:         $prefix = exec($this->config->get('php_prefix')
        !          57173:                         . "php-config" .
        !          57174:                        $this->config->get('php_suffix') . " --prefix");
        !          57175:         $this->_harvestInstDir($prefix, $inst_dir . DIRECTORY_SEPARATOR . $prefix, $built_files);
        !          57176:         chdir($old_cwd);
        !          57177:         return $built_files;
1.1       misho    57178:     }
                   57179: 
                   57180:     /**
1.1.1.2 ! misho    57181:      * Message callback function used when running the "phpize"
        !          57182:      * program.  Extracts the API numbers used.  Ignores other message
        !          57183:      * types than "cmdoutput".
        !          57184:      *
        !          57185:      * @param string $what the type of message
        !          57186:      * @param mixed $data the message
        !          57187:      *
        !          57188:      * @return void
        !          57189:      *
        !          57190:      * @access public
1.1       misho    57191:      */
1.1.1.2 ! misho    57192:     function phpizeCallback($what, $data)
1.1       misho    57193:     {
1.1.1.2 ! misho    57194:         if ($what != 'cmdoutput') {
        !          57195:             return;
        !          57196:         }
        !          57197:         $this->log(1, rtrim($data));
        !          57198:         if (preg_match('/You should update your .aclocal.m4/', $data)) {
        !          57199:             return;
        !          57200:         }
        !          57201:         $matches = array();
        !          57202:         if (preg_match('/^\s+(\S[^:]+):\s+(\d{8})/', $data, $matches)) {
        !          57203:             $member = preg_replace('/[^a-z]/', '_', strtolower($matches[1]));
        !          57204:             $apino = (int)$matches[2];
        !          57205:             if (isset($this->$member)) {
        !          57206:                 $this->$member = $apino;
        !          57207:                 //$msg = sprintf("%-22s : %d", $matches[1], $apino);
        !          57208:                 //$this->log(1, $msg);
        !          57209:             }
1.1       misho    57210:         }
                   57211:     }
                   57212: 
                   57213:     /**
1.1.1.2 ! misho    57214:      * Run an external command, using a message callback to report
        !          57215:      * output.  The command will be run through popen and output is
        !          57216:      * reported for every line with a "cmdoutput" message with the
        !          57217:      * line string, including newlines, as payload.
        !          57218:      *
        !          57219:      * @param string $command the command to run
        !          57220:      *
        !          57221:      * @param mixed $callback (optional) function to use as message
        !          57222:      * callback
        !          57223:      *
        !          57224:      * @return bool whether the command was successful (exit code 0
        !          57225:      * means success, any other means failure)
        !          57226:      *
        !          57227:      * @access private
1.1       misho    57228:      */
1.1.1.2 ! misho    57229:     function _runCommand($command, $callback = null)
1.1       misho    57230:     {
1.1.1.2 ! misho    57231:         $this->log(1, "running: $command");
        !          57232:         $pp = popen("$command 2>&1", "r");
        !          57233:         if (!$pp) {
        !          57234:             return $this->raiseError("failed to run `$command'");
        !          57235:         }
        !          57236:         if ($callback && $callback[0]->debug == 1) {
        !          57237:             $olddbg = $callback[0]->debug;
        !          57238:             $callback[0]->debug = 2;
1.1       misho    57239:         }
                   57240: 
1.1.1.2 ! misho    57241:         while ($line = fgets($pp, 1024)) {
        !          57242:             if ($callback) {
        !          57243:                 call_user_func($callback, 'cmdoutput', $line);
        !          57244:             } else {
        !          57245:                 $this->log(2, rtrim($line));
1.1       misho    57246:             }
                   57247:         }
1.1.1.2 ! misho    57248:         if ($callback && isset($olddbg)) {
        !          57249:             $callback[0]->debug = $olddbg;
1.1       misho    57250:         }
                   57251: 
1.1.1.2 ! misho    57252:         $exitcode = is_resource($pp) ? pclose($pp) : -1;
        !          57253:         return ($exitcode == 0);
1.1       misho    57254:     }
                   57255: 
1.1.1.2 ! misho    57256:     function log($level, $msg)
        !          57257:     {
        !          57258:         if ($this->current_callback) {
        !          57259:             if ($this->debug >= $level) {
        !          57260:                 call_user_func($this->current_callback, 'output', $msg);
1.1       misho    57261:             }
1.1.1.2 ! misho    57262:             return;
1.1       misho    57263:         }
1.1.1.2 ! misho    57264:         return PEAR_Common::log($level, $msg);
        !          57265:     }
        !          57266: }<?php
        !          57267: /**
        !          57268:  * PEAR_ChannelFile, the channel handling class
        !          57269:  *
        !          57270:  * PHP versions 4 and 5
        !          57271:  *
        !          57272:  * @category   pear
        !          57273:  * @package    PEAR
        !          57274:  * @author     Greg Beaver <cellog@php.net>
        !          57275:  * @copyright  1997-2009 The Authors
        !          57276:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          57277:  * @version    CVS: $Id: ChannelFile.php 313023 2011-07-06 19:17:11Z dufuz $
        !          57278:  * @link       http://pear.php.net/package/PEAR
        !          57279:  * @since      File available since Release 1.4.0a1
        !          57280:  */
1.1       misho    57281: 
1.1.1.2 ! misho    57282: /**
        !          57283:  * Needed for error handling
        !          57284:  */
        !          57285: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ErrorStack.php';
        !          57286: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/XMLParser.php';
        !          57287: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
1.1       misho    57288: 
1.1.1.2 ! misho    57289: /**
        !          57290:  * Error code if the channel.xml <channel> tag does not contain a valid version
        !          57291:  */
        !          57292: define('PEAR_CHANNELFILE_ERROR_NO_VERSION', 1);
        !          57293: /**
        !          57294:  * Error code if the channel.xml <channel> tag version is not supported (version 1.0 is the only supported version,
        !          57295:  * currently
        !          57296:  */
        !          57297: define('PEAR_CHANNELFILE_ERROR_INVALID_VERSION', 2);
1.1       misho    57298: 
1.1.1.2 ! misho    57299: /**
        !          57300:  * Error code if parsing is attempted with no xml extension
        !          57301:  */
        !          57302: define('PEAR_CHANNELFILE_ERROR_NO_XML_EXT', 3);
1.1       misho    57303: 
1.1.1.2 ! misho    57304: /**
        !          57305:  * Error code if creating the xml parser resource fails
        !          57306:  */
        !          57307: define('PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER', 4);
1.1       misho    57308: 
1.1.1.2 ! misho    57309: /**
        !          57310:  * Error code used for all sax xml parsing errors
        !          57311:  */
        !          57312: define('PEAR_CHANNELFILE_ERROR_PARSER_ERROR', 5);
1.1       misho    57313: 
1.1.1.2 ! misho    57314: /**#@+
        !          57315:  * Validation errors
        !          57316:  */
        !          57317: /**
        !          57318:  * Error code when channel name is missing
        !          57319:  */
        !          57320: define('PEAR_CHANNELFILE_ERROR_NO_NAME', 6);
        !          57321: /**
        !          57322:  * Error code when channel name is invalid
        !          57323:  */
        !          57324: define('PEAR_CHANNELFILE_ERROR_INVALID_NAME', 7);
        !          57325: /**
        !          57326:  * Error code when channel summary is missing
        !          57327:  */
        !          57328: define('PEAR_CHANNELFILE_ERROR_NO_SUMMARY', 8);
        !          57329: /**
        !          57330:  * Error code when channel summary is multi-line
        !          57331:  */
        !          57332: define('PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY', 9);
        !          57333: /**
        !          57334:  * Error code when channel server is missing for protocol
        !          57335:  */
        !          57336: define('PEAR_CHANNELFILE_ERROR_NO_HOST', 10);
        !          57337: /**
        !          57338:  * Error code when channel server is invalid for protocol
        !          57339:  */
        !          57340: define('PEAR_CHANNELFILE_ERROR_INVALID_HOST', 11);
        !          57341: /**
        !          57342:  * Error code when a mirror name is invalid
        !          57343:  */
        !          57344: define('PEAR_CHANNELFILE_ERROR_INVALID_MIRROR', 21);
        !          57345: /**
        !          57346:  * Error code when a mirror type is invalid
        !          57347:  */
        !          57348: define('PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE', 22);
        !          57349: /**
        !          57350:  * Error code when an attempt is made to generate xml, but the parsed content is invalid
        !          57351:  */
        !          57352: define('PEAR_CHANNELFILE_ERROR_INVALID', 23);
        !          57353: /**
        !          57354:  * Error code when an empty package name validate regex is passed in
        !          57355:  */
        !          57356: define('PEAR_CHANNELFILE_ERROR_EMPTY_REGEX', 24);
        !          57357: /**
        !          57358:  * Error code when a <function> tag has no version
        !          57359:  */
        !          57360: define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION', 25);
        !          57361: /**
        !          57362:  * Error code when a <function> tag has no name
        !          57363:  */
        !          57364: define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME', 26);
        !          57365: /**
        !          57366:  * Error code when a <validatepackage> tag has no name
        !          57367:  */
        !          57368: define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME', 27);
        !          57369: /**
        !          57370:  * Error code when a <validatepackage> tag has no version attribute
        !          57371:  */
        !          57372: define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION', 28);
        !          57373: /**
        !          57374:  * Error code when a mirror does not exist but is called for in one of the set*
        !          57375:  * methods.
        !          57376:  */
        !          57377: define('PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND', 32);
        !          57378: /**
        !          57379:  * Error code when a server port is not numeric
        !          57380:  */
        !          57381: define('PEAR_CHANNELFILE_ERROR_INVALID_PORT', 33);
        !          57382: /**
        !          57383:  * Error code when <static> contains no version attribute
        !          57384:  */
        !          57385: define('PEAR_CHANNELFILE_ERROR_NO_STATICVERSION', 34);
        !          57386: /**
        !          57387:  * Error code when <baseurl> contains no type attribute in a <rest> protocol definition
        !          57388:  */
        !          57389: define('PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE', 35);
        !          57390: /**
        !          57391:  * Error code when a mirror is defined and the channel.xml represents the __uri pseudo-channel
        !          57392:  */
        !          57393: define('PEAR_CHANNELFILE_URI_CANT_MIRROR', 36);
        !          57394: /**
        !          57395:  * Error code when ssl attribute is present and is not "yes"
        !          57396:  */
        !          57397: define('PEAR_CHANNELFILE_ERROR_INVALID_SSL', 37);
        !          57398: /**#@-*/
1.1       misho    57399: 
1.1.1.2 ! misho    57400: /**
        !          57401:  * Mirror types allowed.  Currently only internet servers are recognized.
        !          57402:  */
        !          57403: $GLOBALS['_PEAR_CHANNELS_MIRROR_TYPES'] =  array('server');
1.1       misho    57404: 
1.1.1.2 ! misho    57405: 
        !          57406: /**
        !          57407:  * The Channel handling class
        !          57408:  *
        !          57409:  * @category   pear
        !          57410:  * @package    PEAR
        !          57411:  * @author     Greg Beaver <cellog@php.net>
        !          57412:  * @copyright  1997-2009 The Authors
        !          57413:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          57414:  * @version    Release: 1.9.4
        !          57415:  * @link       http://pear.php.net/package/PEAR
        !          57416:  * @since      Class available since Release 1.4.0a1
        !          57417:  */
        !          57418: class PEAR_ChannelFile
        !          57419: {
1.1       misho    57420:     /**
1.1.1.2 ! misho    57421:      * @access private
        !          57422:      * @var PEAR_ErrorStack
        !          57423:      * @access private
1.1       misho    57424:      */
1.1.1.2 ! misho    57425:     var $_stack;
1.1       misho    57426: 
                   57427:     /**
1.1.1.2 ! misho    57428:      * Supported channel.xml versions, for parsing
        !          57429:      * @var array
        !          57430:      * @access private
1.1       misho    57431:      */
1.1.1.2 ! misho    57432:     var $_supportedVersions = array('1.0');
1.1       misho    57433: 
1.1.1.2 ! misho    57434:     /**
        !          57435:      * Parsed channel information
        !          57436:      * @var array
        !          57437:      * @access private
        !          57438:      */
        !          57439:     var $_channelInfo;
1.1       misho    57440: 
1.1.1.2 ! misho    57441:     /**
        !          57442:      * index into the subchannels array, used for parsing xml
        !          57443:      * @var int
        !          57444:      * @access private
        !          57445:      */
        !          57446:     var $_subchannelIndex;
1.1       misho    57447: 
1.1.1.2 ! misho    57448:     /**
        !          57449:      * index into the mirrors array, used for parsing xml
        !          57450:      * @var int
        !          57451:      * @access private
        !          57452:      */
        !          57453:     var $_mirrorIndex;
1.1       misho    57454: 
1.1.1.2 ! misho    57455:     /**
        !          57456:      * Flag used to determine the validity of parsed content
        !          57457:      * @var boolean
        !          57458:      * @access private
        !          57459:      */
        !          57460:     var $_isValid = false;
1.1       misho    57461: 
1.1.1.2 ! misho    57462:     function PEAR_ChannelFile()
        !          57463:     {
        !          57464:         $this->_stack = &new PEAR_ErrorStack('PEAR_ChannelFile');
        !          57465:         $this->_stack->setErrorMessageTemplate($this->_getErrorMessage());
        !          57466:         $this->_isValid = false;
1.1       misho    57467:     }
                   57468: 
                   57469:     /**
1.1.1.2 ! misho    57470:      * @return array
        !          57471:      * @access protected
1.1       misho    57472:      */
1.1.1.2 ! misho    57473:     function _getErrorMessage()
1.1       misho    57474:     {
1.1.1.2 ! misho    57475:         return
        !          57476:             array(
        !          57477:                 PEAR_CHANNELFILE_ERROR_INVALID_VERSION =>
        !          57478:                     'While parsing channel.xml, an invalid version number "%version% was passed in, expecting one of %versions%',
        !          57479:                 PEAR_CHANNELFILE_ERROR_NO_VERSION =>
        !          57480:                     'No version number found in <channel> tag',
        !          57481:                 PEAR_CHANNELFILE_ERROR_NO_XML_EXT =>
        !          57482:                     '%error%',
        !          57483:                 PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER =>
        !          57484:                     'Unable to create XML parser',
        !          57485:                 PEAR_CHANNELFILE_ERROR_PARSER_ERROR =>
        !          57486:                     '%error%',
        !          57487:                 PEAR_CHANNELFILE_ERROR_NO_NAME =>
        !          57488:                     'Missing channel name',
        !          57489:                 PEAR_CHANNELFILE_ERROR_INVALID_NAME =>
        !          57490:                     'Invalid channel %tag% "%name%"',
        !          57491:                 PEAR_CHANNELFILE_ERROR_NO_SUMMARY =>
        !          57492:                     'Missing channel summary',
        !          57493:                 PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY =>
        !          57494:                     'Channel summary should be on one line, but is multi-line',
        !          57495:                 PEAR_CHANNELFILE_ERROR_NO_HOST =>
        !          57496:                     'Missing channel server for %type% server',
        !          57497:                 PEAR_CHANNELFILE_ERROR_INVALID_HOST =>
        !          57498:                     'Server name "%server%" is invalid for %type% server',
        !          57499:                 PEAR_CHANNELFILE_ERROR_INVALID_MIRROR =>
        !          57500:                     'Invalid mirror name "%name%", mirror type %type%',
        !          57501:                 PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE =>
        !          57502:                     'Invalid mirror type "%type%"',
        !          57503:                 PEAR_CHANNELFILE_ERROR_INVALID =>
        !          57504:                     'Cannot generate xml, contents are invalid',
        !          57505:                 PEAR_CHANNELFILE_ERROR_EMPTY_REGEX =>
        !          57506:                     'packagenameregex cannot be empty',
        !          57507:                 PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION =>
        !          57508:                     '%parent% %protocol% function has no version',
        !          57509:                 PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME =>
        !          57510:                     '%parent% %protocol% function has no name',
        !          57511:                 PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE =>
        !          57512:                     '%parent% rest baseurl has no type',
        !          57513:                 PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME =>
        !          57514:                     'Validation package has no name in <validatepackage> tag',
        !          57515:                 PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION =>
        !          57516:                     'Validation package "%package%" has no version',
        !          57517:                 PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND =>
        !          57518:                     'Mirror "%mirror%" does not exist',
        !          57519:                 PEAR_CHANNELFILE_ERROR_INVALID_PORT =>
        !          57520:                     'Port "%port%" must be numeric',
        !          57521:                 PEAR_CHANNELFILE_ERROR_NO_STATICVERSION =>
        !          57522:                     '<static> tag must contain version attribute',
        !          57523:                 PEAR_CHANNELFILE_URI_CANT_MIRROR =>
        !          57524:                     'The __uri pseudo-channel cannot have mirrors',
        !          57525:                 PEAR_CHANNELFILE_ERROR_INVALID_SSL =>
        !          57526:                     '%server% has invalid ssl attribute "%ssl%" can only be yes or not present',
        !          57527:             );
1.1       misho    57528:     }
                   57529: 
                   57530:     /**
1.1.1.2 ! misho    57531:      * @param string contents of package.xml file
        !          57532:      * @return bool success of parsing
1.1       misho    57533:      */
1.1.1.2 ! misho    57534:     function fromXmlString($data)
1.1       misho    57535:     {
1.1.1.2 ! misho    57536:         if (preg_match('/<channel\s+version="([0-9]+\.[0-9]+)"/', $data, $channelversion)) {
        !          57537:             if (!in_array($channelversion[1], $this->_supportedVersions)) {
        !          57538:                 $this->_stack->push(PEAR_CHANNELFILE_ERROR_INVALID_VERSION, 'error',
        !          57539:                     array('version' => $channelversion[1]));
        !          57540:                 return false;
        !          57541:             }
        !          57542:             $parser = new PEAR_XMLParser;
        !          57543:             $result = $parser->parse($data);
        !          57544:             if ($result !== true) {
        !          57545:                 if ($result->getCode() == 1) {
        !          57546:                     $this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_XML_EXT, 'error',
        !          57547:                         array('error' => $result->getMessage()));
        !          57548:                 } else {
        !          57549:                     $this->_stack->push(PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER, 'error');
1.1       misho    57550:                 }
                   57551:                 return false;
                   57552:             }
1.1.1.2 ! misho    57553:             $this->_channelInfo = $parser->getData();
        !          57554:             return true;
        !          57555:         } else {
        !          57556:             $this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_VERSION, 'error', array('xml' => $data));
1.1       misho    57557:             return false;
                   57558:         }
                   57559:     }
                   57560: 
                   57561:     /**
1.1.1.2 ! misho    57562:      * @return array
1.1       misho    57563:      */
1.1.1.2 ! misho    57564:     function toArray()
1.1       misho    57565:     {
1.1.1.2 ! misho    57566:         if (!$this->_isValid && !$this->validate()) {
        !          57567:             return false;
1.1       misho    57568:         }
1.1.1.2 ! misho    57569:         return $this->_channelInfo;
1.1       misho    57570:     }
                   57571: 
                   57572:     /**
1.1.1.2 ! misho    57573:      * @param array
        !          57574:      * @static
        !          57575:      * @return PEAR_ChannelFile|false false if invalid
1.1       misho    57576:      */
1.1.1.2 ! misho    57577:     function &fromArray($data, $compatibility = false, $stackClass = 'PEAR_ErrorStack')
1.1       misho    57578:     {
1.1.1.2 ! misho    57579:         $a = new PEAR_ChannelFile($compatibility, $stackClass);
        !          57580:         $a->_fromArray($data);
        !          57581:         if (!$a->validate()) {
        !          57582:             $a = false;
        !          57583:             return $a;
1.1       misho    57584:         }
1.1.1.2 ! misho    57585:         return $a;
1.1       misho    57586:     }
                   57587: 
                   57588:     /**
1.1.1.2 ! misho    57589:      * Unlike {@link fromArray()} this does not do any validation
        !          57590:      * @param array
        !          57591:      * @static
        !          57592:      * @return PEAR_ChannelFile
1.1       misho    57593:      */
1.1.1.2 ! misho    57594:     function &fromArrayWithErrors($data, $compatibility = false,
        !          57595:                                   $stackClass = 'PEAR_ErrorStack')
1.1       misho    57596:     {
1.1.1.2 ! misho    57597:         $a = new PEAR_ChannelFile($compatibility, $stackClass);
        !          57598:         $a->_fromArray($data);
        !          57599:         return $a;
        !          57600:     }
1.1       misho    57601: 
1.1.1.2 ! misho    57602:     /**
        !          57603:      * @param array
        !          57604:      * @access private
        !          57605:      */
        !          57606:     function _fromArray($data)
        !          57607:     {
        !          57608:         $this->_channelInfo = $data;
1.1       misho    57609:     }
                   57610: 
                   57611:     /**
1.1.1.2 ! misho    57612:      * Wrapper to {@link PEAR_ErrorStack::getErrors()}
        !          57613:      * @param boolean determines whether to purge the error stack after retrieving
        !          57614:      * @return array
1.1       misho    57615:      */
1.1.1.2 ! misho    57616:     function getErrors($purge = false)
1.1       misho    57617:     {
1.1.1.2 ! misho    57618:         return $this->_stack->getErrors($purge);
1.1       misho    57619:     }
                   57620: 
                   57621:     /**
1.1.1.2 ! misho    57622:      * Unindent given string (?)
        !          57623:      *
        !          57624:      * @param string $str The string that has to be unindented.
        !          57625:      * @return string
        !          57626:      * @access private
1.1       misho    57627:      */
1.1.1.2 ! misho    57628:     function _unIndent($str)
1.1       misho    57629:     {
1.1.1.2 ! misho    57630:         // remove leading newlines
        !          57631:         $str = preg_replace('/^[\r\n]+/', '', $str);
        !          57632:         // find whitespace at the beginning of the first line
        !          57633:         $indent_len = strspn($str, " \t");
        !          57634:         $indent = substr($str, 0, $indent_len);
        !          57635:         $data = '';
        !          57636:         // remove the same amount of whitespace from following lines
        !          57637:         foreach (explode("\n", $str) as $line) {
        !          57638:             if (substr($line, 0, $indent_len) == $indent) {
        !          57639:                 $data .= substr($line, $indent_len) . "\n";
1.1       misho    57640:             }
1.1.1.2 ! misho    57641:         }
        !          57642:         return $data;
        !          57643:     }
1.1       misho    57644: 
1.1.1.2 ! misho    57645:     /**
        !          57646:      * Parse a channel.xml file.  Expects the name of
        !          57647:      * a channel xml file as input.
        !          57648:      *
        !          57649:      * @param string  $descfile  name of channel xml file
        !          57650:      * @return bool success of parsing
        !          57651:      */
        !          57652:     function fromXmlFile($descfile)
        !          57653:     {
        !          57654:         if (!file_exists($descfile) || !is_file($descfile) || !is_readable($descfile) ||
        !          57655:              (!$fp = fopen($descfile, 'r'))) {
        !          57656:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
        !          57657:             return PEAR::raiseError("Unable to open $descfile");
1.1       misho    57658:         }
                   57659: 
1.1.1.2 ! misho    57660:         // read the whole thing so we only get one cdata callback
        !          57661:         // for each block of cdata
        !          57662:         fclose($fp);
        !          57663:         $data = file_get_contents($descfile);
        !          57664:         return $this->fromXmlString($data);
1.1       misho    57665:     }
                   57666: 
                   57667:     /**
1.1.1.2 ! misho    57668:      * Parse channel information from different sources
        !          57669:      *
        !          57670:      * This method is able to extract information about a channel
        !          57671:      * from an .xml file or a string
        !          57672:      *
        !          57673:      * @access public
        !          57674:      * @param  string Filename of the source or the source itself
        !          57675:      * @return bool
1.1       misho    57676:      */
1.1.1.2 ! misho    57677:     function fromAny($info)
1.1       misho    57678:     {
1.1.1.2 ! misho    57679:         if (is_string($info) && file_exists($info) && strlen($info) < 255) {
        !          57680:             $tmp = substr($info, -4);
        !          57681:             if ($tmp == '.xml') {
        !          57682:                 $info = $this->fromXmlFile($info);
        !          57683:             } else {
        !          57684:                 $fp = fopen($info, "r");
        !          57685:                 $test = fread($fp, 5);
        !          57686:                 fclose($fp);
        !          57687:                 if ($test == "<?xml") {
        !          57688:                     $info = $this->fromXmlFile($info);
1.1       misho    57689:                 }
                   57690:             }
1.1.1.2 ! misho    57691:             if (PEAR::isError($info)) {
        !          57692:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
        !          57693:                 return PEAR::raiseError($info);
1.1       misho    57694:             }
                   57695:         }
1.1.1.2 ! misho    57696:         if (is_string($info)) {
        !          57697:             $info = $this->fromXmlString($info);
        !          57698:         }
        !          57699:         return $info;
1.1       misho    57700:     }
                   57701: 
                   57702:     /**
1.1.1.2 ! misho    57703:      * Return an XML document based on previous parsing and modifications
        !          57704:      *
        !          57705:      * @return string XML data
        !          57706:      *
        !          57707:      * @access public
1.1       misho    57708:      */
1.1.1.2 ! misho    57709:     function toXml()
1.1       misho    57710:     {
1.1.1.2 ! misho    57711:         if (!$this->_isValid && !$this->validate()) {
        !          57712:             $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID);
1.1       misho    57713:             return false;
                   57714:         }
1.1.1.2 ! misho    57715:         if (!isset($this->_channelInfo['attribs']['version'])) {
        !          57716:             $this->_channelInfo['attribs']['version'] = '1.0';
1.1       misho    57717:         }
1.1.1.2 ! misho    57718:         $channelInfo = $this->_channelInfo;
        !          57719:         $ret = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n";
        !          57720:         $ret .= "<channel version=\"" .
        !          57721:             $channelInfo['attribs']['version'] . "\" xmlns=\"http://pear.php.net/channel-1.0\"
        !          57722:   xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
        !          57723:   xsi:schemaLocation=\"http://pear.php.net/dtd/channel-"
        !          57724:             . $channelInfo['attribs']['version'] . " http://pear.php.net/dtd/channel-" .
        !          57725:             $channelInfo['attribs']['version'] . ".xsd\">
        !          57726:  <name>$channelInfo[name]</name>
        !          57727:  <summary>" . htmlspecialchars($channelInfo['summary'])."</summary>
        !          57728: ";
        !          57729:         if (isset($channelInfo['suggestedalias'])) {
        !          57730:             $ret .= ' <suggestedalias>' . $channelInfo['suggestedalias'] . "</suggestedalias>\n";
        !          57731:         }
        !          57732:         if (isset($channelInfo['validatepackage'])) {
        !          57733:             $ret .= ' <validatepackage version="' .
        !          57734:                 $channelInfo['validatepackage']['attribs']['version']. '">' .
        !          57735:                 htmlspecialchars($channelInfo['validatepackage']['_content']) .
        !          57736:                 "</validatepackage>\n";
        !          57737:         }
        !          57738:         $ret .= " <servers>\n";
        !          57739:         $ret .= '  <primary';
        !          57740:         if (isset($channelInfo['servers']['primary']['attribs']['ssl'])) {
        !          57741:             $ret .= ' ssl="' . $channelInfo['servers']['primary']['attribs']['ssl'] . '"';
        !          57742:         }
        !          57743:         if (isset($channelInfo['servers']['primary']['attribs']['port'])) {
        !          57744:             $ret .= ' port="' . $channelInfo['servers']['primary']['attribs']['port'] . '"';
        !          57745:         }
        !          57746:         $ret .= ">\n";
        !          57747:         if (isset($channelInfo['servers']['primary']['rest'])) {
        !          57748:             $ret .= $this->_makeRestXml($channelInfo['servers']['primary']['rest'], '   ');
        !          57749:         }
        !          57750:         $ret .= "  </primary>\n";
        !          57751:         if (isset($channelInfo['servers']['mirror'])) {
        !          57752:             $ret .= $this->_makeMirrorsXml($channelInfo);
        !          57753:         }
        !          57754:         $ret .= " </servers>\n";
        !          57755:         $ret .= "</channel>";
        !          57756:         return str_replace("\r", "\n", str_replace("\r\n", "\n", $ret));
1.1       misho    57757:     }
                   57758: 
                   57759:     /**
1.1.1.2 ! misho    57760:      * Generate the <rest> tag
        !          57761:      * @access private
1.1       misho    57762:      */
1.1.1.2 ! misho    57763:     function _makeRestXml($info, $indent)
1.1       misho    57764:     {
1.1.1.2 ! misho    57765:         $ret = $indent . "<rest>\n";
        !          57766:         if (isset($info['baseurl']) && !isset($info['baseurl'][0])) {
        !          57767:             $info['baseurl'] = array($info['baseurl']);
1.1       misho    57768:         }
                   57769: 
1.1.1.2 ! misho    57770:         if (isset($info['baseurl'])) {
        !          57771:             foreach ($info['baseurl'] as $url) {
        !          57772:                 $ret .= "$indent <baseurl type=\"" . $url['attribs']['type'] . "\"";
        !          57773:                 $ret .= ">" . $url['_content'] . "</baseurl>\n";
        !          57774:             }
        !          57775:         }
        !          57776:         $ret .= $indent . "</rest>\n";
        !          57777:         return $ret;
1.1       misho    57778:     }
                   57779: 
                   57780:     /**
1.1.1.2 ! misho    57781:      * Generate the <mirrors> tag
        !          57782:      * @access private
1.1       misho    57783:      */
1.1.1.2 ! misho    57784:     function _makeMirrorsXml($channelInfo)
1.1       misho    57785:     {
1.1.1.2 ! misho    57786:         $ret = "";
        !          57787:         if (!isset($channelInfo['servers']['mirror'][0])) {
        !          57788:             $channelInfo['servers']['mirror'] = array($channelInfo['servers']['mirror']);
1.1       misho    57789:         }
1.1.1.2 ! misho    57790:         foreach ($channelInfo['servers']['mirror'] as $mirror) {
        !          57791:             $ret .= '  <mirror host="' . $mirror['attribs']['host'] . '"';
        !          57792:             if (isset($mirror['attribs']['port'])) {
        !          57793:                 $ret .= ' port="' . $mirror['attribs']['port'] . '"';
        !          57794:             }
        !          57795:             if (isset($mirror['attribs']['ssl'])) {
        !          57796:                 $ret .= ' ssl="' . $mirror['attribs']['ssl'] . '"';
        !          57797:             }
        !          57798:             $ret .= ">\n";
        !          57799:             if (isset($mirror['rest'])) {
        !          57800:                 if (isset($mirror['rest'])) {
        !          57801:                     $ret .= $this->_makeRestXml($mirror['rest'], '   ');
        !          57802:                 }
        !          57803:                 $ret .= "  </mirror>\n";
        !          57804:             } else {
        !          57805:                 $ret .= "/>\n";
        !          57806:             }
1.1       misho    57807:         }
1.1.1.2 ! misho    57808:         return $ret;
1.1       misho    57809:     }
                   57810: 
                   57811:     /**
1.1.1.2 ! misho    57812:      * Generate the <functions> tag
        !          57813:      * @access private
1.1       misho    57814:      */
1.1.1.2 ! misho    57815:     function _makeFunctionsXml($functions, $indent, $rest = false)
1.1       misho    57816:     {
1.1.1.2 ! misho    57817:         $ret = '';
        !          57818:         if (!isset($functions[0])) {
        !          57819:             $functions = array($functions);
1.1       misho    57820:         }
1.1.1.2 ! misho    57821:         foreach ($functions as $function) {
        !          57822:             $ret .= "$indent<function version=\"" . $function['attribs']['version'] . "\"";
        !          57823:             if ($rest) {
        !          57824:                 $ret .= ' uri="' . $function['attribs']['uri'] . '"';
        !          57825:             }
        !          57826:             $ret .= ">" . $function['_content'] . "</function>\n";
1.1       misho    57827:         }
1.1.1.2 ! misho    57828:         return $ret;
1.1       misho    57829:     }
                   57830: 
                   57831:     /**
1.1.1.2 ! misho    57832:      * Validation error.  Also marks the object contents as invalid
        !          57833:      * @param error code
        !          57834:      * @param array error information
        !          57835:      * @access private
1.1       misho    57836:      */
1.1.1.2 ! misho    57837:     function _validateError($code, $params = array())
1.1       misho    57838:     {
1.1.1.2 ! misho    57839:         $this->_stack->push($code, 'error', $params);
        !          57840:         $this->_isValid = false;
1.1       misho    57841:     }
                   57842: 
                   57843:     /**
1.1.1.2 ! misho    57844:      * Validation warning.  Does not mark the object contents invalid.
        !          57845:      * @param error code
        !          57846:      * @param array error information
        !          57847:      * @access private
1.1       misho    57848:      */
1.1.1.2 ! misho    57849:     function _validateWarning($code, $params = array())
1.1       misho    57850:     {
1.1.1.2 ! misho    57851:         $this->_stack->push($code, 'warning', $params);
1.1       misho    57852:     }
1.1.1.2 ! misho    57853: 
1.1       misho    57854:     /**
1.1.1.2 ! misho    57855:      * Validate parsed file.
        !          57856:      *
        !          57857:      * @access public
        !          57858:      * @return boolean
1.1       misho    57859:      */
1.1.1.2 ! misho    57860:     function validate()
1.1       misho    57861:     {
1.1.1.2 ! misho    57862:         $this->_isValid = true;
        !          57863:         $info = $this->_channelInfo;
        !          57864:         if (empty($info['name'])) {
        !          57865:             $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_NAME);
        !          57866:         } elseif (!$this->validChannelServer($info['name'])) {
        !          57867:             if ($info['name'] != '__uri') {
        !          57868:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, array('tag' => 'name',
        !          57869:                     'name' => $info['name']));
        !          57870:             }
1.1       misho    57871:         }
1.1.1.2 ! misho    57872:         if (empty($info['summary'])) {
        !          57873:             $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY);
        !          57874:         } elseif (strpos(trim($info['summary']), "\n") !== false) {
        !          57875:             $this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY,
        !          57876:                 array('summary' => $info['summary']));
        !          57877:         }
        !          57878:         if (isset($info['suggestedalias'])) {
        !          57879:             if (!$this->validChannelServer($info['suggestedalias'])) {
        !          57880:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
        !          57881:                     array('tag' => 'suggestedalias', 'name' =>$info['suggestedalias']));
1.1       misho    57882:             }
1.1.1.2 ! misho    57883:         }
        !          57884:         if (isset($info['localalias'])) {
        !          57885:             if (!$this->validChannelServer($info['localalias'])) {
        !          57886:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
        !          57887:                     array('tag' => 'localalias', 'name' =>$info['localalias']));
        !          57888:             }
        !          57889:         }
        !          57890:         if (isset($info['validatepackage'])) {
        !          57891:             if (!isset($info['validatepackage']['_content'])) {
        !          57892:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME);
        !          57893:             }
        !          57894:             if (!isset($info['validatepackage']['attribs']['version'])) {
        !          57895:                 $content = isset($info['validatepackage']['_content']) ?
        !          57896:                     $info['validatepackage']['_content'] :
        !          57897:                     null;
        !          57898:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION,
        !          57899:                     array('package' => $content));
1.1       misho    57900:             }
                   57901:         }
                   57902: 
1.1.1.2 ! misho    57903:         if (isset($info['servers']['primary']['attribs'], $info['servers']['primary']['attribs']['port']) &&
        !          57904:               !is_numeric($info['servers']['primary']['attribs']['port'])) {
        !          57905:             $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_PORT,
        !          57906:                 array('port' => $info['servers']['primary']['attribs']['port']));
1.1       misho    57907:         }
                   57908: 
1.1.1.2 ! misho    57909:         if (isset($info['servers']['primary']['attribs'], $info['servers']['primary']['attribs']['ssl']) &&
        !          57910:               $info['servers']['primary']['attribs']['ssl'] != 'yes') {
        !          57911:             $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL,
        !          57912:                 array('ssl' => $info['servers']['primary']['attribs']['ssl'],
        !          57913:                     'server' => $info['name']));
1.1       misho    57914:         }
                   57915: 
1.1.1.2 ! misho    57916:         if (isset($info['servers']['primary']['rest']) &&
        !          57917:               isset($info['servers']['primary']['rest']['baseurl'])) {
        !          57918:             $this->_validateFunctions('rest', $info['servers']['primary']['rest']['baseurl']);
        !          57919:         }
        !          57920:         if (isset($info['servers']['mirror'])) {
        !          57921:             if ($this->_channelInfo['name'] == '__uri') {
        !          57922:                 $this->_validateError(PEAR_CHANNELFILE_URI_CANT_MIRROR);
        !          57923:             }
        !          57924:             if (!isset($info['servers']['mirror'][0])) {
        !          57925:                 $info['servers']['mirror'] = array($info['servers']['mirror']);
        !          57926:             }
        !          57927:             foreach ($info['servers']['mirror'] as $mirror) {
        !          57928:                 if (!isset($mirror['attribs']['host'])) {
        !          57929:                     $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_HOST,
        !          57930:                       array('type' => 'mirror'));
        !          57931:                 } elseif (!$this->validChannelServer($mirror['attribs']['host'])) {
        !          57932:                     $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_HOST,
        !          57933:                         array('server' => $mirror['attribs']['host'], 'type' => 'mirror'));
        !          57934:                 }
        !          57935:                 if (isset($mirror['attribs']['ssl']) && $mirror['attribs']['ssl'] != 'yes') {
        !          57936:                     $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL,
        !          57937:                         array('ssl' => $info['ssl'], 'server' => $mirror['attribs']['host']));
        !          57938:                 }
        !          57939:                 if (isset($mirror['rest'])) {
        !          57940:                     $this->_validateFunctions('rest', $mirror['rest']['baseurl'],
        !          57941:                         $mirror['attribs']['host']);
        !          57942:                 }
        !          57943:             }
        !          57944:         }
        !          57945:         return $this->_isValid;
1.1       misho    57946:     }
                   57947: 
                   57948:     /**
1.1.1.2 ! misho    57949:      * @param string  rest - protocol name this function applies to
        !          57950:      * @param array the functions
        !          57951:      * @param string the name of the parent element (mirror name, for instance)
1.1       misho    57952:      */
1.1.1.2 ! misho    57953:     function _validateFunctions($protocol, $functions, $parent = '')
1.1       misho    57954:     {
1.1.1.2 ! misho    57955:         if (!isset($functions[0])) {
        !          57956:             $functions = array($functions);
        !          57957:         }
        !          57958: 
        !          57959:         foreach ($functions as $function) {
        !          57960:             if (!isset($function['_content']) || empty($function['_content'])) {
        !          57961:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME,
        !          57962:                     array('parent' => $parent, 'protocol' => $protocol));
1.1       misho    57963:             }
                   57964: 
1.1.1.2 ! misho    57965:             if ($protocol == 'rest') {
        !          57966:                 if (!isset($function['attribs']['type']) ||
        !          57967:                       empty($function['attribs']['type'])) {
        !          57968:                     $this->_validateError(PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE,
        !          57969:                         array('parent' => $parent, 'protocol' => $protocol));
1.1       misho    57970:                 }
                   57971:             } else {
1.1.1.2 ! misho    57972:                 if (!isset($function['attribs']['version']) ||
        !          57973:                       empty($function['attribs']['version'])) {
        !          57974:                     $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION,
        !          57975:                         array('parent' => $parent, 'protocol' => $protocol));
1.1       misho    57976:                 }
                   57977:             }
                   57978:         }
                   57979:     }
                   57980: 
                   57981:     /**
1.1.1.2 ! misho    57982:      * Test whether a string contains a valid channel server.
        !          57983:      * @param string $ver the package version to test
        !          57984:      * @return bool
1.1       misho    57985:      */
1.1.1.2 ! misho    57986:     function validChannelServer($server)
1.1       misho    57987:     {
1.1.1.2 ! misho    57988:         if ($server == '__uri') {
1.1       misho    57989:             return true;
                   57990:         }
1.1.1.2 ! misho    57991:         return (bool) preg_match(PEAR_CHANNELS_SERVER_PREG, $server);
1.1       misho    57992:     }
                   57993: 
                   57994:     /**
                   57995:      * @return string|false
                   57996:      */
1.1.1.2 ! misho    57997:     function getName()
1.1       misho    57998:     {
1.1.1.2 ! misho    57999:         if (isset($this->_channelInfo['name'])) {
        !          58000:             return $this->_channelInfo['name'];
1.1       misho    58001:         }
                   58002: 
1.1.1.2 ! misho    58003:         return false;
1.1       misho    58004:     }
                   58005: 
                   58006:     /**
1.1.1.2 ! misho    58007:      * @return string|false
1.1       misho    58008:      */
1.1.1.2 ! misho    58009:     function getServer()
1.1       misho    58010:     {
1.1.1.2 ! misho    58011:         if (isset($this->_channelInfo['name'])) {
        !          58012:             return $this->_channelInfo['name'];
1.1       misho    58013:         }
                   58014: 
1.1.1.2 ! misho    58015:         return false;
        !          58016:     }
1.1       misho    58017: 
1.1.1.2 ! misho    58018:     /**
        !          58019:      * @return int|80 port number to connect to
        !          58020:      */
        !          58021:     function getPort($mirror = false)
        !          58022:     {
        !          58023:         if ($mirror) {
        !          58024:             if ($mir = $this->getMirror($mirror)) {
        !          58025:                 if (isset($mir['attribs']['port'])) {
        !          58026:                     return $mir['attribs']['port'];
        !          58027:                 }
1.1       misho    58028: 
1.1.1.2 ! misho    58029:                 if ($this->getSSL($mirror)) {
        !          58030:                     return 443;
1.1       misho    58031:                 }
1.1.1.2 ! misho    58032: 
        !          58033:                 return 80;
1.1       misho    58034:             }
1.1.1.2 ! misho    58035: 
        !          58036:             return false;
1.1       misho    58037:         }
                   58038: 
1.1.1.2 ! misho    58039:         if (isset($this->_channelInfo['servers']['primary']['attribs']['port'])) {
        !          58040:             return $this->_channelInfo['servers']['primary']['attribs']['port'];
        !          58041:         }
        !          58042: 
        !          58043:         if ($this->getSSL()) {
        !          58044:             return 443;
        !          58045:         }
        !          58046: 
        !          58047:         return 80;
1.1       misho    58048:     }
                   58049: 
1.1.1.2 ! misho    58050:     /**
        !          58051:      * @return bool Determines whether secure sockets layer (SSL) is used to connect to this channel
        !          58052:      */
        !          58053:     function getSSL($mirror = false)
1.1       misho    58054:     {
1.1.1.2 ! misho    58055:         if ($mirror) {
        !          58056:             if ($mir = $this->getMirror($mirror)) {
        !          58057:                 if (isset($mir['attribs']['ssl'])) {
        !          58058:                     return true;
        !          58059:                 }
        !          58060: 
        !          58061:                 return false;
1.1       misho    58062:             }
1.1.1.2 ! misho    58063: 
        !          58064:             return false;
        !          58065:         }
        !          58066: 
        !          58067:         if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) {
        !          58068:             return true;
1.1       misho    58069:         }
                   58070: 
                   58071:         return false;
                   58072:     }
                   58073: 
                   58074:     /**
1.1.1.2 ! misho    58075:      * @return string|false
1.1       misho    58076:      */
1.1.1.2 ! misho    58077:     function getSummary()
1.1       misho    58078:     {
1.1.1.2 ! misho    58079:         if (isset($this->_channelInfo['summary'])) {
        !          58080:             return $this->_channelInfo['summary'];
1.1       misho    58081:         }
                   58082: 
1.1.1.2 ! misho    58083:         return false;
1.1       misho    58084:     }
                   58085: 
1.1.1.2 ! misho    58086:     /**
        !          58087:      * @param string protocol type
        !          58088:      * @param string Mirror name
        !          58089:      * @return array|false
        !          58090:      */
        !          58091:     function getFunctions($protocol, $mirror = false)
1.1       misho    58092:     {
1.1.1.2 ! misho    58093:         if ($this->getName() == '__uri') {
        !          58094:             return false;
        !          58095:         }
1.1       misho    58096: 
1.1.1.2 ! misho    58097:         $function = $protocol == 'rest' ? 'baseurl' : 'function';
        !          58098:         if ($mirror) {
        !          58099:             if ($mir = $this->getMirror($mirror)) {
        !          58100:                 if (isset($mir[$protocol][$function])) {
        !          58101:                     return $mir[$protocol][$function];
        !          58102:                 }
        !          58103:             }
1.1       misho    58104: 
1.1.1.2 ! misho    58105:             return false;
1.1       misho    58106:         }
                   58107: 
1.1.1.2 ! misho    58108:         if (isset($this->_channelInfo['servers']['primary'][$protocol][$function])) {
        !          58109:             return $this->_channelInfo['servers']['primary'][$protocol][$function];
1.1       misho    58110:         }
                   58111: 
1.1.1.2 ! misho    58112:         return false;
1.1       misho    58113:     }
                   58114: 
1.1.1.2 ! misho    58115:     /**
        !          58116:      * @param string Protocol type
        !          58117:      * @param string Function name (null to return the
        !          58118:      *               first protocol of the type requested)
        !          58119:      * @param string Mirror name, if any
        !          58120:      * @return array
        !          58121:      */
        !          58122:      function getFunction($type, $name = null, $mirror = false)
        !          58123:      {
        !          58124:         $protocols = $this->getFunctions($type, $mirror);
        !          58125:         if (!$protocols) {
        !          58126:             return false;
        !          58127:         }
1.1       misho    58128: 
1.1.1.2 ! misho    58129:         foreach ($protocols as $protocol) {
        !          58130:             if ($name === null) {
        !          58131:                 return $protocol;
        !          58132:             }
1.1       misho    58133: 
1.1.1.2 ! misho    58134:             if ($protocol['_content'] != $name) {
        !          58135:                 continue;
        !          58136:             }
1.1       misho    58137: 
1.1.1.2 ! misho    58138:             return $protocol;
        !          58139:         }
1.1       misho    58140: 
1.1.1.2 ! misho    58141:         return false;
        !          58142:      }
1.1       misho    58143: 
                   58144:     /**
1.1.1.2 ! misho    58145:      * @param string protocol type
        !          58146:      * @param string protocol name
        !          58147:      * @param string version
        !          58148:      * @param string mirror name
        !          58149:      * @return boolean
1.1       misho    58150:      */
1.1.1.2 ! misho    58151:     function supports($type, $name = null, $mirror = false, $version = '1.0')
1.1       misho    58152:     {
1.1.1.2 ! misho    58153:         $protocols = $this->getFunctions($type, $mirror);
        !          58154:         if (!$protocols) {
        !          58155:             return false;
1.1       misho    58156:         }
1.1.1.2 ! misho    58157: 
        !          58158:         foreach ($protocols as $protocol) {
        !          58159:             if ($protocol['attribs']['version'] != $version) {
        !          58160:                 continue;
        !          58161:             }
        !          58162: 
        !          58163:             if ($name === null) {
        !          58164:                 return true;
        !          58165:             }
        !          58166: 
        !          58167:             if ($protocol['_content'] != $name) {
        !          58168:                 continue;
        !          58169:             }
        !          58170: 
        !          58171:             return true;
1.1       misho    58172:         }
1.1.1.2 ! misho    58173: 
        !          58174:         return false;
1.1       misho    58175:     }
                   58176: 
1.1.1.2 ! misho    58177:     /**
        !          58178:      * Determines whether a channel supports Representational State Transfer (REST) protocols
        !          58179:      * for retrieving channel information
        !          58180:      * @param string
        !          58181:      * @return bool
        !          58182:      */
        !          58183:     function supportsREST($mirror = false)
1.1       misho    58184:     {
1.1.1.2 ! misho    58185:         if ($mirror == $this->_channelInfo['name']) {
        !          58186:             $mirror = false;
1.1       misho    58187:         }
1.1.1.2 ! misho    58188: 
        !          58189:         if ($mirror) {
        !          58190:             if ($mir = $this->getMirror($mirror)) {
        !          58191:                 return isset($mir['rest']);
        !          58192:             }
        !          58193: 
        !          58194:             return false;
1.1       misho    58195:         }
                   58196: 
1.1.1.2 ! misho    58197:         return isset($this->_channelInfo['servers']['primary']['rest']);
        !          58198:     }
1.1       misho    58199: 
                   58200:     /**
1.1.1.2 ! misho    58201:      * Get the URL to access a base resource.
1.1       misho    58202:      *
1.1.1.2 ! misho    58203:      * Hyperlinks in the returned xml will be used to retrieve the proper information
        !          58204:      * needed.  This allows extreme extensibility and flexibility in implementation
        !          58205:      * @param string Resource Type to retrieve
1.1       misho    58206:      */
1.1.1.2 ! misho    58207:     function getBaseURL($resourceType, $mirror = false)
1.1       misho    58208:     {
1.1.1.2 ! misho    58209:         if ($mirror == $this->_channelInfo['name']) {
        !          58210:             $mirror = false;
        !          58211:         }
1.1       misho    58212: 
1.1.1.2 ! misho    58213:         if ($mirror) {
        !          58214:             $mir = $this->getMirror($mirror);
        !          58215:             if (!$mir) {
        !          58216:                 return false;
        !          58217:             }
1.1       misho    58218: 
1.1.1.2 ! misho    58219:             $rest = $mir['rest'];
        !          58220:         } else {
        !          58221:             $rest = $this->_channelInfo['servers']['primary']['rest'];
        !          58222:         }
1.1       misho    58223: 
1.1.1.2 ! misho    58224:         if (!isset($rest['baseurl'][0])) {
        !          58225:             $rest['baseurl'] = array($rest['baseurl']);
        !          58226:         }
        !          58227: 
        !          58228:         foreach ($rest['baseurl'] as $baseurl) {
        !          58229:             if (strtolower($baseurl['attribs']['type']) == strtolower($resourceType)) {
        !          58230:                 return $baseurl['_content'];
        !          58231:             }
        !          58232:         }
        !          58233: 
        !          58234:         return false;
        !          58235:     }
1.1       misho    58236: 
                   58237:     /**
1.1.1.2 ! misho    58238:      * Since REST does not implement RPC, provide this as a logical wrapper around
        !          58239:      * resetFunctions for REST
        !          58240:      * @param string|false mirror name, if any
1.1       misho    58241:      */
1.1.1.2 ! misho    58242:     function resetREST($mirror = false)
1.1       misho    58243:     {
1.1.1.2 ! misho    58244:         return $this->resetFunctions('rest', $mirror);
1.1       misho    58245:     }
                   58246: 
                   58247:     /**
1.1.1.2 ! misho    58248:      * Empty all protocol definitions
        !          58249:      * @param string protocol type
        !          58250:      * @param string|false mirror name, if any
1.1       misho    58251:      */
1.1.1.2 ! misho    58252:     function resetFunctions($type, $mirror = false)
1.1       misho    58253:     {
1.1.1.2 ! misho    58254:         if ($mirror) {
        !          58255:             if (isset($this->_channelInfo['servers']['mirror'])) {
        !          58256:                 $mirrors = $this->_channelInfo['servers']['mirror'];
        !          58257:                 if (!isset($mirrors[0])) {
        !          58258:                     $mirrors = array($mirrors);
        !          58259:                 }
1.1       misho    58260: 
1.1.1.2 ! misho    58261:                 foreach ($mirrors as $i => $mir) {
        !          58262:                     if ($mir['attribs']['host'] == $mirror) {
        !          58263:                         if (isset($this->_channelInfo['servers']['mirror'][$i][$type])) {
        !          58264:                             unset($this->_channelInfo['servers']['mirror'][$i][$type]);
        !          58265:                         }
        !          58266: 
        !          58267:                         return true;
        !          58268:                     }
        !          58269:                 }
        !          58270: 
        !          58271:                 return false;
1.1       misho    58272:             }
                   58273: 
1.1.1.2 ! misho    58274:             return false;
        !          58275:         }
1.1       misho    58276: 
1.1.1.2 ! misho    58277:         if (isset($this->_channelInfo['servers']['primary'][$type])) {
        !          58278:             unset($this->_channelInfo['servers']['primary'][$type]);
1.1       misho    58279:         }
                   58280: 
                   58281:         return true;
                   58282:     }
                   58283: 
                   58284:     /**
1.1.1.2 ! misho    58285:      * Set a channel's protocols to the protocols supported by pearweb
1.1       misho    58286:      */
1.1.1.2 ! misho    58287:     function setDefaultPEARProtocols($version = '1.0', $mirror = false)
1.1       misho    58288:     {
1.1.1.2 ! misho    58289:         switch ($version) {
        !          58290:             case '1.0' :
        !          58291:                 $this->resetREST($mirror);
1.1       misho    58292: 
1.1.1.2 ! misho    58293:                 if (!isset($this->_channelInfo['servers'])) {
        !          58294:                     $this->_channelInfo['servers'] = array('primary' =>
        !          58295:                         array('rest' => array()));
        !          58296:                 } elseif (!isset($this->_channelInfo['servers']['primary'])) {
        !          58297:                     $this->_channelInfo['servers']['primary'] = array('rest' => array());
        !          58298:                 }
1.1       misho    58299: 
1.1.1.2 ! misho    58300:                 return true;
        !          58301:             break;
        !          58302:             default :
        !          58303:                 return false;
        !          58304:             break;
1.1       misho    58305:         }
                   58306:     }
                   58307: 
                   58308:     /**
1.1.1.2 ! misho    58309:      * @return array
1.1       misho    58310:      */
1.1.1.2 ! misho    58311:     function getMirrors()
1.1       misho    58312:     {
1.1.1.2 ! misho    58313:         if (isset($this->_channelInfo['servers']['mirror'])) {
        !          58314:             $mirrors = $this->_channelInfo['servers']['mirror'];
        !          58315:             if (!isset($mirrors[0])) {
        !          58316:                 $mirrors = array($mirrors);
        !          58317:             }
1.1       misho    58318: 
1.1.1.2 ! misho    58319:             return $mirrors;
1.1       misho    58320:         }
                   58321: 
1.1.1.2 ! misho    58322:         return array();
        !          58323:     }
1.1       misho    58324: 
                   58325:     /**
1.1.1.2 ! misho    58326:      * Get the unserialized XML representing a mirror
        !          58327:      * @return array|false
1.1       misho    58328:      */
1.1.1.2 ! misho    58329:     function getMirror($server)
1.1       misho    58330:     {
1.1.1.2 ! misho    58331:         foreach ($this->getMirrors() as $mirror) {
        !          58332:             if ($mirror['attribs']['host'] == $server) {
        !          58333:                 return $mirror;
        !          58334:             }
1.1       misho    58335:         }
1.1.1.2 ! misho    58336: 
1.1       misho    58337:         return false;
                   58338:     }
                   58339: 
                   58340:     /**
1.1.1.2 ! misho    58341:      * @param string
        !          58342:      * @return string|false
        !          58343:      * @error PEAR_CHANNELFILE_ERROR_NO_NAME
        !          58344:      * @error PEAR_CHANNELFILE_ERROR_INVALID_NAME
1.1       misho    58345:      */
1.1.1.2 ! misho    58346:     function setName($name)
1.1       misho    58347:     {
1.1.1.2 ! misho    58348:         return $this->setServer($name);
1.1       misho    58349:     }
                   58350: 
                   58351:     /**
1.1.1.2 ! misho    58352:      * Set the socket number (port) that is used to connect to this channel
        !          58353:      * @param integer
        !          58354:      * @param string|false name of the mirror server, or false for the primary
1.1       misho    58355:      */
1.1.1.2 ! misho    58356:     function setPort($port, $mirror = false)
1.1       misho    58357:     {
1.1.1.2 ! misho    58358:         if ($mirror) {
        !          58359:             if (!isset($this->_channelInfo['servers']['mirror'])) {
        !          58360:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
        !          58361:                     array('mirror' => $mirror));
        !          58362:                 return false;
        !          58363:             }
        !          58364: 
        !          58365:             if (isset($this->_channelInfo['servers']['mirror'][0])) {
        !          58366:                 foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
        !          58367:                     if ($mirror == $mir['attribs']['host']) {
        !          58368:                         $this->_channelInfo['servers']['mirror'][$i]['attribs']['port'] = $port;
        !          58369:                         return true;
        !          58370:                     }
        !          58371:                 }
        !          58372: 
        !          58373:                 return false;
        !          58374:             } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
        !          58375:                 $this->_channelInfo['servers']['mirror']['attribs']['port'] = $port;
        !          58376:                 $this->_isValid = false;
        !          58377:                 return true;
        !          58378:             }
1.1       misho    58379:         }
                   58380: 
1.1.1.2 ! misho    58381:         $this->_channelInfo['servers']['primary']['attribs']['port'] = $port;
        !          58382:         $this->_isValid = false;
        !          58383:         return true;
1.1       misho    58384:     }
                   58385: 
                   58386:     /**
1.1.1.2 ! misho    58387:      * Set the socket number (port) that is used to connect to this channel
        !          58388:      * @param bool Determines whether to turn on SSL support or turn it off
        !          58389:      * @param string|false name of the mirror server, or false for the primary
1.1       misho    58390:      */
1.1.1.2 ! misho    58391:     function setSSL($ssl = true, $mirror = false)
1.1       misho    58392:     {
1.1.1.2 ! misho    58393:         if ($mirror) {
        !          58394:             if (!isset($this->_channelInfo['servers']['mirror'])) {
        !          58395:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
        !          58396:                     array('mirror' => $mirror));
        !          58397:                 return false;
1.1       misho    58398:             }
                   58399: 
1.1.1.2 ! misho    58400:             if (isset($this->_channelInfo['servers']['mirror'][0])) {
        !          58401:                 foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
        !          58402:                     if ($mirror == $mir['attribs']['host']) {
        !          58403:                         if (!$ssl) {
        !          58404:                             if (isset($this->_channelInfo['servers']['mirror'][$i]
        !          58405:                                   ['attribs']['ssl'])) {
        !          58406:                                 unset($this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl']);
        !          58407:                             }
        !          58408:                         } else {
        !          58409:                             $this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl'] = 'yes';
        !          58410:                         }
1.1       misho    58411: 
1.1.1.2 ! misho    58412:                         return true;
        !          58413:                     }
        !          58414:                 }
        !          58415: 
        !          58416:                 return false;
        !          58417:             } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
        !          58418:                 if (!$ssl) {
        !          58419:                     if (isset($this->_channelInfo['servers']['mirror']['attribs']['ssl'])) {
        !          58420:                         unset($this->_channelInfo['servers']['mirror']['attribs']['ssl']);
        !          58421:                     }
        !          58422:                 } else {
        !          58423:                     $this->_channelInfo['servers']['mirror']['attribs']['ssl'] = 'yes';
        !          58424:                 }
        !          58425: 
        !          58426:                 $this->_isValid = false;
        !          58427:                 return true;
        !          58428:             }
1.1       misho    58429:         }
                   58430: 
1.1.1.2 ! misho    58431:         if ($ssl) {
        !          58432:             $this->_channelInfo['servers']['primary']['attribs']['ssl'] = 'yes';
        !          58433:         } else {
        !          58434:             if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) {
        !          58435:                 unset($this->_channelInfo['servers']['primary']['attribs']['ssl']);
        !          58436:             }
1.1       misho    58437:         }
                   58438: 
1.1.1.2 ! misho    58439:         $this->_isValid = false;
        !          58440:         return true;
1.1       misho    58441:     }
                   58442: 
1.1.1.2 ! misho    58443:     /**
        !          58444:      * @param string
        !          58445:      * @return string|false
        !          58446:      * @error PEAR_CHANNELFILE_ERROR_NO_SERVER
        !          58447:      * @error PEAR_CHANNELFILE_ERROR_INVALID_SERVER
        !          58448:      */
        !          58449:     function setServer($server, $mirror = false)
1.1       misho    58450:     {
1.1.1.2 ! misho    58451:         if (empty($server)) {
        !          58452:             $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SERVER);
        !          58453:             return false;
        !          58454:         } elseif (!$this->validChannelServer($server)) {
        !          58455:             $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
        !          58456:                 array('tag' => 'name', 'name' => $server));
        !          58457:             return false;
1.1       misho    58458:         }
                   58459: 
1.1.1.2 ! misho    58460:         if ($mirror) {
        !          58461:             $found = false;
        !          58462:             foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
        !          58463:                 if ($mirror == $mir['attribs']['host']) {
        !          58464:                     $found = true;
        !          58465:                     break;
1.1       misho    58466:                 }
                   58467:             }
                   58468: 
1.1.1.2 ! misho    58469:             if (!$found) {
        !          58470:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
        !          58471:                     array('mirror' => $mirror));
        !          58472:                 return false;
1.1       misho    58473:             }
                   58474: 
1.1.1.2 ! misho    58475:             $this->_channelInfo['mirror'][$i]['attribs']['host'] = $server;
        !          58476:             return true;
1.1       misho    58477:         }
1.1.1.2 ! misho    58478: 
        !          58479:         $this->_channelInfo['name'] = $server;
        !          58480:         return true;
1.1       misho    58481:     }
                   58482: 
                   58483:     /**
1.1.1.2 ! misho    58484:      * @param string
        !          58485:      * @return boolean success
        !          58486:      * @error PEAR_CHANNELFILE_ERROR_NO_SUMMARY
        !          58487:      * @warning PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY
        !          58488:      */
        !          58489:     function setSummary($summary)
1.1       misho    58490:     {
1.1.1.2 ! misho    58491:         if (empty($summary)) {
        !          58492:             $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY);
        !          58493:             return false;
        !          58494:         } elseif (strpos(trim($summary), "\n") !== false) {
        !          58495:             $this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY,
        !          58496:                 array('summary' => $summary));
1.1       misho    58497:         }
                   58498: 
1.1.1.2 ! misho    58499:         $this->_channelInfo['summary'] = $summary;
        !          58500:         return true;
        !          58501:     }
1.1       misho    58502: 
1.1.1.2 ! misho    58503:     /**
        !          58504:      * @param string
        !          58505:      * @param boolean determines whether the alias is in channel.xml or local
        !          58506:      * @return boolean success
        !          58507:      */
        !          58508:     function setAlias($alias, $local = false)
        !          58509:     {
        !          58510:         if (!$this->validChannelServer($alias)) {
        !          58511:             $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
        !          58512:                 array('tag' => 'suggestedalias', 'name' => $alias));
        !          58513:             return false;
1.1       misho    58514:         }
                   58515: 
1.1.1.2 ! misho    58516:         if ($local) {
        !          58517:             $this->_channelInfo['localalias'] = $alias;
        !          58518:         } else {
        !          58519:             $this->_channelInfo['suggestedalias'] = $alias;
1.1       misho    58520:         }
                   58521: 
1.1.1.2 ! misho    58522:         return true;
1.1       misho    58523:     }
                   58524: 
                   58525:     /**
1.1.1.2 ! misho    58526:      * @return string
1.1       misho    58527:      */
1.1.1.2 ! misho    58528:     function getAlias()
1.1       misho    58529:     {
1.1.1.2 ! misho    58530:         if (isset($this->_channelInfo['localalias'])) {
        !          58531:             return $this->_channelInfo['localalias'];
1.1       misho    58532:         }
1.1.1.2 ! misho    58533:         if (isset($this->_channelInfo['suggestedalias'])) {
        !          58534:             return $this->_channelInfo['suggestedalias'];
        !          58535:         }
        !          58536:         if (isset($this->_channelInfo['name'])) {
        !          58537:             return $this->_channelInfo['name'];
        !          58538:         }
        !          58539:         return '';
1.1       misho    58540:     }
                   58541: 
1.1.1.2 ! misho    58542:     /**
        !          58543:      * Set the package validation object if it differs from PEAR's default
        !          58544:      * The class must be includeable via changing _ in the classname to path separator,
        !          58545:      * but no checking of this is made.
        !          58546:      * @param string|false pass in false to reset to the default packagename regex
        !          58547:      * @return boolean success
        !          58548:      */
        !          58549:     function setValidationPackage($validateclass, $version)
1.1       misho    58550:     {
1.1.1.2 ! misho    58551:         if (empty($validateclass)) {
        !          58552:             unset($this->_channelInfo['validatepackage']);
        !          58553:         }
        !          58554:         $this->_channelInfo['validatepackage'] = array('_content' => $validateclass);
        !          58555:         $this->_channelInfo['validatepackage']['attribs'] = array('version' => $version);
        !          58556:     }
1.1       misho    58557: 
1.1.1.2 ! misho    58558:     /**
        !          58559:      * Add a protocol to the provides section
        !          58560:      * @param string protocol type
        !          58561:      * @param string protocol version
        !          58562:      * @param string protocol name, if any
        !          58563:      * @param string mirror name, if this is a mirror's protocol
        !          58564:      * @return bool
        !          58565:      */
        !          58566:     function addFunction($type, $version, $name = '', $mirror = false)
        !          58567:     {
        !          58568:         if ($mirror) {
        !          58569:             return $this->addMirrorFunction($mirror, $type, $version, $name);
        !          58570:         }
        !          58571: 
        !          58572:         $set = array('attribs' => array('version' => $version), '_content' => $name);
        !          58573:         if (!isset($this->_channelInfo['servers']['primary'][$type]['function'])) {
        !          58574:             if (!isset($this->_channelInfo['servers'])) {
        !          58575:                 $this->_channelInfo['servers'] = array('primary' =>
        !          58576:                     array($type => array()));
        !          58577:             } elseif (!isset($this->_channelInfo['servers']['primary'])) {
        !          58578:                 $this->_channelInfo['servers']['primary'] = array($type => array());
        !          58579:             }
        !          58580: 
        !          58581:             $this->_channelInfo['servers']['primary'][$type]['function'] = $set;
        !          58582:             $this->_isValid = false;
        !          58583:             return true;
        !          58584:         } elseif (!isset($this->_channelInfo['servers']['primary'][$type]['function'][0])) {
        !          58585:             $this->_channelInfo['servers']['primary'][$type]['function'] = array(
        !          58586:                 $this->_channelInfo['servers']['primary'][$type]['function']);
        !          58587:         }
        !          58588: 
        !          58589:         $this->_channelInfo['servers']['primary'][$type]['function'][] = $set;
        !          58590:         return true;
        !          58591:     }
        !          58592:     /**
        !          58593:      * Add a protocol to a mirror's provides section
        !          58594:      * @param string mirror name (server)
        !          58595:      * @param string protocol type
        !          58596:      * @param string protocol version
        !          58597:      * @param string protocol name, if any
        !          58598:      */
        !          58599:     function addMirrorFunction($mirror, $type, $version, $name = '')
        !          58600:     {
        !          58601:         if (!isset($this->_channelInfo['servers']['mirror'])) {
        !          58602:             $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
        !          58603:                 array('mirror' => $mirror));
        !          58604:             return false;
        !          58605:         }
        !          58606: 
        !          58607:         $setmirror = false;
        !          58608:         if (isset($this->_channelInfo['servers']['mirror'][0])) {
        !          58609:             foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
        !          58610:                 if ($mirror == $mir['attribs']['host']) {
        !          58611:                     $setmirror = &$this->_channelInfo['servers']['mirror'][$i];
1.1       misho    58612:                     break;
                   58613:                 }
                   58614:             }
                   58615:         } else {
1.1.1.2 ! misho    58616:             if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
        !          58617:                 $setmirror = &$this->_channelInfo['servers']['mirror'];
        !          58618:             }
1.1       misho    58619:         }
                   58620: 
1.1.1.2 ! misho    58621:         if (!$setmirror) {
        !          58622:             $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
        !          58623:                 array('mirror' => $mirror));
        !          58624:             return false;
        !          58625:         }
        !          58626: 
        !          58627:         $set = array('attribs' => array('version' => $version), '_content' => $name);
        !          58628:         if (!isset($setmirror[$type]['function'])) {
        !          58629:             $setmirror[$type]['function'] = $set;
        !          58630:             $this->_isValid = false;
        !          58631:             return true;
        !          58632:         } elseif (!isset($setmirror[$type]['function'][0])) {
        !          58633:             $setmirror[$type]['function'] = array($setmirror[$type]['function']);
        !          58634:         }
        !          58635: 
        !          58636:         $setmirror[$type]['function'][] = $set;
        !          58637:         $this->_isValid = false;
        !          58638:         return true;
        !          58639:     }
        !          58640: 
        !          58641:     /**
        !          58642:      * @param string Resource Type this url links to
        !          58643:      * @param string URL
        !          58644:      * @param string|false mirror name, if this is not a primary server REST base URL
        !          58645:      */
        !          58646:     function setBaseURL($resourceType, $url, $mirror = false)
        !          58647:     {
        !          58648:         if ($mirror) {
        !          58649:             if (!isset($this->_channelInfo['servers']['mirror'])) {
        !          58650:                 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
        !          58651:                     array('mirror' => $mirror));
        !          58652:                 return false;
        !          58653:             }
        !          58654: 
        !          58655:             $setmirror = false;
        !          58656:             if (isset($this->_channelInfo['servers']['mirror'][0])) {
        !          58657:                 foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
        !          58658:                     if ($mirror == $mir['attribs']['host']) {
        !          58659:                         $setmirror = &$this->_channelInfo['servers']['mirror'][$i];
        !          58660:                         break;
        !          58661:                     }
        !          58662:                 }
        !          58663:             } else {
        !          58664:                 if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
        !          58665:                     $setmirror = &$this->_channelInfo['servers']['mirror'];
        !          58666:                 }
        !          58667:             }
        !          58668:         } else {
        !          58669:             $setmirror = &$this->_channelInfo['servers']['primary'];
        !          58670:         }
        !          58671: 
        !          58672:         $set = array('attribs' => array('type' => $resourceType), '_content' => $url);
        !          58673:         if (!isset($setmirror['rest'])) {
        !          58674:             $setmirror['rest'] = array();
        !          58675:         }
        !          58676: 
        !          58677:         if (!isset($setmirror['rest']['baseurl'])) {
        !          58678:             $setmirror['rest']['baseurl'] = $set;
        !          58679:             $this->_isValid = false;
        !          58680:             return true;
        !          58681:         } elseif (!isset($setmirror['rest']['baseurl'][0])) {
        !          58682:             $setmirror['rest']['baseurl'] = array($setmirror['rest']['baseurl']);
        !          58683:         }
        !          58684: 
        !          58685:         foreach ($setmirror['rest']['baseurl'] as $i => $url) {
        !          58686:             if ($url['attribs']['type'] == $resourceType) {
        !          58687:                 $this->_isValid = false;
        !          58688:                 $setmirror['rest']['baseurl'][$i] = $set;
        !          58689:                 return true;
        !          58690:             }
        !          58691:         }
        !          58692: 
        !          58693:         $setmirror['rest']['baseurl'][] = $set;
        !          58694:         $this->_isValid = false;
        !          58695:         return true;
        !          58696:     }
        !          58697: 
        !          58698:     /**
        !          58699:      * @param string mirror server
        !          58700:      * @param int mirror http port
        !          58701:      * @return boolean
        !          58702:      */
        !          58703:     function addMirror($server, $port = null)
        !          58704:     {
        !          58705:         if ($this->_channelInfo['name'] == '__uri') {
        !          58706:             return false; // the __uri channel cannot have mirrors by definition
        !          58707:         }
        !          58708: 
        !          58709:         $set = array('attribs' => array('host' => $server));
        !          58710:         if (is_numeric($port)) {
        !          58711:             $set['attribs']['port'] = $port;
        !          58712:         }
        !          58713: 
        !          58714:         if (!isset($this->_channelInfo['servers']['mirror'])) {
        !          58715:             $this->_channelInfo['servers']['mirror'] = $set;
        !          58716:             return true;
        !          58717:         }
        !          58718: 
        !          58719:         if (!isset($this->_channelInfo['servers']['mirror'][0])) {
        !          58720:             $this->_channelInfo['servers']['mirror'] =
        !          58721:                 array($this->_channelInfo['servers']['mirror']);
        !          58722:         }
        !          58723: 
        !          58724:         $this->_channelInfo['servers']['mirror'][] = $set;
        !          58725:         return true;
        !          58726:     }
        !          58727: 
        !          58728:     /**
        !          58729:      * Retrieve the name of the validation package for this channel
        !          58730:      * @return string|false
        !          58731:      */
        !          58732:     function getValidationPackage()
        !          58733:     {
        !          58734:         if (!$this->_isValid && !$this->validate()) {
        !          58735:             return false;
        !          58736:         }
        !          58737: 
        !          58738:         if (!isset($this->_channelInfo['validatepackage'])) {
        !          58739:             return array('attribs' => array('version' => 'default'),
        !          58740:                 '_content' => 'PEAR_Validate');
        !          58741:         }
        !          58742: 
        !          58743:         return $this->_channelInfo['validatepackage'];
        !          58744:     }
        !          58745: 
        !          58746:     /**
        !          58747:      * Retrieve the object that can be used for custom validation
        !          58748:      * @param string|false the name of the package to validate.  If the package is
        !          58749:      *                     the channel validation package, PEAR_Validate is returned
        !          58750:      * @return PEAR_Validate|false false is returned if the validation package
        !          58751:      *         cannot be located
        !          58752:      */
        !          58753:     function &getValidationObject($package = false)
        !          58754:     {
        !          58755:         if (!class_exists('PEAR_Validate')) {
        !          58756:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Validate.php';
        !          58757:         }
        !          58758: 
        !          58759:         if (!$this->_isValid) {
        !          58760:             if (!$this->validate()) {
        !          58761:                 $a = false;
        !          58762:                 return $a;
        !          58763:             }
        !          58764:         }
        !          58765: 
        !          58766:         if (isset($this->_channelInfo['validatepackage'])) {
        !          58767:             if ($package == $this->_channelInfo['validatepackage']) {
        !          58768:                 // channel validation packages are always validated by PEAR_Validate
        !          58769:                 $val = &new PEAR_Validate;
        !          58770:                 return $val;
        !          58771:             }
        !          58772: 
        !          58773:             if (!class_exists(str_replace('.', '_',
        !          58774:                   $this->_channelInfo['validatepackage']['_content']))) {
        !          58775:                 if ($this->isIncludeable(str_replace('_', '/',
        !          58776:                       $this->_channelInfo['validatepackage']['_content']) . '.php')) {
        !          58777:                     include_once 'phar://install-pear-nozlib.phar/' . str_replace('_', '/',
        !          58778:                         $this->_channelInfo['validatepackage']['_content']) . '.php';
        !          58779:                     $vclass = str_replace('.', '_',
        !          58780:                         $this->_channelInfo['validatepackage']['_content']);
        !          58781:                     $val = &new $vclass;
        !          58782:                 } else {
        !          58783:                     $a = false;
        !          58784:                     return $a;
        !          58785:                 }
        !          58786:             } else {
        !          58787:                 $vclass = str_replace('.', '_',
        !          58788:                     $this->_channelInfo['validatepackage']['_content']);
        !          58789:                 $val = &new $vclass;
        !          58790:             }
        !          58791:         } else {
        !          58792:             $val = &new PEAR_Validate;
        !          58793:         }
        !          58794: 
        !          58795:         return $val;
        !          58796:     }
        !          58797: 
        !          58798:     function isIncludeable($path)
        !          58799:     {
        !          58800:         $possibilities = explode(PATH_SEPARATOR, ini_get('include_path'));
        !          58801:         foreach ($possibilities as $dir) {
        !          58802:             if (file_exists($dir . DIRECTORY_SEPARATOR . $path)
        !          58803:                   && is_readable($dir . DIRECTORY_SEPARATOR . $path)) {
        !          58804:                 return true;
        !          58805:             }
        !          58806:         }
        !          58807: 
        !          58808:         return false;
        !          58809:     }
        !          58810: 
        !          58811:     /**
        !          58812:      * This function is used by the channel updater and retrieves a value set by
        !          58813:      * the registry, or the current time if it has not been set
        !          58814:      * @return string
        !          58815:      */
        !          58816:     function lastModified()
        !          58817:     {
        !          58818:         if (isset($this->_channelInfo['_lastmodified'])) {
        !          58819:             return $this->_channelInfo['_lastmodified'];
        !          58820:         }
        !          58821: 
        !          58822:         return time();
1.1       misho    58823:     }
                   58824: }<?php
                   58825: /**
1.1.1.2 ! misho    58826:  * PEAR_ChannelFile_Parser for parsing channel.xml
1.1       misho    58827:  *
                   58828:  * PHP versions 4 and 5
                   58829:  *
                   58830:  * @category   pear
                   58831:  * @package    PEAR
                   58832:  * @author     Greg Beaver <cellog@php.net>
                   58833:  * @copyright  1997-2009 The Authors
                   58834:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    58835:  * @version    CVS: $Id: Parser.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    58836:  * @link       http://pear.php.net/package/PEAR
1.1.1.2 ! misho    58837:  * @since      File available since Release 1.4.0a1
1.1       misho    58838:  */
                   58839: 
                   58840: /**
1.1.1.2 ! misho    58841:  * base xml parser class
1.1       misho    58842:  */
1.1.1.2 ! misho    58843: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/XMLParser.php';
        !          58844: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
1.1       misho    58845: /**
1.1.1.2 ! misho    58846:  * Parser for channel.xml
1.1       misho    58847:  * @category   pear
                   58848:  * @package    PEAR
                   58849:  * @author     Greg Beaver <cellog@php.net>
                   58850:  * @copyright  1997-2009 The Authors
                   58851:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    58852:  * @version    Release: 1.9.4
1.1       misho    58853:  * @link       http://pear.php.net/package/PEAR
1.1.1.2 ! misho    58854:  * @since      Class available since Release 1.4.0a1
1.1       misho    58855:  */
1.1.1.2 ! misho    58856: class PEAR_ChannelFile_Parser extends PEAR_XMLParser
1.1       misho    58857: {
1.1.1.2 ! misho    58858:     var $_config;
        !          58859:     var $_logger;
        !          58860:     var $_registry;
1.1       misho    58861: 
1.1.1.2 ! misho    58862:     function setConfig(&$c)
        !          58863:     {
        !          58864:         $this->_config = &$c;
        !          58865:         $this->_registry = &$c->getRegistry();
        !          58866:     }
1.1       misho    58867: 
1.1.1.2 ! misho    58868:     function setLogger(&$l)
        !          58869:     {
        !          58870:         $this->_logger = &$l;
        !          58871:     }
1.1       misho    58872: 
1.1.1.2 ! misho    58873:     function parse($data, $file)
        !          58874:     {
        !          58875:         if (PEAR::isError($err = parent::parse($data, $file))) {
        !          58876:             return $err;
        !          58877:         }
1.1       misho    58878: 
1.1.1.2 ! misho    58879:         $ret = new PEAR_ChannelFile;
        !          58880:         $ret->setConfig($this->_config);
        !          58881:         if (isset($this->_logger)) {
        !          58882:             $ret->setLogger($this->_logger);
        !          58883:         }
1.1       misho    58884: 
1.1.1.2 ! misho    58885:         $ret->fromArray($this->_unserializedData);
        !          58886:         // make sure the filelist is in the easy to read format needed
        !          58887:         $ret->flattenFilelist();
        !          58888:         $ret->setPackagefile($file, $archive);
        !          58889:         return $ret;
        !          58890:     }
        !          58891: }<?php
        !          58892: /**
        !          58893:  * PEAR_Command, command pattern class
        !          58894:  *
        !          58895:  * PHP versions 4 and 5
        !          58896:  *
        !          58897:  * @category   pear
        !          58898:  * @package    PEAR
        !          58899:  * @author     Stig Bakken <ssb@php.net>
        !          58900:  * @author     Greg Beaver <cellog@php.net>
        !          58901:  * @copyright  1997-2009 The Authors
        !          58902:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          58903:  * @version    CVS: $Id: Command.php 313023 2011-07-06 19:17:11Z dufuz $
        !          58904:  * @link       http://pear.php.net/package/PEAR
        !          58905:  * @since      File available since Release 0.1
        !          58906:  */
1.1       misho    58907: 
1.1.1.2 ! misho    58908: /**
        !          58909:  * Needed for error handling
        !          58910:  */
        !          58911: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
        !          58912: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Frontend.php';
        !          58913: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/XMLParser.php';
1.1       misho    58914: 
1.1.1.2 ! misho    58915: /**
        !          58916:  * List of commands and what classes they are implemented in.
        !          58917:  * @var array command => implementing class
        !          58918:  */
        !          58919: $GLOBALS['_PEAR_Command_commandlist'] = array();
1.1       misho    58920: 
1.1.1.2 ! misho    58921: /**
        !          58922:  * List of commands and their descriptions
        !          58923:  * @var array command => description
        !          58924:  */
        !          58925: $GLOBALS['_PEAR_Command_commanddesc'] = array();
1.1       misho    58926: 
1.1.1.2 ! misho    58927: /**
        !          58928:  * List of shortcuts to common commands.
        !          58929:  * @var array shortcut => command
        !          58930:  */
        !          58931: $GLOBALS['_PEAR_Command_shortcuts'] = array();
1.1       misho    58932: 
1.1.1.2 ! misho    58933: /**
        !          58934:  * Array of command objects
        !          58935:  * @var array class => object
        !          58936:  */
        !          58937: $GLOBALS['_PEAR_Command_objects'] = array();
1.1       misho    58938: 
1.1.1.2 ! misho    58939: /**
        !          58940:  * PEAR command class, a simple factory class for administrative
        !          58941:  * commands.
        !          58942:  *
        !          58943:  * How to implement command classes:
        !          58944:  *
        !          58945:  * - The class must be called PEAR_Command_Nnn, installed in the
        !          58946:  *   "PEAR/Common" subdir, with a method called getCommands() that
        !          58947:  *   returns an array of the commands implemented by the class (see
        !          58948:  *   PEAR/Command/Install.php for an example).
        !          58949:  *
        !          58950:  * - The class must implement a run() function that is called with three
        !          58951:  *   params:
        !          58952:  *
        !          58953:  *    (string) command name
        !          58954:  *    (array)  assoc array with options, freely defined by each
        !          58955:  *             command, for example:
        !          58956:  *             array('force' => true)
        !          58957:  *    (array)  list of the other parameters
        !          58958:  *
        !          58959:  *   The run() function returns a PEAR_CommandResponse object.  Use
        !          58960:  *   these methods to get information:
        !          58961:  *
        !          58962:  *    int getStatus()   Returns PEAR_COMMAND_(SUCCESS|FAILURE|PARTIAL)
        !          58963:  *                      *_PARTIAL means that you need to issue at least
        !          58964:  *                      one more command to complete the operation
        !          58965:  *                      (used for example for validation steps).
        !          58966:  *
        !          58967:  *    string getMessage()  Returns a message for the user.  Remember,
        !          58968:  *                         no HTML or other interface-specific markup.
        !          58969:  *
        !          58970:  *   If something unexpected happens, run() returns a PEAR error.
        !          58971:  *
        !          58972:  * - DON'T OUTPUT ANYTHING! Return text for output instead.
        !          58973:  *
        !          58974:  * - DON'T USE HTML! The text you return will be used from both Gtk,
        !          58975:  *   web and command-line interfaces, so for now, keep everything to
        !          58976:  *   plain text.
        !          58977:  *
        !          58978:  * - DON'T USE EXIT OR DIE! Always use pear errors.  From static
        !          58979:  *   classes do PEAR::raiseError(), from other classes do
        !          58980:  *   $this->raiseError().
        !          58981:  * @category   pear
        !          58982:  * @package    PEAR
        !          58983:  * @author     Stig Bakken <ssb@php.net>
        !          58984:  * @author     Greg Beaver <cellog@php.net>
        !          58985:  * @copyright  1997-2009 The Authors
        !          58986:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          58987:  * @version    Release: 1.9.4
        !          58988:  * @link       http://pear.php.net/package/PEAR
        !          58989:  * @since      Class available since Release 0.1
        !          58990:  */
        !          58991: class PEAR_Command
        !          58992: {
        !          58993:     // {{{ factory()
1.1       misho    58994: 
                   58995:     /**
1.1.1.2 ! misho    58996:      * Get the right object for executing a command.
        !          58997:      *
        !          58998:      * @param string $command The name of the command
        !          58999:      * @param object $config  Instance of PEAR_Config object
        !          59000:      *
        !          59001:      * @return object the command object or a PEAR error
1.1       misho    59002:      *
                   59003:      * @access public
1.1.1.2 ! misho    59004:      * @static
1.1       misho    59005:      */
1.1.1.2 ! misho    59006:     function &factory($command, &$config)
1.1       misho    59007:     {
1.1.1.2 ! misho    59008:         if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
        !          59009:             PEAR_Command::registerCommands();
        !          59010:         }
        !          59011:         if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
        !          59012:             $command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
        !          59013:         }
        !          59014:         if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
        !          59015:             $a = PEAR::raiseError("unknown command `$command'");
        !          59016:             return $a;
        !          59017:         }
        !          59018:         $class = $GLOBALS['_PEAR_Command_commandlist'][$command];
        !          59019:         if (!class_exists($class)) {
        !          59020:             require_once $GLOBALS['_PEAR_Command_objects'][$class];
        !          59021:         }
        !          59022:         if (!class_exists($class)) {
        !          59023:             $a = PEAR::raiseError("unknown command `$command'");
        !          59024:             return $a;
        !          59025:         }
        !          59026:         $ui =& PEAR_Command::getFrontendObject();
        !          59027:         $obj = &new $class($ui, $config);
        !          59028:         return $obj;
        !          59029:     }
        !          59030: 
        !          59031:     // }}}
        !          59032:     // {{{ & getObject()
        !          59033:     function &getObject($command)
        !          59034:     {
        !          59035:         $class = $GLOBALS['_PEAR_Command_commandlist'][$command];
        !          59036:         if (!class_exists($class)) {
        !          59037:             require_once $GLOBALS['_PEAR_Command_objects'][$class];
        !          59038:         }
        !          59039:         if (!class_exists($class)) {
        !          59040:             return PEAR::raiseError("unknown command `$command'");
        !          59041:         }
        !          59042:         $ui =& PEAR_Command::getFrontendObject();
        !          59043:         $config = &PEAR_Config::singleton();
        !          59044:         $obj = &new $class($ui, $config);
        !          59045:         return $obj;
1.1       misho    59046:     }
                   59047: 
                   59048:     // }}}
1.1.1.2 ! misho    59049:     // {{{ & getFrontendObject()
1.1       misho    59050: 
                   59051:     /**
1.1.1.2 ! misho    59052:      * Get instance of frontend object.
        !          59053:      *
        !          59054:      * @return object|PEAR_Error
        !          59055:      * @static
1.1       misho    59056:      */
1.1.1.2 ! misho    59057:     function &getFrontendObject()
1.1       misho    59058:     {
1.1.1.2 ! misho    59059:         $a = &PEAR_Frontend::singleton();
1.1       misho    59060:         return $a;
                   59061:     }
                   59062: 
1.1.1.2 ! misho    59063:     // }}}
        !          59064:     // {{{ & setFrontendClass()
        !          59065: 
1.1       misho    59066:     /**
1.1.1.2 ! misho    59067:      * Load current frontend class.
        !          59068:      *
        !          59069:      * @param string $uiclass Name of class implementing the frontend
        !          59070:      *
        !          59071:      * @return object the frontend object, or a PEAR error
        !          59072:      * @static
1.1       misho    59073:      */
1.1.1.2 ! misho    59074:     function &setFrontendClass($uiclass)
1.1       misho    59075:     {
1.1.1.2 ! misho    59076:         $a = &PEAR_Frontend::setFrontendClass($uiclass);
1.1       misho    59077:         return $a;
                   59078:     }
                   59079: 
1.1.1.2 ! misho    59080:     // }}}
        !          59081:     // {{{ setFrontendType()
        !          59082: 
        !          59083:     /**
        !          59084:      * Set current frontend.
        !          59085:      *
        !          59086:      * @param string $uitype Name of the frontend type (for example "CLI")
        !          59087:      *
        !          59088:      * @return object the frontend object, or a PEAR error
        !          59089:      * @static
        !          59090:      */
        !          59091:     function setFrontendType($uitype)
1.1       misho    59092:     {
1.1.1.2 ! misho    59093:         $uiclass = 'PEAR_Frontend_' . $uitype;
        !          59094:         return PEAR_Command::setFrontendClass($uiclass);
1.1       misho    59095:     }
                   59096: 
1.1.1.2 ! misho    59097:     // }}}
        !          59098:     // {{{ registerCommands()
        !          59099: 
        !          59100:     /**
        !          59101:      * Scan through the Command directory looking for classes
        !          59102:      * and see what commands they implement.
        !          59103:      *
        !          59104:      * @param bool   (optional) if FALSE (default), the new list of
        !          59105:      *               commands should replace the current one.  If TRUE,
        !          59106:      *               new entries will be merged with old.
        !          59107:      *
        !          59108:      * @param string (optional) where (what directory) to look for
        !          59109:      *               classes, defaults to the Command subdirectory of
        !          59110:      *               the directory from where this file (__FILE__) is
        !          59111:      *               included.
        !          59112:      *
        !          59113:      * @return bool TRUE on success, a PEAR error on failure
        !          59114:      *
        !          59115:      * @access public
        !          59116:      * @static
        !          59117:      */
        !          59118:     function registerCommands($merge = false, $dir = null)
1.1       misho    59119:     {
1.1.1.2 ! misho    59120:         $parser = new PEAR_XMLParser;
        !          59121:         if ($dir === null) {
        !          59122:             $dir = dirname(__FILE__) . '/Command';
1.1       misho    59123:         }
1.1.1.2 ! misho    59124:         if (!is_dir($dir)) {
        !          59125:             return PEAR::raiseError("registerCommands: opendir($dir) '$dir' does not exist or is not a directory");
1.1       misho    59126:         }
1.1.1.2 ! misho    59127:         $dp = @opendir($dir);
        !          59128:         if (empty($dp)) {
        !          59129:             return PEAR::raiseError("registerCommands: opendir($dir) failed");
1.1       misho    59130:         }
1.1.1.2 ! misho    59131:         if (!$merge) {
        !          59132:             $GLOBALS['_PEAR_Command_commandlist'] = array();
1.1       misho    59133:         }
                   59134: 
1.1.1.2 ! misho    59135:         while ($file = readdir($dp)) {
        !          59136:             if ($file{0} == '.' || substr($file, -4) != '.xml') {
1.1       misho    59137:                 continue;
                   59138:             }
1.1.1.2 ! misho    59139: 
        !          59140:             $f = substr($file, 0, -4);
        !          59141:             $class = "PEAR_Command_" . $f;
        !          59142:             // List of commands
        !          59143:             if (empty($GLOBALS['_PEAR_Command_objects'][$class])) {
        !          59144:                 $GLOBALS['_PEAR_Command_objects'][$class] = "$dir/" . $f . '.php';
1.1       misho    59145:             }
1.1.1.2 ! misho    59146: 
        !          59147:             $parser->parse(file_get_contents("$dir/$file"));
        !          59148:             $implements = $parser->getData();
        !          59149:             foreach ($implements as $command => $desc) {
        !          59150:                 if ($command == 'attribs') {
1.1       misho    59151:                     continue;
                   59152:                 }
1.1.1.2 ! misho    59153: 
        !          59154:                 if (isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
        !          59155:                     return PEAR::raiseError('Command "' . $command . '" already registered in ' .
        !          59156:                         'class "' . $GLOBALS['_PEAR_Command_commandlist'][$command] . '"');
1.1       misho    59157:                 }
1.1.1.2 ! misho    59158: 
        !          59159:                 $GLOBALS['_PEAR_Command_commandlist'][$command] = $class;
        !          59160:                 $GLOBALS['_PEAR_Command_commanddesc'][$command] = $desc['summary'];
        !          59161:                 if (isset($desc['shortcut'])) {
        !          59162:                     $shortcut = $desc['shortcut'];
        !          59163:                     if (isset($GLOBALS['_PEAR_Command_shortcuts'][$shortcut])) {
        !          59164:                         return PEAR::raiseError('Command shortcut "' . $shortcut . '" already ' .
        !          59165:                             'registered to command "' . $command . '" in class "' .
        !          59166:                             $GLOBALS['_PEAR_Command_commandlist'][$command] . '"');
        !          59167:                     }
        !          59168:                     $GLOBALS['_PEAR_Command_shortcuts'][$shortcut] = $command;
        !          59169:                 }
        !          59170: 
        !          59171:                 if (isset($desc['options']) && $desc['options']) {
        !          59172:                     foreach ($desc['options'] as $oname => $option) {
        !          59173:                         if (isset($option['shortopt']) && strlen($option['shortopt']) > 1) {
        !          59174:                             return PEAR::raiseError('Option "' . $oname . '" short option "' .
        !          59175:                                 $option['shortopt'] . '" must be ' .
        !          59176:                                 'only 1 character in Command "' . $command . '" in class "' .
        !          59177:                                 $class . '"');
        !          59178:                         }
        !          59179:                     }
1.1       misho    59180:                 }
                   59181:             }
                   59182:         }
                   59183: 
1.1.1.2 ! misho    59184:         ksort($GLOBALS['_PEAR_Command_shortcuts']);
        !          59185:         ksort($GLOBALS['_PEAR_Command_commandlist']);
        !          59186:         @closedir($dp);
        !          59187:         return true;
        !          59188:     }
1.1       misho    59189: 
1.1.1.2 ! misho    59190:     // }}}
        !          59191:     // {{{ getCommands()
        !          59192: 
        !          59193:     /**
        !          59194:      * Get the list of currently supported commands, and what
        !          59195:      * classes implement them.
        !          59196:      *
        !          59197:      * @return array command => implementing class
        !          59198:      *
        !          59199:      * @access public
        !          59200:      * @static
        !          59201:      */
        !          59202:     function getCommands()
1.1       misho    59203:     {
1.1.1.2 ! misho    59204:         if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
        !          59205:             PEAR_Command::registerCommands();
1.1       misho    59206:         }
1.1.1.2 ! misho    59207:         return $GLOBALS['_PEAR_Command_commandlist'];
        !          59208:     }
1.1       misho    59209: 
1.1.1.2 ! misho    59210:     // }}}
        !          59211:     // {{{ getShortcuts()
1.1       misho    59212: 
1.1.1.2 ! misho    59213:     /**
        !          59214:      * Get the list of command shortcuts.
        !          59215:      *
        !          59216:      * @return array shortcut => command
        !          59217:      *
        !          59218:      * @access public
        !          59219:      * @static
        !          59220:      */
        !          59221:     function getShortcuts()
        !          59222:     {
        !          59223:         if (empty($GLOBALS['_PEAR_Command_shortcuts'])) {
        !          59224:             PEAR_Command::registerCommands();
1.1       misho    59225:         }
1.1.1.2 ! misho    59226:         return $GLOBALS['_PEAR_Command_shortcuts'];
        !          59227:     }
1.1       misho    59228: 
1.1.1.2 ! misho    59229:     // }}}
        !          59230:     // {{{ getGetoptArgs()
1.1       misho    59231: 
1.1.1.2 ! misho    59232:     /**
        !          59233:      * Compiles arguments for getopt.
        !          59234:      *
        !          59235:      * @param string $command     command to get optstring for
        !          59236:      * @param string $short_args  (reference) short getopt format
        !          59237:      * @param array  $long_args   (reference) long getopt format
        !          59238:      *
        !          59239:      * @return void
        !          59240:      *
        !          59241:      * @access public
        !          59242:      * @static
        !          59243:      */
        !          59244:     function getGetoptArgs($command, &$short_args, &$long_args)
        !          59245:     {
        !          59246:         if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
        !          59247:             PEAR_Command::registerCommands();
1.1       misho    59248:         }
1.1.1.2 ! misho    59249:         if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
        !          59250:             $command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
        !          59251:         }
        !          59252:         if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
        !          59253:             return null;
1.1       misho    59254:         }
1.1.1.2 ! misho    59255:         $obj = &PEAR_Command::getObject($command);
        !          59256:         return $obj->getGetoptArgs($command, $short_args, $long_args);
        !          59257:     }
1.1       misho    59258: 
1.1.1.2 ! misho    59259:     // }}}
        !          59260:     // {{{ getDescription()
1.1       misho    59261: 
1.1.1.2 ! misho    59262:     /**
        !          59263:      * Get description for a command.
        !          59264:      *
        !          59265:      * @param  string $command Name of the command
        !          59266:      *
        !          59267:      * @return string command description
        !          59268:      *
        !          59269:      * @access public
        !          59270:      * @static
        !          59271:      */
        !          59272:     function getDescription($command)
        !          59273:     {
        !          59274:         if (!isset($GLOBALS['_PEAR_Command_commanddesc'][$command])) {
        !          59275:             return null;
        !          59276:         }
        !          59277:         return $GLOBALS['_PEAR_Command_commanddesc'][$command];
        !          59278:     }
1.1       misho    59279: 
1.1.1.2 ! misho    59280:     // }}}
        !          59281:     // {{{ getHelp()
1.1       misho    59282: 
1.1.1.2 ! misho    59283:     /**
        !          59284:      * Get help for command.
        !          59285:      *
        !          59286:      * @param string $command Name of the command to return help for
        !          59287:      *
        !          59288:      * @access public
        !          59289:      * @static
        !          59290:      */
        !          59291:     function getHelp($command)
        !          59292:     {
        !          59293:         $cmds = PEAR_Command::getCommands();
        !          59294:         if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
        !          59295:             $command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
        !          59296:         }
        !          59297:         if (isset($cmds[$command])) {
        !          59298:             $obj = &PEAR_Command::getObject($command);
        !          59299:             return $obj->getHelp($command);
        !          59300:         }
        !          59301:         return false;
        !          59302:     }
        !          59303:     // }}}
        !          59304: }<?php
        !          59305: /**
        !          59306:  * PEAR_Command_Auth (login, logout commands)
        !          59307:  *
        !          59308:  * PHP versions 4 and 5
        !          59309:  *
        !          59310:  * @category   pear
        !          59311:  * @package    PEAR
        !          59312:  * @author     Stig Bakken <ssb@php.net>
        !          59313:  * @author     Greg Beaver <cellog@php.net>
        !          59314:  * @copyright  1997-2009 The Authors
        !          59315:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          59316:  * @version    CVS: $Id: Auth.php 313023 2011-07-06 19:17:11Z dufuz $
        !          59317:  * @link       http://pear.php.net/package/PEAR
        !          59318:  * @since      File available since Release 0.1
        !          59319:  * @deprecated since 1.8.0alpha1
        !          59320:  */
1.1       misho    59321: 
1.1.1.2 ! misho    59322: /**
        !          59323:  * base class
        !          59324:  */
        !          59325: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Channels.php';
1.1       misho    59326: 
1.1.1.2 ! misho    59327: /**
        !          59328:  * PEAR commands for login/logout
        !          59329:  *
        !          59330:  * @category   pear
        !          59331:  * @package    PEAR
        !          59332:  * @author     Stig Bakken <ssb@php.net>
        !          59333:  * @author     Greg Beaver <cellog@php.net>
        !          59334:  * @copyright  1997-2009 The Authors
        !          59335:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          59336:  * @version    Release: 1.9.4
        !          59337:  * @link       http://pear.php.net/package/PEAR
        !          59338:  * @since      Class available since Release 0.1
        !          59339:  * @deprecated since 1.8.0alpha1
        !          59340:  */
        !          59341: class PEAR_Command_Auth extends PEAR_Command_Channels
        !          59342: {
        !          59343:     var $commands = array(
        !          59344:         'login' => array(
        !          59345:             'summary' => 'Connects and authenticates to remote server [Deprecated in favor of channel-login]',
        !          59346:             'shortcut' => 'li',
        !          59347:             'function' => 'doLogin',
        !          59348:             'options' => array(),
        !          59349:             'doc' => '<channel name>
        !          59350: WARNING: This function is deprecated in favor of using channel-login
1.1       misho    59351: 
1.1.1.2 ! misho    59352: Log in to a remote channel server.  If <channel name> is not supplied,
        !          59353: the default channel is used. To use remote functions in the installer
        !          59354: that require any kind of privileges, you need to log in first.  The
        !          59355: username and password you enter here will be stored in your per-user
        !          59356: PEAR configuration (~/.pearrc on Unix-like systems).  After logging
        !          59357: in, your username and password will be sent along in subsequent
        !          59358: operations on the remote server.',
        !          59359:             ),
        !          59360:         'logout' => array(
        !          59361:             'summary' => 'Logs out from the remote server [Deprecated in favor of channel-logout]',
        !          59362:             'shortcut' => 'lo',
        !          59363:             'function' => 'doLogout',
        !          59364:             'options' => array(),
        !          59365:             'doc' => '
        !          59366: WARNING: This function is deprecated in favor of using channel-logout
1.1       misho    59367: 
1.1.1.2 ! misho    59368: Logs out from the remote server.  This command does not actually
        !          59369: connect to the remote server, it only deletes the stored username and
        !          59370: password from your user configuration.',
        !          59371:             )
1.1       misho    59372: 
1.1.1.2 ! misho    59373:         );
1.1       misho    59374: 
1.1.1.2 ! misho    59375:     /**
        !          59376:      * PEAR_Command_Auth constructor.
        !          59377:      *
        !          59378:      * @access public
        !          59379:      */
        !          59380:     function PEAR_Command_Auth(&$ui, &$config)
        !          59381:     {
        !          59382:         parent::PEAR_Command_Channels($ui, $config);
        !          59383:     }
        !          59384: }<commands version="1.0">
        !          59385:  <login>
        !          59386:   <summary>Connects and authenticates to remote server [Deprecated in favor of channel-login]</summary>
        !          59387:   <function>doLogin</function>
        !          59388:   <shortcut>li</shortcut>
        !          59389:   <options />
        !          59390:   <doc>&lt;channel name&gt;
        !          59391: WARNING: This function is deprecated in favor of using channel-login
1.1       misho    59392: 
1.1.1.2 ! misho    59393: Log in to a remote channel server.  If &lt;channel name&gt; is not supplied,
        !          59394: the default channel is used. To use remote functions in the installer
        !          59395: that require any kind of privileges, you need to log in first.  The
        !          59396: username and password you enter here will be stored in your per-user
        !          59397: PEAR configuration (~/.pearrc on Unix-like systems).  After logging
        !          59398: in, your username and password will be sent along in subsequent
        !          59399: operations on the remote server.</doc>
        !          59400:  </login>
        !          59401:  <logout>
        !          59402:   <summary>Logs out from the remote server [Deprecated in favor of channel-logout]</summary>
        !          59403:   <function>doLogout</function>
        !          59404:   <shortcut>lo</shortcut>
        !          59405:   <options />
        !          59406:   <doc>
        !          59407: WARNING: This function is deprecated in favor of using channel-logout
1.1       misho    59408: 
1.1.1.2 ! misho    59409: Logs out from the remote server.  This command does not actually
        !          59410: connect to the remote server, it only deletes the stored username and
        !          59411: password from your user configuration.</doc>
        !          59412:  </logout>
        !          59413: </commands><?php
        !          59414: /**
        !          59415:  * PEAR_Command_Auth (build command)
        !          59416:  *
        !          59417:  * PHP versions 4 and 5
        !          59418:  *
        !          59419:  * @category   pear
        !          59420:  * @package    PEAR
        !          59421:  * @author     Stig Bakken <ssb@php.net>
        !          59422:  * @author     Tomas V.V.Cox <cox@idecnet.com>
        !          59423:  * @author     Greg Beaver <cellog@php.net>
        !          59424:  * @copyright  1997-2009 The Authors
        !          59425:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          59426:  * @version    CVS: $Id: Build.php 313023 2011-07-06 19:17:11Z dufuz $
        !          59427:  * @link       http://pear.php.net/package/PEAR
        !          59428:  * @since      File available since Release 0.1
        !          59429:  */
1.1       misho    59430: 
1.1.1.2 ! misho    59431: /**
        !          59432:  * base class
        !          59433:  */
        !          59434: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Common.php';
1.1       misho    59435: 
1.1.1.2 ! misho    59436: /**
        !          59437:  * PEAR commands for building extensions.
        !          59438:  *
        !          59439:  * @category   pear
        !          59440:  * @package    PEAR
        !          59441:  * @author     Stig Bakken <ssb@php.net>
        !          59442:  * @author     Tomas V.V.Cox <cox@idecnet.com>
        !          59443:  * @author     Greg Beaver <cellog@php.net>
        !          59444:  * @copyright  1997-2009 The Authors
        !          59445:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          59446:  * @version    Release: 1.9.4
        !          59447:  * @link       http://pear.php.net/package/PEAR
        !          59448:  * @since      Class available since Release 0.1
        !          59449:  */
        !          59450: class PEAR_Command_Build extends PEAR_Command_Common
        !          59451: {
        !          59452:     var $commands = array(
        !          59453:         'build' => array(
        !          59454:             'summary' => 'Build an Extension From C Source',
        !          59455:             'function' => 'doBuild',
        !          59456:             'shortcut' => 'b',
        !          59457:             'options' => array(),
        !          59458:             'doc' => '[package.xml]
        !          59459: Builds one or more extensions contained in a package.'
        !          59460:             ),
1.1       misho    59461:         );
                   59462: 
1.1.1.2 ! misho    59463:     /**
        !          59464:      * PEAR_Command_Build constructor.
        !          59465:      *
        !          59466:      * @access public
        !          59467:      */
        !          59468:     function PEAR_Command_Build(&$ui, &$config)
        !          59469:     {
        !          59470:         parent::PEAR_Command_Common($ui, $config);
        !          59471:     }
1.1       misho    59472: 
1.1.1.2 ! misho    59473:     function doBuild($command, $options, $params)
        !          59474:     {
        !          59475:         require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Builder.php';
        !          59476:         if (sizeof($params) < 1) {
        !          59477:             $params[0] = 'package.xml';
1.1       misho    59478:         }
                   59479: 
1.1.1.2 ! misho    59480:         $builder = &new PEAR_Builder($this->ui);
        !          59481:         $this->debug = $this->config->get('verbose');
        !          59482:         $err = $builder->build($params[0], array(&$this, 'buildCallback'));
        !          59483:         if (PEAR::isError($err)) {
        !          59484:             return $err;
        !          59485:         }
1.1       misho    59486: 
1.1.1.2 ! misho    59487:         return true;
        !          59488:     }
1.1       misho    59489: 
1.1.1.2 ! misho    59490:     function buildCallback($what, $data)
        !          59491:     {
        !          59492:         if (($what == 'cmdoutput' && $this->debug > 1) ||
        !          59493:             ($what == 'output' && $this->debug > 0)) {
        !          59494:             $this->ui->outputData(rtrim($data), 'build');
        !          59495:         }
        !          59496:     }
        !          59497: }<commands version="1.0">
        !          59498:  <build>
        !          59499:   <summary>Build an Extension From C Source</summary>
        !          59500:   <function>doBuild</function>
        !          59501:   <shortcut>b</shortcut>
        !          59502:   <options />
        !          59503:   <doc>[package.xml]
        !          59504: Builds one or more extensions contained in a package.</doc>
        !          59505:  </build>
        !          59506: </commands><?php
        !          59507: // /* vim: set expandtab tabstop=4 shiftwidth=4: */
        !          59508: /**
        !          59509:  * PEAR_Command_Channels (list-channels, update-channels, channel-delete, channel-add,
        !          59510:  * channel-update, channel-info, channel-alias, channel-discover commands)
        !          59511:  *
        !          59512:  * PHP versions 4 and 5
        !          59513:  *
        !          59514:  * @category   pear
        !          59515:  * @package    PEAR
        !          59516:  * @author     Stig Bakken <ssb@php.net>
        !          59517:  * @author     Greg Beaver <cellog@php.net>
        !          59518:  * @copyright  1997-2009 The Authors
        !          59519:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          59520:  * @version    CVS: $Id: Channels.php 313023 2011-07-06 19:17:11Z dufuz $
        !          59521:  * @link       http://pear.php.net/package/PEAR
        !          59522:  * @since      File available since Release 1.4.0a1
        !          59523:  */
1.1       misho    59524: 
1.1.1.2 ! misho    59525: /**
        !          59526:  * base class
        !          59527:  */
        !          59528: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Common.php';
1.1       misho    59529: 
1.1.1.2 ! misho    59530: define('PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS', -500);
1.1       misho    59531: 
1.1.1.2 ! misho    59532: /**
        !          59533:  * PEAR commands for managing channels.
        !          59534:  *
        !          59535:  * @category   pear
        !          59536:  * @package    PEAR
        !          59537:  * @author     Greg Beaver <cellog@php.net>
        !          59538:  * @copyright  1997-2009 The Authors
        !          59539:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          59540:  * @version    Release: 1.9.4
        !          59541:  * @link       http://pear.php.net/package/PEAR
        !          59542:  * @since      Class available since Release 1.4.0a1
        !          59543:  */
        !          59544: class PEAR_Command_Channels extends PEAR_Command_Common
        !          59545: {
        !          59546:     var $commands = array(
        !          59547:         'list-channels' => array(
        !          59548:             'summary' => 'List Available Channels',
        !          59549:             'function' => 'doList',
        !          59550:             'shortcut' => 'lc',
        !          59551:             'options' => array(),
        !          59552:             'doc' => '
        !          59553: List all available channels for installation.
        !          59554: ',
        !          59555:             ),
        !          59556:         'update-channels' => array(
        !          59557:             'summary' => 'Update the Channel List',
        !          59558:             'function' => 'doUpdateAll',
        !          59559:             'shortcut' => 'uc',
        !          59560:             'options' => array(),
        !          59561:             'doc' => '
        !          59562: List all installed packages in all channels.
        !          59563: '
        !          59564:             ),
        !          59565:         'channel-delete' => array(
        !          59566:             'summary' => 'Remove a Channel From the List',
        !          59567:             'function' => 'doDelete',
        !          59568:             'shortcut' => 'cde',
        !          59569:             'options' => array(),
        !          59570:             'doc' => '<channel name>
        !          59571: Delete a channel from the registry.  You may not
        !          59572: remove any channel that has installed packages.
        !          59573: '
        !          59574:             ),
        !          59575:         'channel-add' => array(
        !          59576:             'summary' => 'Add a Channel',
        !          59577:             'function' => 'doAdd',
        !          59578:             'shortcut' => 'ca',
        !          59579:             'options' => array(),
        !          59580:             'doc' => '<channel.xml>
        !          59581: Add a private channel to the channel list.  Note that all
        !          59582: public channels should be synced using "update-channels".
        !          59583: Parameter may be either a local file or remote URL to a
        !          59584: channel.xml.
        !          59585: '
        !          59586:             ),
        !          59587:         'channel-update' => array(
        !          59588:             'summary' => 'Update an Existing Channel',
        !          59589:             'function' => 'doUpdate',
        !          59590:             'shortcut' => 'cu',
        !          59591:             'options' => array(
        !          59592:                 'force' => array(
        !          59593:                     'shortopt' => 'f',
        !          59594:                     'doc' => 'will force download of new channel.xml if an existing channel name is used',
        !          59595:                     ),
        !          59596:                 'channel' => array(
        !          59597:                     'shortopt' => 'c',
        !          59598:                     'arg' => 'CHANNEL',
        !          59599:                     'doc' => 'will force download of new channel.xml if an existing channel name is used',
        !          59600:                     ),
        !          59601: ),
        !          59602:             'doc' => '[<channel.xml>|<channel name>]
        !          59603: Update a channel in the channel list directly.  Note that all
        !          59604: public channels can be synced using "update-channels".
        !          59605: Parameter may be a local or remote channel.xml, or the name of
        !          59606: an existing channel.
        !          59607: '
        !          59608:             ),
        !          59609:         'channel-info' => array(
        !          59610:             'summary' => 'Retrieve Information on a Channel',
        !          59611:             'function' => 'doInfo',
        !          59612:             'shortcut' => 'ci',
        !          59613:             'options' => array(),
        !          59614:             'doc' => '<package>
        !          59615: List the files in an installed package.
        !          59616: '
        !          59617:             ),
        !          59618:         'channel-alias' => array(
        !          59619:             'summary' => 'Specify an alias to a channel name',
        !          59620:             'function' => 'doAlias',
        !          59621:             'shortcut' => 'cha',
        !          59622:             'options' => array(),
        !          59623:             'doc' => '<channel> <alias>
        !          59624: Specify a specific alias to use for a channel name.
        !          59625: The alias may not be an existing channel name or
        !          59626: alias.
        !          59627: '
        !          59628:             ),
        !          59629:         'channel-discover' => array(
        !          59630:             'summary' => 'Initialize a Channel from its server',
        !          59631:             'function' => 'doDiscover',
        !          59632:             'shortcut' => 'di',
        !          59633:             'options' => array(),
        !          59634:             'doc' => '[<channel.xml>|<channel name>]
        !          59635: Initialize a channel from its server and create a local channel.xml.
        !          59636: If <channel name> is in the format "<username>:<password>@<channel>" then
        !          59637: <username> and <password> will be set as the login username/password for
        !          59638: <channel>. Use caution when passing the username/password in this way, as
        !          59639: it may allow other users on your computer to briefly view your username/
        !          59640: password via the system\'s process list.
        !          59641: '
        !          59642:             ),
        !          59643:         'channel-login' => array(
        !          59644:             'summary' => 'Connects and authenticates to remote channel server',
        !          59645:             'shortcut' => 'cli',
        !          59646:             'function' => 'doLogin',
        !          59647:             'options' => array(),
        !          59648:             'doc' => '<channel name>
        !          59649: Log in to a remote channel server.  If <channel name> is not supplied,
        !          59650: the default channel is used. To use remote functions in the installer
        !          59651: that require any kind of privileges, you need to log in first.  The
        !          59652: username and password you enter here will be stored in your per-user
        !          59653: PEAR configuration (~/.pearrc on Unix-like systems).  After logging
        !          59654: in, your username and password will be sent along in subsequent
        !          59655: operations on the remote server.',
        !          59656:             ),
        !          59657:         'channel-logout' => array(
        !          59658:             'summary' => 'Logs out from the remote channel server',
        !          59659:             'shortcut' => 'clo',
        !          59660:             'function' => 'doLogout',
        !          59661:             'options' => array(),
        !          59662:             'doc' => '<channel name>
        !          59663: Logs out from a remote channel server.  If <channel name> is not supplied,
        !          59664: the default channel is used. This command does not actually connect to the
        !          59665: remote server, it only deletes the stored username and password from your user
        !          59666: configuration.',
        !          59667:             ),
        !          59668:         );
1.1       misho    59669: 
1.1.1.2 ! misho    59670:     /**
        !          59671:      * PEAR_Command_Registry constructor.
        !          59672:      *
        !          59673:      * @access public
        !          59674:      */
        !          59675:     function PEAR_Command_Channels(&$ui, &$config)
        !          59676:     {
        !          59677:         parent::PEAR_Command_Common($ui, $config);
        !          59678:     }
        !          59679: 
        !          59680:     function _sortChannels($a, $b)
        !          59681:     {
        !          59682:         return strnatcasecmp($a->getName(), $b->getName());
        !          59683:     }
        !          59684: 
        !          59685:     function doList($command, $options, $params)
        !          59686:     {
        !          59687:         $reg = &$this->config->getRegistry();
        !          59688:         $registered = $reg->getChannels();
        !          59689:         usort($registered, array(&$this, '_sortchannels'));
        !          59690:         $i = $j = 0;
        !          59691:         $data = array(
        !          59692:             'caption' => 'Registered Channels:',
        !          59693:             'border' => true,
        !          59694:             'headline' => array('Channel', 'Alias', 'Summary')
        !          59695:             );
        !          59696:         foreach ($registered as $channel) {
        !          59697:             $data['data'][] = array($channel->getName(),
        !          59698:                                     $channel->getAlias(),
        !          59699:                                     $channel->getSummary());
        !          59700:         }
        !          59701: 
        !          59702:         if (count($registered) === 0) {
        !          59703:             $data = '(no registered channels)';
        !          59704:         }
        !          59705:         $this->ui->outputData($data, $command);
        !          59706:         return true;
        !          59707:     }
        !          59708: 
        !          59709:     function doUpdateAll($command, $options, $params)
        !          59710:     {
        !          59711:         $reg = &$this->config->getRegistry();
        !          59712:         $channels = $reg->getChannels();
        !          59713: 
        !          59714:         $success = true;
        !          59715:         foreach ($channels as $channel) {
        !          59716:             if ($channel->getName() != '__uri') {
        !          59717:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          59718:                 $err = $this->doUpdate('channel-update',
        !          59719:                                           $options,
        !          59720:                                           array($channel->getName()));
        !          59721:                 if (PEAR::isError($err)) {
        !          59722:                     $this->ui->outputData($err->getMessage(), $command);
        !          59723:                     $success = false;
        !          59724:                 } else {
        !          59725:                     $success &= $err;
1.1       misho    59726:                 }
                   59727:             }
1.1.1.2 ! misho    59728:         }
        !          59729:         return $success;
        !          59730:     }
1.1       misho    59731: 
1.1.1.2 ! misho    59732:     function doInfo($command, $options, $params)
        !          59733:     {
        !          59734:         if (count($params) !== 1) {
        !          59735:             return $this->raiseError("No channel specified");
        !          59736:         }
        !          59737: 
        !          59738:         $reg     = &$this->config->getRegistry();
        !          59739:         $channel = strtolower($params[0]);
        !          59740:         if ($reg->channelExists($channel)) {
        !          59741:             $chan = $reg->getChannel($channel);
        !          59742:             if (PEAR::isError($chan)) {
        !          59743:                 return $this->raiseError($chan);
        !          59744:             }
        !          59745:         } else {
        !          59746:             if (strpos($channel, '://')) {
        !          59747:                 $downloader = &$this->getDownloader();
        !          59748:                 $tmpdir = $this->config->get('temp_dir');
        !          59749:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          59750:                 $loc = $downloader->downloadHttp($channel, $this->ui, $tmpdir);
        !          59751:                 PEAR::staticPopErrorHandling();
        !          59752:                 if (PEAR::isError($loc)) {
        !          59753:                     return $this->raiseError('Cannot open "' . $channel .
        !          59754:                         '" (' . $loc->getMessage() . ')');
        !          59755:                 } else {
        !          59756:                     $contents = implode('', file($loc));
        !          59757:                 }
        !          59758:             } else {
        !          59759:                 if (!file_exists($params[0])) {
        !          59760:                     return $this->raiseError('Unknown channel "' . $channel . '"');
1.1       misho    59761:                 }
                   59762: 
1.1.1.2 ! misho    59763:                 $fp = fopen($params[0], 'r');
        !          59764:                 if (!$fp) {
        !          59765:                     return $this->raiseError('Cannot open "' . $params[0] . '"');
1.1       misho    59766:                 }
                   59767: 
1.1.1.2 ! misho    59768:                 $contents = '';
        !          59769:                 while (!feof($fp)) {
        !          59770:                     $contents .= fread($fp, 1024);
        !          59771:                 }
        !          59772:                 fclose($fp);
        !          59773:             }
1.1       misho    59774: 
1.1.1.2 ! misho    59775:             if (!class_exists('PEAR_ChannelFile')) {
        !          59776:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
        !          59777:             }
1.1       misho    59778: 
1.1.1.2 ! misho    59779:             $chan = new PEAR_ChannelFile;
        !          59780:             $chan->fromXmlString($contents);
        !          59781:             $chan->validate();
        !          59782:             if ($errs = $chan->getErrors(true)) {
        !          59783:                 foreach ($errs as $err) {
        !          59784:                     $this->ui->outputData($err['level'] . ': ' . $err['message']);
1.1       misho    59785:                 }
1.1.1.2 ! misho    59786:                 return $this->raiseError('Channel file "' . $params[0] . '" is not valid');
1.1       misho    59787:             }
1.1.1.2 ! misho    59788:         }
1.1       misho    59789: 
1.1.1.2 ! misho    59790:         if (!$chan) {
        !          59791:             return $this->raiseError('Serious error: Channel "' . $params[0] .
        !          59792:                 '" has a corrupted registry entry');
        !          59793:         }
        !          59794: 
        !          59795:         $channel = $chan->getName();
        !          59796:         $caption = 'Channel ' . $channel . ' Information:';
        !          59797:         $data1 = array(
        !          59798:             'caption' => $caption,
        !          59799:             'border' => true);
        !          59800:         $data1['data']['server'] = array('Name and Server', $chan->getName());
        !          59801:         if ($chan->getAlias() != $chan->getName()) {
        !          59802:             $data1['data']['alias'] = array('Alias', $chan->getAlias());
        !          59803:         }
        !          59804: 
        !          59805:         $data1['data']['summary'] = array('Summary', $chan->getSummary());
        !          59806:         $validate = $chan->getValidationPackage();
        !          59807:         $data1['data']['vpackage'] = array('Validation Package Name', $validate['_content']);
        !          59808:         $data1['data']['vpackageversion'] =
        !          59809:             array('Validation Package Version', $validate['attribs']['version']);
        !          59810:         $d = array();
        !          59811:         $d['main'] = $data1;
        !          59812: 
        !          59813:         $data['data'] = array();
        !          59814:         $data['caption'] = 'Server Capabilities';
        !          59815:         $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
        !          59816:         if ($chan->supportsREST()) {
        !          59817:             if ($chan->supportsREST()) {
        !          59818:                 $funcs = $chan->getFunctions('rest');
        !          59819:                 if (!isset($funcs[0])) {
        !          59820:                     $funcs = array($funcs);
        !          59821:                 }
        !          59822:                 foreach ($funcs as $protocol) {
        !          59823:                     $data['data'][] = array('rest', $protocol['attribs']['type'],
        !          59824:                         $protocol['_content']);
1.1       misho    59825:                 }
                   59826:             }
1.1.1.2 ! misho    59827:         } else {
        !          59828:             $data['data'][] = array('No supported protocols');
1.1       misho    59829:         }
                   59830: 
1.1.1.2 ! misho    59831:         $d['protocols'] = $data;
        !          59832:         $data['data'] = array();
        !          59833:         $mirrors = $chan->getMirrors();
        !          59834:         if ($mirrors) {
        !          59835:             $data['caption'] = 'Channel ' . $channel . ' Mirrors:';
        !          59836:             unset($data['headline']);
        !          59837:             foreach ($mirrors as $mirror) {
        !          59838:                 $data['data'][] = array($mirror['attribs']['host']);
        !          59839:                 $d['mirrors'] = $data;
1.1       misho    59840:             }
                   59841: 
1.1.1.2 ! misho    59842:             foreach ($mirrors as $i => $mirror) {
        !          59843:                 $data['data'] = array();
        !          59844:                 $data['caption'] = 'Mirror ' . $mirror['attribs']['host'] . ' Capabilities';
        !          59845:                 $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
        !          59846:                 if ($chan->supportsREST($mirror['attribs']['host'])) {
        !          59847:                     if ($chan->supportsREST($mirror['attribs']['host'])) {
        !          59848:                         $funcs = $chan->getFunctions('rest', $mirror['attribs']['host']);
        !          59849:                         if (!isset($funcs[0])) {
        !          59850:                             $funcs = array($funcs);
        !          59851:                         }
        !          59852: 
        !          59853:                         foreach ($funcs as $protocol) {
        !          59854:                             $data['data'][] = array('rest', $protocol['attribs']['type'],
        !          59855:                                 $protocol['_content']);
        !          59856:                         }
        !          59857:                     }
        !          59858:                 } else {
        !          59859:                     $data['data'][] = array('No supported protocols');
        !          59860:                 }
        !          59861:                 $d['mirrorprotocols' . $i] = $data;
        !          59862:             }
        !          59863:         }
        !          59864:         $this->ui->outputData($d, 'channel-info');
1.1       misho    59865:     }
                   59866: 
                   59867:     // }}}
                   59868: 
1.1.1.2 ! misho    59869:     function doDelete($command, $options, $params)
1.1       misho    59870:     {
1.1.1.2 ! misho    59871:         if (count($params) !== 1) {
        !          59872:             return $this->raiseError('channel-delete: no channel specified');
        !          59873:         }
        !          59874: 
1.1       misho    59875:         $reg = &$this->config->getRegistry();
1.1.1.2 ! misho    59876:         if (!$reg->channelExists($params[0])) {
        !          59877:             return $this->raiseError('channel-delete: channel "' . $params[0] . '" does not exist');
        !          59878:         }
1.1       misho    59879: 
1.1.1.2 ! misho    59880:         $channel = $reg->channelName($params[0]);
        !          59881:         if ($channel == 'pear.php.net') {
        !          59882:             return $this->raiseError('Cannot delete the pear.php.net channel');
1.1       misho    59883:         }
                   59884: 
1.1.1.2 ! misho    59885:         if ($channel == 'pecl.php.net') {
        !          59886:             return $this->raiseError('Cannot delete the pecl.php.net channel');
        !          59887:         }
1.1       misho    59888: 
1.1.1.2 ! misho    59889:         if ($channel == 'doc.php.net') {
        !          59890:             return $this->raiseError('Cannot delete the doc.php.net channel');
1.1       misho    59891:         }
                   59892: 
1.1.1.2 ! misho    59893:         if ($channel == '__uri') {
        !          59894:             return $this->raiseError('Cannot delete the __uri pseudo-channel');
1.1       misho    59895:         }
                   59896: 
1.1.1.2 ! misho    59897:         if (PEAR::isError($err = $reg->listPackages($channel))) {
        !          59898:             return $err;
        !          59899:         }
1.1       misho    59900: 
1.1.1.2 ! misho    59901:         if (count($err)) {
        !          59902:             return $this->raiseError('Channel "' . $channel .
        !          59903:                 '" has installed packages, cannot delete');
1.1       misho    59904:         }
                   59905: 
1.1.1.2 ! misho    59906:         if (!$reg->deleteChannel($channel)) {
        !          59907:             return $this->raiseError('Channel "' . $channel . '" deletion failed');
        !          59908:         } else {
        !          59909:             $this->config->deleteChannel($channel);
        !          59910:             $this->ui->outputData('Channel "' . $channel . '" deleted', $command);
1.1       misho    59911:         }
1.1.1.2 ! misho    59912:     }
1.1       misho    59913: 
1.1.1.2 ! misho    59914:     function doAdd($command, $options, $params)
        !          59915:     {
        !          59916:         if (count($params) !== 1) {
        !          59917:             return $this->raiseError('channel-add: no channel file specified');
1.1       misho    59918:         }
                   59919: 
1.1.1.2 ! misho    59920:         if (strpos($params[0], '://')) {
        !          59921:             $downloader = &$this->getDownloader();
        !          59922:             $tmpdir = $this->config->get('temp_dir');
        !          59923:             if (!file_exists($tmpdir)) {
        !          59924:                 require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
        !          59925:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          59926:                 $err = System::mkdir(array('-p', $tmpdir));
        !          59927:                 PEAR::staticPopErrorHandling();
        !          59928:                 if (PEAR::isError($err)) {
        !          59929:                     return $this->raiseError('channel-add: temp_dir does not exist: "' .
        !          59930:                         $tmpdir .
        !          59931:                         '" - You can change this location with "pear config-set temp_dir"');
        !          59932:                 }
        !          59933:             }
        !          59934: 
        !          59935:             if (!is_writable($tmpdir)) {
        !          59936:                 return $this->raiseError('channel-add: temp_dir is not writable: "' .
        !          59937:                     $tmpdir .
        !          59938:                     '" - You can change this location with "pear config-set temp_dir"');
        !          59939:             }
        !          59940: 
1.1       misho    59941:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
1.1.1.2 ! misho    59942:             $loc = $downloader->downloadHttp($params[0], $this->ui, $tmpdir, null, false);
1.1       misho    59943:             PEAR::staticPopErrorHandling();
1.1.1.2 ! misho    59944:             if (PEAR::isError($loc)) {
        !          59945:                 return $this->raiseError('channel-add: Cannot open "' . $params[0] .
        !          59946:                     '" (' . $loc->getMessage() . ')');
1.1       misho    59947:             }
1.1.1.2 ! misho    59948: 
        !          59949:             list($loc, $lastmodified) = $loc;
        !          59950:             $contents = implode('', file($loc));
        !          59951:         } else {
        !          59952:             $lastmodified = $fp = false;
        !          59953:             if (file_exists($params[0])) {
        !          59954:                 $fp = fopen($params[0], 'r');
1.1       misho    59955:             }
1.1.1.2 ! misho    59956: 
        !          59957:             if (!$fp) {
        !          59958:                 return $this->raiseError('channel-add: cannot open "' . $params[0] . '"');
1.1       misho    59959:             }
1.1.1.2 ! misho    59960: 
        !          59961:             $contents = '';
        !          59962:             while (!feof($fp)) {
        !          59963:                 $contents .= fread($fp, 1024);
        !          59964:             }
        !          59965:             fclose($fp);
1.1       misho    59966:         }
1.1.1.2 ! misho    59967: 
        !          59968:         if (!class_exists('PEAR_ChannelFile')) {
        !          59969:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
1.1       misho    59970:         }
                   59971: 
1.1.1.2 ! misho    59972:         $channel = new PEAR_ChannelFile;
        !          59973:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          59974:         $result = $channel->fromXmlString($contents);
        !          59975:         PEAR::staticPopErrorHandling();
        !          59976:         if (!$result) {
        !          59977:             $exit = false;
        !          59978:             if (count($errors = $channel->getErrors(true))) {
        !          59979:                 foreach ($errors as $error) {
        !          59980:                     $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
        !          59981:                     if (!$exit) {
        !          59982:                         $exit = $error['level'] == 'error' ? true : false;
1.1       misho    59983:                     }
                   59984:                 }
1.1.1.2 ! misho    59985:                 if ($exit) {
        !          59986:                     return $this->raiseError('channel-add: invalid channel.xml file');
1.1       misho    59987:                 }
                   59988:             }
                   59989:         }
                   59990: 
                   59991:         $reg = &$this->config->getRegistry();
1.1.1.2 ! misho    59992:         if ($reg->channelExists($channel->getName())) {
        !          59993:             return $this->raiseError('channel-add: Channel "' . $channel->getName() .
        !          59994:                 '" exists, use channel-update to update entry', PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS);
1.1       misho    59995:         }
                   59996: 
1.1.1.2 ! misho    59997:         $ret = $reg->addChannel($channel, $lastmodified);
        !          59998:         if (PEAR::isError($ret)) {
        !          59999:             return $ret;
1.1       misho    60000:         }
                   60001: 
1.1.1.2 ! misho    60002:         if (!$ret) {
        !          60003:             return $this->raiseError('channel-add: adding Channel "' . $channel->getName() .
        !          60004:                 '" to registry failed');
1.1       misho    60005:         }
                   60006: 
1.1.1.2 ! misho    60007:         $this->config->setChannels($reg->listChannels());
        !          60008:         $this->config->writeConfigFile();
        !          60009:         $this->ui->outputData('Adding Channel "' . $channel->getName() . '" succeeded', $command);
        !          60010:     }
1.1       misho    60011: 
1.1.1.2 ! misho    60012:     function doUpdate($command, $options, $params)
1.1       misho    60013:     {
1.1.1.2 ! misho    60014:         if (count($params) !== 1) {
        !          60015:             return $this->raiseError("No channel file specified");
1.1       misho    60016:         }
                   60017: 
1.1.1.2 ! misho    60018:         $tmpdir = $this->config->get('temp_dir');
        !          60019:         if (!file_exists($tmpdir)) {
        !          60020:             require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
        !          60021:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          60022:             $err = System::mkdir(array('-p', $tmpdir));
        !          60023:             PEAR::staticPopErrorHandling();
        !          60024:             if (PEAR::isError($err)) {
        !          60025:                 return $this->raiseError('channel-add: temp_dir does not exist: "' .
        !          60026:                     $tmpdir .
        !          60027:                     '" - You can change this location with "pear config-set temp_dir"');
        !          60028:             }
1.1       misho    60029:         }
                   60030: 
1.1.1.2 ! misho    60031:         if (!is_writable($tmpdir)) {
        !          60032:             return $this->raiseError('channel-add: temp_dir is not writable: "' .
        !          60033:                 $tmpdir .
        !          60034:                 '" - You can change this location with "pear config-set temp_dir"');
1.1       misho    60035:         }
                   60036: 
                   60037:         $reg = &$this->config->getRegistry();
1.1.1.2 ! misho    60038:         $lastmodified = false;
        !          60039:         if ((!file_exists($params[0]) || is_dir($params[0]))
        !          60040:               && $reg->channelExists(strtolower($params[0]))) {
        !          60041:             $c = $reg->getChannel(strtolower($params[0]));
        !          60042:             if (PEAR::isError($c)) {
        !          60043:                 return $this->raiseError($c);
        !          60044:             }
1.1       misho    60045: 
1.1.1.2 ! misho    60046:             $this->ui->outputData("Updating channel \"$params[0]\"", $command);
        !          60047:             $dl = &$this->getDownloader(array());
        !          60048:             // if force is specified, use a timestamp of "1" to force retrieval
        !          60049:             $lastmodified = isset($options['force']) ? false : $c->lastModified();
        !          60050:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          60051:             $contents = $dl->downloadHttp('http://' . $c->getName() . '/channel.xml',
        !          60052:                 $this->ui, $tmpdir, null, $lastmodified);
        !          60053:             PEAR::staticPopErrorHandling();
        !          60054:             if (PEAR::isError($contents)) {
        !          60055:                 // Attempt to fall back to https
        !          60056:                 $this->ui->outputData("Channel \"$params[0]\" is not responding over http://, failed with message: " . $contents->getMessage());
        !          60057:                 $this->ui->outputData("Trying channel \"$params[0]\" over https:// instead");
        !          60058:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          60059:                 $contents = $dl->downloadHttp('https://' . $c->getName() . '/channel.xml',
        !          60060:                     $this->ui, $tmpdir, null, $lastmodified);
        !          60061:                 PEAR::staticPopErrorHandling();
        !          60062:                 if (PEAR::isError($contents)) {
        !          60063:                     return $this->raiseError('Cannot retrieve channel.xml for channel "' .
        !          60064:                         $c->getName() . '" (' . $contents->getMessage() . ')');
        !          60065:                 }
1.1       misho    60066:             }
                   60067: 
1.1.1.2 ! misho    60068:             list($contents, $lastmodified) = $contents;
        !          60069:             if (!$contents) {
        !          60070:                 $this->ui->outputData("Channel \"$params[0]\" is up to date");
        !          60071:                 return;
1.1       misho    60072:             }
                   60073: 
1.1.1.2 ! misho    60074:             $contents = implode('', file($contents));
        !          60075:             if (!class_exists('PEAR_ChannelFile')) {
        !          60076:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
        !          60077:             }
1.1       misho    60078: 
1.1.1.2 ! misho    60079:             $channel = new PEAR_ChannelFile;
        !          60080:             $channel->fromXmlString($contents);
        !          60081:             if (!$channel->getErrors()) {
        !          60082:                 // security check: is the downloaded file for the channel we got it from?
        !          60083:                 if (strtolower($channel->getName()) != strtolower($c->getName())) {
        !          60084:                     if (!isset($options['force'])) {
        !          60085:                         return $this->raiseError('ERROR: downloaded channel definition file' .
        !          60086:                             ' for channel "' . $channel->getName() . '" from channel "' .
        !          60087:                             strtolower($c->getName()) . '"');
        !          60088:                     }
1.1       misho    60089: 
1.1.1.2 ! misho    60090:                     $this->ui->log(0, 'WARNING: downloaded channel definition file' .
        !          60091:                         ' for channel "' . $channel->getName() . '" from channel "' .
        !          60092:                         strtolower($c->getName()) . '"');
        !          60093:                 }
        !          60094:             }
        !          60095:         } else {
        !          60096:             if (strpos($params[0], '://')) {
        !          60097:                 $dl = &$this->getDownloader();
1.1       misho    60098:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
1.1.1.2 ! misho    60099:                 $loc = $dl->downloadHttp($params[0],
        !          60100:                     $this->ui, $tmpdir, null, $lastmodified);
        !          60101:                 PEAR::staticPopErrorHandling();
        !          60102:                 if (PEAR::isError($loc)) {
        !          60103:                     return $this->raiseError("Cannot open " . $params[0] .
        !          60104:                          ' (' . $loc->getMessage() . ')');
1.1       misho    60105:                 }
                   60106: 
1.1.1.2 ! misho    60107:                 list($loc, $lastmodified) = $loc;
        !          60108:                 $contents = implode('', file($loc));
        !          60109:             } else {
        !          60110:                 $fp = false;
        !          60111:                 if (file_exists($params[0])) {
        !          60112:                     $fp = fopen($params[0], 'r');
        !          60113:                 }
1.1       misho    60114: 
1.1.1.2 ! misho    60115:                 if (!$fp) {
        !          60116:                     return $this->raiseError("Cannot open " . $params[0]);
1.1       misho    60117:                 }
                   60118: 
1.1.1.2 ! misho    60119:                 $contents = '';
        !          60120:                 while (!feof($fp)) {
        !          60121:                     $contents .= fread($fp, 1024);
1.1       misho    60122:                 }
1.1.1.2 ! misho    60123:                 fclose($fp);
        !          60124:             }
1.1       misho    60125: 
1.1.1.2 ! misho    60126:             if (!class_exists('PEAR_ChannelFile')) {
        !          60127:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
1.1       misho    60128:             }
                   60129: 
1.1.1.2 ! misho    60130:             $channel = new PEAR_ChannelFile;
        !          60131:             $channel->fromXmlString($contents);
        !          60132:         }
1.1       misho    60133: 
1.1.1.2 ! misho    60134:         $exit = false;
        !          60135:         if (count($errors = $channel->getErrors(true))) {
        !          60136:             foreach ($errors as $error) {
        !          60137:                 $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
        !          60138:                 if (!$exit) {
        !          60139:                     $exit = $error['level'] == 'error' ? true : false;
1.1       misho    60140:                 }
1.1.1.2 ! misho    60141:             }
        !          60142:             if ($exit) {
        !          60143:                 return $this->raiseError('Invalid channel.xml file');
1.1       misho    60144:             }
                   60145:         }
                   60146: 
1.1.1.2 ! misho    60147:         if (!$reg->channelExists($channel->getName())) {
        !          60148:             return $this->raiseError('Error: Channel "' . $channel->getName() .
        !          60149:                 '" does not exist, use channel-add to add an entry');
        !          60150:         }
1.1       misho    60151: 
1.1.1.2 ! misho    60152:         $ret = $reg->updateChannel($channel, $lastmodified);
        !          60153:         if (PEAR::isError($ret)) {
        !          60154:             return $ret;
        !          60155:         }
1.1       misho    60156: 
1.1.1.2 ! misho    60157:         if (!$ret) {
        !          60158:             return $this->raiseError('Updating Channel "' . $channel->getName() .
        !          60159:                 '" in registry failed');
        !          60160:         }
1.1       misho    60161: 
1.1.1.2 ! misho    60162:         $this->config->setChannels($reg->listChannels());
        !          60163:         $this->config->writeConfigFile();
        !          60164:         $this->ui->outputData('Update of Channel "' . $channel->getName() . '" succeeded');
        !          60165:     }
1.1       misho    60166: 
1.1.1.2 ! misho    60167:     function &getDownloader()
        !          60168:     {
        !          60169:         if (!class_exists('PEAR_Downloader')) {
        !          60170:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Downloader.php';
        !          60171:         }
        !          60172:         $a = new PEAR_Downloader($this->ui, array(), $this->config);
        !          60173:         return $a;
        !          60174:     }
1.1       misho    60175: 
1.1.1.2 ! misho    60176:     function doAlias($command, $options, $params)
        !          60177:     {
        !          60178:         if (count($params) === 1) {
        !          60179:             return $this->raiseError('No channel alias specified');
        !          60180:         }
1.1       misho    60181: 
1.1.1.2 ! misho    60182:         if (count($params) !== 2 || (!empty($params[1]) && $params[1]{0} == '-')) {
        !          60183:             return $this->raiseError(
        !          60184:                 'Invalid format, correct is: channel-alias channel alias');
        !          60185:         }
1.1       misho    60186: 
1.1.1.2 ! misho    60187:         $reg = &$this->config->getRegistry();
        !          60188:         if (!$reg->channelExists($params[0], true)) {
        !          60189:             $extra = '';
        !          60190:             if ($reg->isAlias($params[0])) {
        !          60191:                 $extra = ' (use "channel-alias ' . $reg->channelName($params[0]) . ' ' .
        !          60192:                     strtolower($params[1]) . '")';
        !          60193:             }
1.1       misho    60194: 
1.1.1.2 ! misho    60195:             return $this->raiseError('"' . $params[0] . '" is not a valid channel' . $extra);
        !          60196:         }
1.1       misho    60197: 
1.1.1.2 ! misho    60198:         if ($reg->isAlias($params[1])) {
        !          60199:             return $this->raiseError('Channel "' . $reg->channelName($params[1]) . '" is ' .
        !          60200:                 'already aliased to "' . strtolower($params[1]) . '", cannot re-alias');
        !          60201:         }
1.1       misho    60202: 
1.1.1.2 ! misho    60203:         $chan = &$reg->getChannel($params[0]);
        !          60204:         if (PEAR::isError($chan)) {
        !          60205:             return $this->raiseError('Corrupt registry?  Error retrieving channel "' . $params[0] .
        !          60206:                 '" information (' . $chan->getMessage() . ')');
        !          60207:         }
1.1       misho    60208: 
1.1.1.2 ! misho    60209:         // make it a local alias
        !          60210:         if (!$chan->setAlias(strtolower($params[1]), true)) {
        !          60211:             return $this->raiseError('Alias "' . strtolower($params[1]) .
        !          60212:                 '" is not a valid channel alias');
        !          60213:         }
1.1       misho    60214: 
1.1.1.2 ! misho    60215:         $reg->updateChannel($chan);
        !          60216:         $this->ui->outputData('Channel "' . $chan->getName() . '" aliased successfully to "' .
        !          60217:             strtolower($params[1]) . '"');
        !          60218:     }
1.1       misho    60219: 
1.1.1.2 ! misho    60220:     /**
        !          60221:      * The channel-discover command
        !          60222:      *
        !          60223:      * @param string $command command name
        !          60224:      * @param array  $options option_name => value
        !          60225:      * @param array  $params  list of additional parameters.
        !          60226:      *               $params[0] should contain a string with either:
        !          60227:      *               - <channel name> or
        !          60228:      *               - <username>:<password>@<channel name>
        !          60229:      * @return null|PEAR_Error
        !          60230:      */
        !          60231:     function doDiscover($command, $options, $params)
        !          60232:     {
        !          60233:         if (count($params) !== 1) {
        !          60234:             return $this->raiseError("No channel server specified");
        !          60235:         }
1.1       misho    60236: 
1.1.1.2 ! misho    60237:         // Look for the possible input format "<username>:<password>@<channel>"
        !          60238:         if (preg_match('/^(.+):(.+)@(.+)\\z/', $params[0], $matches)) {
        !          60239:             $username = $matches[1];
        !          60240:             $password = $matches[2];
        !          60241:             $channel  = $matches[3];
        !          60242:         } else {
        !          60243:             $channel = $params[0];
        !          60244:         }
1.1       misho    60245: 
1.1.1.2 ! misho    60246:         $reg = &$this->config->getRegistry();
        !          60247:         if ($reg->channelExists($channel)) {
        !          60248:             if (!$reg->isAlias($channel)) {
        !          60249:                 return $this->raiseError("Channel \"$channel\" is already initialized", PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS);
        !          60250:             }
1.1       misho    60251: 
1.1.1.2 ! misho    60252:             return $this->raiseError("A channel alias named \"$channel\" " .
        !          60253:                 'already exists, aliasing channel "' . $reg->channelName($channel)
        !          60254:                 . '"');
        !          60255:         }
1.1       misho    60256: 
1.1.1.2 ! misho    60257:         $this->pushErrorHandling(PEAR_ERROR_RETURN);
        !          60258:         $err = $this->doAdd($command, $options, array('http://' . $channel . '/channel.xml'));
        !          60259:         $this->popErrorHandling();
        !          60260:         if (PEAR::isError($err)) {
        !          60261:             if ($err->getCode() === PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS) {
        !          60262:                 return $this->raiseError("Discovery of channel \"$channel\" failed (" .
        !          60263:                     $err->getMessage() . ')');
        !          60264:             }
        !          60265:             // Attempt fetch via https
        !          60266:             $this->ui->outputData("Discovering channel $channel over http:// failed with message: " . $err->getMessage());
        !          60267:             $this->ui->outputData("Trying to discover channel $channel over https:// instead");
        !          60268:             $this->pushErrorHandling(PEAR_ERROR_RETURN);
        !          60269:             $err = $this->doAdd($command, $options, array('https://' . $channel . '/channel.xml'));
        !          60270:             $this->popErrorHandling();
        !          60271:             if (PEAR::isError($err)) {
        !          60272:                 return $this->raiseError("Discovery of channel \"$channel\" failed (" .
        !          60273:                     $err->getMessage() . ')');
        !          60274:             }
        !          60275:         }
1.1       misho    60276: 
1.1.1.2 ! misho    60277:         // Store username/password if they were given
        !          60278:         // Arguably we should do a logintest on the channel here, but since
        !          60279:         // that's awkward on a REST-based channel (even "pear login" doesn't
        !          60280:         // do it for those), and XML-RPC is deprecated, it's fairly pointless.
        !          60281:         if (isset($username)) {
        !          60282:             $this->config->set('username', $username, 'user', $channel);
        !          60283:             $this->config->set('password', $password, 'user', $channel);
        !          60284:             $this->config->store();
        !          60285:             $this->ui->outputData("Stored login for channel \"$channel\" using username \"$username\"", $command);
        !          60286:         }
1.1       misho    60287: 
1.1.1.2 ! misho    60288:         $this->ui->outputData("Discovery of channel \"$channel\" succeeded", $command);
        !          60289:     }
1.1       misho    60290: 
1.1.1.2 ! misho    60291:     /**
        !          60292:      * Execute the 'login' command.
        !          60293:      *
        !          60294:      * @param string $command command name
        !          60295:      * @param array $options option_name => value
        !          60296:      * @param array $params list of additional parameters
        !          60297:      *
        !          60298:      * @return bool TRUE on success or
        !          60299:      * a PEAR error on failure
        !          60300:      *
        !          60301:      * @access public
        !          60302:      */
        !          60303:     function doLogin($command, $options, $params)
        !          60304:     {
        !          60305:         $reg = &$this->config->getRegistry();
1.1       misho    60306: 
1.1.1.2 ! misho    60307:         // If a parameter is supplied, use that as the channel to log in to
        !          60308:         $channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel');
1.1       misho    60309: 
1.1.1.2 ! misho    60310:         $chan = $reg->getChannel($channel);
        !          60311:         if (PEAR::isError($chan)) {
        !          60312:             return $this->raiseError($chan);
        !          60313:         }
1.1       misho    60314: 
1.1.1.2 ! misho    60315:         $server   = $this->config->get('preferred_mirror', null, $channel);
        !          60316:         $username = $this->config->get('username',         null, $channel);
        !          60317:         if (empty($username)) {
        !          60318:             $username = isset($_ENV['USER']) ? $_ENV['USER'] : null;
        !          60319:         }
        !          60320:         $this->ui->outputData("Logging in to $server.", $command);
1.1       misho    60321: 
1.1.1.2 ! misho    60322:         list($username, $password) = $this->ui->userDialog(
        !          60323:             $command,
        !          60324:             array('Username', 'Password'),
        !          60325:             array('text',     'password'),
        !          60326:             array($username,  '')
        !          60327:             );
        !          60328:         $username = trim($username);
        !          60329:         $password = trim($password);
1.1       misho    60330: 
1.1.1.2 ! misho    60331:         $ourfile = $this->config->getConfFile('user');
        !          60332:         if (!$ourfile) {
        !          60333:             $ourfile = $this->config->getConfFile('system');
        !          60334:         }
1.1       misho    60335: 
1.1.1.2 ! misho    60336:         $this->config->set('username', $username, 'user', $channel);
        !          60337:         $this->config->set('password', $password, 'user', $channel);
1.1       misho    60338: 
1.1.1.2 ! misho    60339:         if ($chan->supportsREST()) {
        !          60340:             $ok = true;
        !          60341:         }
1.1       misho    60342: 
1.1.1.2 ! misho    60343:         if ($ok !== true) {
        !          60344:             return $this->raiseError('Login failed!');
        !          60345:         }
1.1       misho    60346: 
1.1.1.2 ! misho    60347:         $this->ui->outputData("Logged in.", $command);
        !          60348:         // avoid changing any temporary settings changed with -d
        !          60349:         $ourconfig = new PEAR_Config($ourfile, $ourfile);
        !          60350:         $ourconfig->set('username', $username, 'user', $channel);
        !          60351:         $ourconfig->set('password', $password, 'user', $channel);
        !          60352:         $ourconfig->store();
1.1       misho    60353: 
1.1.1.2 ! misho    60354:         return true;
        !          60355:     }
1.1       misho    60356: 
                   60357:     /**
1.1.1.2 ! misho    60358:      * Execute the 'logout' command.
        !          60359:      *
        !          60360:      * @param string $command command name
        !          60361:      * @param array $options option_name => value
        !          60362:      * @param array $params list of additional parameters
        !          60363:      *
        !          60364:      * @return bool TRUE on success or
        !          60365:      * a PEAR error on failure
1.1       misho    60366:      *
                   60367:      * @access public
                   60368:      */
1.1.1.2 ! misho    60369:     function doLogout($command, $options, $params)
1.1       misho    60370:     {
1.1.1.2 ! misho    60371:         $reg     = &$this->config->getRegistry();
        !          60372: 
        !          60373:         // If a parameter is supplied, use that as the channel to log in to
        !          60374:         $channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel');
        !          60375: 
        !          60376:         $chan    = $reg->getChannel($channel);
        !          60377:         if (PEAR::isError($chan)) {
        !          60378:             return $this->raiseError($chan);
        !          60379:         }
        !          60380: 
        !          60381:         $server = $this->config->get('preferred_mirror', null, $channel);
        !          60382:         $this->ui->outputData("Logging out from $server.", $command);
        !          60383:         $this->config->remove('username', 'user', $channel);
        !          60384:         $this->config->remove('password', 'user', $channel);
        !          60385:         $this->config->store();
        !          60386:         return true;
1.1       misho    60387:     }
1.1.1.2 ! misho    60388: }<commands version="1.0">
        !          60389:  <list-channels>
        !          60390:   <summary>List Available Channels</summary>
        !          60391:   <function>doList</function>
        !          60392:   <shortcut>lc</shortcut>
        !          60393:   <options />
        !          60394:   <doc>
        !          60395: List all available channels for installation.
        !          60396: </doc>
        !          60397:  </list-channels>
        !          60398:  <update-channels>
        !          60399:   <summary>Update the Channel List</summary>
        !          60400:   <function>doUpdateAll</function>
        !          60401:   <shortcut>uc</shortcut>
        !          60402:   <options />
        !          60403:   <doc>
        !          60404: List all installed packages in all channels.
        !          60405: </doc>
        !          60406:  </update-channels>
        !          60407:  <channel-delete>
        !          60408:   <summary>Remove a Channel From the List</summary>
        !          60409:   <function>doDelete</function>
        !          60410:   <shortcut>cde</shortcut>
        !          60411:   <options />
        !          60412:   <doc>&lt;channel name&gt;
        !          60413: Delete a channel from the registry.  You may not
        !          60414: remove any channel that has installed packages.
        !          60415: </doc>
        !          60416:  </channel-delete>
        !          60417:  <channel-add>
        !          60418:   <summary>Add a Channel</summary>
        !          60419:   <function>doAdd</function>
        !          60420:   <shortcut>ca</shortcut>
        !          60421:   <options />
        !          60422:   <doc>&lt;channel.xml&gt;
        !          60423: Add a private channel to the channel list.  Note that all
        !          60424: public channels should be synced using &quot;update-channels&quot;.
        !          60425: Parameter may be either a local file or remote URL to a
        !          60426: channel.xml.
        !          60427: </doc>
        !          60428:  </channel-add>
        !          60429:  <channel-update>
        !          60430:   <summary>Update an Existing Channel</summary>
        !          60431:   <function>doUpdate</function>
        !          60432:   <shortcut>cu</shortcut>
        !          60433:   <options>
        !          60434:    <force>
        !          60435:     <shortopt>f</shortopt>
        !          60436:     <doc>will force download of new channel.xml if an existing channel name is used</doc>
        !          60437:    </force>
        !          60438:    <channel>
        !          60439:     <shortopt>c</shortopt>
        !          60440:     <doc>will force download of new channel.xml if an existing channel name is used</doc>
        !          60441:     <arg>CHANNEL</arg>
        !          60442:    </channel>
        !          60443:   </options>
        !          60444:   <doc>[&lt;channel.xml&gt;|&lt;channel name&gt;]
        !          60445: Update a channel in the channel list directly.  Note that all
        !          60446: public channels can be synced using &quot;update-channels&quot;.
        !          60447: Parameter may be a local or remote channel.xml, or the name of
        !          60448: an existing channel.
        !          60449: </doc>
        !          60450:  </channel-update>
        !          60451:  <channel-info>
        !          60452:   <summary>Retrieve Information on a Channel</summary>
        !          60453:   <function>doInfo</function>
        !          60454:   <shortcut>ci</shortcut>
        !          60455:   <options />
        !          60456:   <doc>&lt;package&gt;
        !          60457: List the files in an installed package.
        !          60458: </doc>
        !          60459:  </channel-info>
        !          60460:  <channel-alias>
        !          60461:   <summary>Specify an alias to a channel name</summary>
        !          60462:   <function>doAlias</function>
        !          60463:   <shortcut>cha</shortcut>
        !          60464:   <options />
        !          60465:   <doc>&lt;channel&gt; &lt;alias&gt;
        !          60466: Specify a specific alias to use for a channel name.
        !          60467: The alias may not be an existing channel name or
        !          60468: alias.
        !          60469: </doc>
        !          60470:  </channel-alias>
        !          60471:  <channel-discover>
        !          60472:   <summary>Initialize a Channel from its server</summary>
        !          60473:   <function>doDiscover</function>
        !          60474:   <shortcut>di</shortcut>
        !          60475:   <options />
        !          60476:   <doc>[&lt;channel.xml&gt;|&lt;channel name&gt;]
        !          60477: Initialize a channel from its server and create a local channel.xml.
        !          60478: If &lt;channel name&gt; is in the format &quot;&lt;username&gt;:&lt;password&gt;@&lt;channel&gt;&quot; then
        !          60479: &lt;username&gt; and &lt;password&gt; will be set as the login username/password for
        !          60480: &lt;channel&gt;. Use caution when passing the username/password in this way, as
        !          60481: it may allow other users on your computer to briefly view your username/
        !          60482: password via the system&#039;s process list.
        !          60483: </doc>
        !          60484:  </channel-discover>
        !          60485:  <channel-login>
        !          60486:   <summary>Connects and authenticates to remote channel server</summary>
        !          60487:   <function>doLogin</function>
        !          60488:   <shortcut>cli</shortcut>
        !          60489:   <options />
        !          60490:   <doc>&lt;channel name&gt;
        !          60491: Log in to a remote channel server.  If &lt;channel name&gt; is not supplied,
        !          60492: the default channel is used. To use remote functions in the installer
        !          60493: that require any kind of privileges, you need to log in first.  The
        !          60494: username and password you enter here will be stored in your per-user
        !          60495: PEAR configuration (~/.pearrc on Unix-like systems).  After logging
        !          60496: in, your username and password will be sent along in subsequent
        !          60497: operations on the remote server.</doc>
        !          60498:  </channel-login>
        !          60499:  <channel-logout>
        !          60500:   <summary>Logs out from the remote channel server</summary>
        !          60501:   <function>doLogout</function>
        !          60502:   <shortcut>clo</shortcut>
        !          60503:   <options />
        !          60504:   <doc>&lt;channel name&gt;
        !          60505: Logs out from a remote channel server.  If &lt;channel name&gt; is not supplied,
        !          60506: the default channel is used. This command does not actually connect to the
        !          60507: remote server, it only deletes the stored username and password from your user
        !          60508: configuration.</doc>
        !          60509:  </channel-logout>
        !          60510: </commands><?php
        !          60511: /**
        !          60512:  * PEAR_Command_Common base class
        !          60513:  *
        !          60514:  * PHP versions 4 and 5
        !          60515:  *
        !          60516:  * @category   pear
        !          60517:  * @package    PEAR
        !          60518:  * @author     Stig Bakken <ssb@php.net>
        !          60519:  * @author     Greg Beaver <cellog@php.net>
        !          60520:  * @copyright  1997-2009 The Authors
        !          60521:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          60522:  * @version    CVS: $Id: Common.php 313023 2011-07-06 19:17:11Z dufuz $
        !          60523:  * @link       http://pear.php.net/package/PEAR
        !          60524:  * @since      File available since Release 0.1
        !          60525:  */
        !          60526: 
        !          60527: /**
        !          60528:  * base class
        !          60529:  */
        !          60530: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
1.1       misho    60531: 
1.1.1.2 ! misho    60532: /**
        !          60533:  * PEAR commands base class
        !          60534:  *
        !          60535:  * @category   pear
        !          60536:  * @package    PEAR
        !          60537:  * @author     Stig Bakken <ssb@php.net>
        !          60538:  * @author     Greg Beaver <cellog@php.net>
        !          60539:  * @copyright  1997-2009 The Authors
        !          60540:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          60541:  * @version    Release: 1.9.4
        !          60542:  * @link       http://pear.php.net/package/PEAR
        !          60543:  * @since      Class available since Release 0.1
        !          60544:  */
        !          60545: class PEAR_Command_Common extends PEAR
        !          60546: {
1.1       misho    60547:     /**
1.1.1.2 ! misho    60548:      * PEAR_Config object used to pass user system and configuration
        !          60549:      * on when executing commands
1.1       misho    60550:      *
1.1.1.2 ! misho    60551:      * @var PEAR_Config
1.1       misho    60552:      */
1.1.1.2 ! misho    60553:     var $config;
        !          60554:     /**
        !          60555:      * @var PEAR_Registry
        !          60556:      * @access protected
        !          60557:      */
        !          60558:     var $_registry;
1.1       misho    60559: 
1.1.1.2 ! misho    60560:     /**
        !          60561:      * User Interface object, for all interaction with the user.
        !          60562:      * @var object
        !          60563:      */
        !          60564:     var $ui;
        !          60565: 
        !          60566:     var $_deps_rel_trans = array(
        !          60567:                                  'lt' => '<',
        !          60568:                                  'le' => '<=',
        !          60569:                                  'eq' => '=',
        !          60570:                                  'ne' => '!=',
        !          60571:                                  'gt' => '>',
        !          60572:                                  'ge' => '>=',
        !          60573:                                  'has' => '=='
        !          60574:                                  );
        !          60575: 
        !          60576:     var $_deps_type_trans = array(
        !          60577:                                   'pkg' => 'package',
        !          60578:                                   'ext' => 'extension',
        !          60579:                                   'php' => 'PHP',
        !          60580:                                   'prog' => 'external program',
        !          60581:                                   'ldlib' => 'external library for linking',
        !          60582:                                   'rtlib' => 'external runtime library',
        !          60583:                                   'os' => 'operating system',
        !          60584:                                   'websrv' => 'web server',
        !          60585:                                   'sapi' => 'SAPI backend'
        !          60586:                                   );
1.1       misho    60587: 
                   60588:     /**
1.1.1.2 ! misho    60589:      * PEAR_Command_Common constructor.
1.1       misho    60590:      *
                   60591:      * @access public
                   60592:      */
1.1.1.2 ! misho    60593:     function PEAR_Command_Common(&$ui, &$config)
1.1       misho    60594:     {
1.1.1.2 ! misho    60595:         parent::PEAR();
        !          60596:         $this->config = &$config;
        !          60597:         $this->ui = &$ui;
1.1       misho    60598:     }
                   60599: 
                   60600:     /**
1.1.1.2 ! misho    60601:      * Return a list of all the commands defined by this class.
        !          60602:      * @return array list of commands
1.1       misho    60603:      * @access public
                   60604:      */
1.1.1.2 ! misho    60605:     function getCommands()
1.1       misho    60606:     {
1.1.1.2 ! misho    60607:         $ret = array();
        !          60608:         foreach (array_keys($this->commands) as $command) {
        !          60609:             $ret[$command] = $this->commands[$command]['summary'];
1.1       misho    60610:         }
1.1.1.2 ! misho    60611: 
        !          60612:         return $ret;
1.1       misho    60613:     }
                   60614: 
                   60615:     /**
1.1.1.2 ! misho    60616:      * Return a list of all the command shortcuts defined by this class.
        !          60617:      * @return array shortcut => command
1.1       misho    60618:      * @access public
                   60619:      */
1.1.1.2 ! misho    60620:     function getShortcuts()
1.1       misho    60621:     {
1.1.1.2 ! misho    60622:         $ret = array();
        !          60623:         foreach (array_keys($this->commands) as $command) {
        !          60624:             if (isset($this->commands[$command]['shortcut'])) {
        !          60625:                 $ret[$this->commands[$command]['shortcut']] = $command;
1.1       misho    60626:             }
                   60627:         }
1.1.1.2 ! misho    60628: 
        !          60629:         return $ret;
1.1       misho    60630:     }
                   60631: 
1.1.1.2 ! misho    60632:     function getOptions($command)
1.1       misho    60633:     {
1.1.1.2 ! misho    60634:         $shortcuts = $this->getShortcuts();
        !          60635:         if (isset($shortcuts[$command])) {
        !          60636:             $command = $shortcuts[$command];
1.1       misho    60637:         }
                   60638: 
1.1.1.2 ! misho    60639:         if (isset($this->commands[$command]) &&
        !          60640:               isset($this->commands[$command]['options'])) {
        !          60641:             return $this->commands[$command]['options'];
1.1       misho    60642:         }
                   60643: 
1.1.1.2 ! misho    60644:         return null;
1.1       misho    60645:     }
                   60646: 
1.1.1.2 ! misho    60647:     function getGetoptArgs($command, &$short_args, &$long_args)
1.1       misho    60648:     {
1.1.1.2 ! misho    60649:         $short_args = '';
        !          60650:         $long_args = array();
        !          60651:         if (empty($this->commands[$command]) || empty($this->commands[$command]['options'])) {
        !          60652:             return;
        !          60653:         }
        !          60654: 
        !          60655:         reset($this->commands[$command]['options']);
        !          60656:         while (list($option, $info) = each($this->commands[$command]['options'])) {
        !          60657:             $larg = $sarg = '';
        !          60658:             if (isset($info['arg'])) {
        !          60659:                 if ($info['arg']{0} == '(') {
        !          60660:                     $larg = '==';
        !          60661:                     $sarg = '::';
        !          60662:                     $arg = substr($info['arg'], 1, -1);
        !          60663:                 } else {
        !          60664:                     $larg = '=';
        !          60665:                     $sarg = ':';
        !          60666:                     $arg = $info['arg'];
        !          60667:                 }
        !          60668:             }
        !          60669: 
        !          60670:             if (isset($info['shortopt'])) {
        !          60671:                 $short_args .= $info['shortopt'] . $sarg;
        !          60672:             }
        !          60673: 
        !          60674:             $long_args[] = $option . $larg;
        !          60675:         }
1.1       misho    60676:     }
                   60677: 
                   60678:     /**
1.1.1.2 ! misho    60679:     * Returns the help message for the given command
        !          60680:     *
        !          60681:     * @param string $command The command
        !          60682:     * @return mixed A fail string if the command does not have help or
        !          60683:     *               a two elements array containing [0]=>help string,
        !          60684:     *               [1]=> help string for the accepted cmd args
        !          60685:     */
        !          60686:     function getHelp($command)
1.1       misho    60687:     {
1.1.1.2 ! misho    60688:         $config = &PEAR_Config::singleton();
        !          60689:         if (!isset($this->commands[$command])) {
        !          60690:             return "No such command \"$command\"";
1.1       misho    60691:         }
1.1.1.2 ! misho    60692: 
        !          60693:         $help = null;
        !          60694:         if (isset($this->commands[$command]['doc'])) {
        !          60695:             $help = $this->commands[$command]['doc'];
1.1       misho    60696:         }
                   60697: 
1.1.1.2 ! misho    60698:         if (empty($help)) {
        !          60699:             // XXX (cox) Fallback to summary if there is no doc (show both?)
        !          60700:             if (!isset($this->commands[$command]['summary'])) {
        !          60701:                 return "No help for command \"$command\"";
        !          60702:             }
        !          60703:             $help = $this->commands[$command]['summary'];
        !          60704:         }
1.1       misho    60705: 
1.1.1.2 ! misho    60706:         if (preg_match_all('/{config\s+([^\}]+)}/e', $help, $matches)) {
        !          60707:             foreach($matches[0] as $k => $v) {
        !          60708:                 $help = preg_replace("/$v/", $config->get($matches[1][$k]), $help);
        !          60709:             }
        !          60710:         }
1.1       misho    60711: 
1.1.1.2 ! misho    60712:         return array($help, $this->getHelpArgs($command));
1.1       misho    60713:     }
                   60714: 
                   60715:     /**
1.1.1.2 ! misho    60716:      * Returns the help for the accepted arguments of a command
1.1       misho    60717:      *
1.1.1.2 ! misho    60718:      * @param  string $command
        !          60719:      * @return string The help string
1.1       misho    60720:      */
1.1.1.2 ! misho    60721:     function getHelpArgs($command)
1.1       misho    60722:     {
1.1.1.2 ! misho    60723:         if (isset($this->commands[$command]['options']) &&
        !          60724:             count($this->commands[$command]['options']))
        !          60725:         {
        !          60726:             $help = "Options:\n";
        !          60727:             foreach ($this->commands[$command]['options'] as $k => $v) {
        !          60728:                 if (isset($v['arg'])) {
        !          60729:                     if ($v['arg'][0] == '(') {
        !          60730:                         $arg = substr($v['arg'], 1, -1);
        !          60731:                         $sapp = " [$arg]";
        !          60732:                         $lapp = "[=$arg]";
        !          60733:                     } else {
        !          60734:                         $sapp = " $v[arg]";
        !          60735:                         $lapp = "=$v[arg]";
        !          60736:                     }
        !          60737:                 } else {
        !          60738:                     $sapp = $lapp = "";
        !          60739:                 }
1.1       misho    60740: 
1.1.1.2 ! misho    60741:                 if (isset($v['shortopt'])) {
        !          60742:                     $s = $v['shortopt'];
        !          60743:                     $help .= "  -$s$sapp, --$k$lapp\n";
        !          60744:                 } else {
        !          60745:                     $help .= "  --$k$lapp\n";
        !          60746:                 }
1.1       misho    60747: 
1.1.1.2 ! misho    60748:                 $p = "        ";
        !          60749:                 $doc = rtrim(str_replace("\n", "\n$p", $v['doc']));
        !          60750:                 $help .= "        $doc\n";
        !          60751:             }
1.1       misho    60752: 
1.1.1.2 ! misho    60753:             return $help;
        !          60754:         }
        !          60755: 
        !          60756:         return null;
1.1       misho    60757:     }
                   60758: 
1.1.1.2 ! misho    60759:     function run($command, $options, $params)
1.1       misho    60760:     {
1.1.1.2 ! misho    60761:         if (empty($this->commands[$command]['function'])) {
        !          60762:             // look for shortcuts
        !          60763:             foreach (array_keys($this->commands) as $cmd) {
        !          60764:                 if (isset($this->commands[$cmd]['shortcut']) && $this->commands[$cmd]['shortcut'] == $command) {
        !          60765:                     if (empty($this->commands[$cmd]['function'])) {
        !          60766:                         return $this->raiseError("unknown command `$command'");
        !          60767:                     } else {
        !          60768:                         $func = $this->commands[$cmd]['function'];
        !          60769:                     }
        !          60770:                     $command = $cmd;
1.1       misho    60771: 
1.1.1.2 ! misho    60772:                     //$command = $this->commands[$cmd]['function'];
        !          60773:                     break;
        !          60774:                 }
        !          60775:             }
        !          60776:         } else {
        !          60777:             $func = $this->commands[$command]['function'];
        !          60778:         }
        !          60779: 
        !          60780:         return $this->$func($command, $options, $params);
1.1       misho    60781:     }
1.1.1.2 ! misho    60782: }<?php
        !          60783: /**
        !          60784:  * PEAR_Command_Config (config-show, config-get, config-set, config-help, config-create commands)
        !          60785:  *
        !          60786:  * PHP versions 4 and 5
        !          60787:  *
        !          60788:  * @category   pear
        !          60789:  * @package    PEAR
        !          60790:  * @author     Stig Bakken <ssb@php.net>
        !          60791:  * @author     Greg Beaver <cellog@php.net>
        !          60792:  * @copyright  1997-2009 The Authors
        !          60793:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          60794:  * @version    CVS: $Id: Config.php 313024 2011-07-06 19:51:24Z dufuz $
        !          60795:  * @link       http://pear.php.net/package/PEAR
        !          60796:  * @since      File available since Release 0.1
        !          60797:  */
        !          60798: 
        !          60799: /**
        !          60800:  * base class
        !          60801:  */
        !          60802: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Common.php';
        !          60803: 
        !          60804: /**
        !          60805:  * PEAR commands for managing configuration data.
        !          60806:  *
        !          60807:  * @category   pear
        !          60808:  * @package    PEAR
        !          60809:  * @author     Stig Bakken <ssb@php.net>
        !          60810:  * @author     Greg Beaver <cellog@php.net>
        !          60811:  * @copyright  1997-2009 The Authors
        !          60812:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          60813:  * @version    Release: 1.9.4
        !          60814:  * @link       http://pear.php.net/package/PEAR
        !          60815:  * @since      Class available since Release 0.1
        !          60816:  */
        !          60817: class PEAR_Command_Config extends PEAR_Command_Common
        !          60818: {
        !          60819:     var $commands = array(
        !          60820:         'config-show' => array(
        !          60821:             'summary' => 'Show All Settings',
        !          60822:             'function' => 'doConfigShow',
        !          60823:             'shortcut' => 'csh',
        !          60824:             'options' => array(
        !          60825:                 'channel' => array(
        !          60826:                     'shortopt' => 'c',
        !          60827:                     'doc' => 'show configuration variables for another channel',
        !          60828:                     'arg' => 'CHAN',
        !          60829:                     ),
        !          60830: ),
        !          60831:             'doc' => '[layer]
        !          60832: Displays all configuration values.  An optional argument
        !          60833: may be used to tell which configuration layer to display.  Valid
        !          60834: configuration layers are "user", "system" and "default". To display
        !          60835: configurations for different channels, set the default_channel
        !          60836: configuration variable and run config-show again.
        !          60837: ',
        !          60838:             ),
        !          60839:         'config-get' => array(
        !          60840:             'summary' => 'Show One Setting',
        !          60841:             'function' => 'doConfigGet',
        !          60842:             'shortcut' => 'cg',
        !          60843:             'options' => array(
        !          60844:                 'channel' => array(
        !          60845:                     'shortopt' => 'c',
        !          60846:                     'doc' => 'show configuration variables for another channel',
        !          60847:                     'arg' => 'CHAN',
        !          60848:                     ),
        !          60849: ),
        !          60850:             'doc' => '<parameter> [layer]
        !          60851: Displays the value of one configuration parameter.  The
        !          60852: first argument is the name of the parameter, an optional second argument
        !          60853: may be used to tell which configuration layer to look in.  Valid configuration
        !          60854: layers are "user", "system" and "default".  If no layer is specified, a value
        !          60855: will be picked from the first layer that defines the parameter, in the order
        !          60856: just specified.  The configuration value will be retrieved for the channel
        !          60857: specified by the default_channel configuration variable.
        !          60858: ',
        !          60859:             ),
        !          60860:         'config-set' => array(
        !          60861:             'summary' => 'Change Setting',
        !          60862:             'function' => 'doConfigSet',
        !          60863:             'shortcut' => 'cs',
        !          60864:             'options' => array(
        !          60865:                 'channel' => array(
        !          60866:                     'shortopt' => 'c',
        !          60867:                     'doc' => 'show configuration variables for another channel',
        !          60868:                     'arg' => 'CHAN',
        !          60869:                     ),
        !          60870: ),
        !          60871:             'doc' => '<parameter> <value> [layer]
        !          60872: Sets the value of one configuration parameter.  The first argument is
        !          60873: the name of the parameter, the second argument is the new value.  Some
        !          60874: parameters are subject to validation, and the command will fail with
        !          60875: an error message if the new value does not make sense.  An optional
        !          60876: third argument may be used to specify in which layer to set the
        !          60877: configuration parameter.  The default layer is "user".  The
        !          60878: configuration value will be set for the current channel, which
        !          60879: is controlled by the default_channel configuration variable.
        !          60880: ',
        !          60881:             ),
        !          60882:         'config-help' => array(
        !          60883:             'summary' => 'Show Information About Setting',
        !          60884:             'function' => 'doConfigHelp',
        !          60885:             'shortcut' => 'ch',
        !          60886:             'options' => array(),
        !          60887:             'doc' => '[parameter]
        !          60888: Displays help for a configuration parameter.  Without arguments it
        !          60889: displays help for all configuration parameters.
        !          60890: ',
        !          60891:            ),
        !          60892:         'config-create' => array(
        !          60893:             'summary' => 'Create a Default configuration file',
        !          60894:             'function' => 'doConfigCreate',
        !          60895:             'shortcut' => 'coc',
        !          60896:             'options' => array(
        !          60897:                 'windows' => array(
        !          60898:                     'shortopt' => 'w',
        !          60899:                     'doc' => 'create a config file for a windows install',
        !          60900:                     ),
        !          60901:             ),
        !          60902:             'doc' => '<root path> <filename>
        !          60903: Create a default configuration file with all directory configuration
        !          60904: variables set to subdirectories of <root path>, and save it as <filename>.
        !          60905: This is useful especially for creating a configuration file for a remote
        !          60906: PEAR installation (using the --remoteconfig option of install, upgrade,
        !          60907: and uninstall).
        !          60908: ',
        !          60909:             ),
        !          60910:         );
1.1       misho    60911: 
                   60912:     /**
1.1.1.2 ! misho    60913:      * PEAR_Command_Config constructor.
1.1       misho    60914:      *
                   60915:      * @access public
                   60916:      */
1.1.1.2 ! misho    60917:     function PEAR_Command_Config(&$ui, &$config)
1.1       misho    60918:     {
1.1.1.2 ! misho    60919:         parent::PEAR_Command_Common($ui, $config);
1.1       misho    60920:     }
                   60921: 
1.1.1.2 ! misho    60922:     function doConfigShow($command, $options, $params)
1.1       misho    60923:     {
1.1.1.2 ! misho    60924:         $layer = null;
        !          60925:         if (is_array($params)) {
        !          60926:             $layer = isset($params[0]) ? $params[0] : null;
1.1       misho    60927:         }
                   60928: 
1.1.1.2 ! misho    60929:         // $params[0] -> the layer
        !          60930:         if ($error = $this->_checkLayer($layer)) {
        !          60931:             return $this->raiseError("config-show:$error");
1.1       misho    60932:         }
                   60933: 
1.1.1.2 ! misho    60934:         $keys = $this->config->getKeys();
        !          60935:         sort($keys);
        !          60936:         $channel = isset($options['channel']) ? $options['channel'] :
        !          60937:             $this->config->get('default_channel');
        !          60938:         $reg = &$this->config->getRegistry();
        !          60939:         if (!$reg->channelExists($channel)) {
        !          60940:             return $this->raiseError('Channel "' . $channel . '" does not exist');
1.1       misho    60941:         }
                   60942: 
1.1.1.2 ! misho    60943:         $channel = $reg->channelName($channel);
        !          60944:         $data = array('caption' => 'Configuration (channel ' . $channel . '):');
        !          60945:         foreach ($keys as $key) {
        !          60946:             $type = $this->config->getType($key);
        !          60947:             $value = $this->config->get($key, $layer, $channel);
        !          60948:             if ($type == 'password' && $value) {
        !          60949:                 $value = '********';
1.1       misho    60950:             }
                   60951: 
1.1.1.2 ! misho    60952:             if ($value === false) {
        !          60953:                 $value = 'false';
        !          60954:             } elseif ($value === true) {
        !          60955:                 $value = 'true';
        !          60956:             }
1.1       misho    60957: 
1.1.1.2 ! misho    60958:             $data['data'][$this->config->getGroup($key)][] = array($this->config->getPrompt($key) , $key, $value);
        !          60959:         }
1.1       misho    60960: 
1.1.1.2 ! misho    60961:         foreach ($this->config->getLayers() as $layer) {
        !          60962:             $data['data']['Config Files'][] = array(ucfirst($layer) . ' Configuration File', 'Filename' , $this->config->getConfFile($layer));
        !          60963:         }
1.1       misho    60964: 
1.1.1.2 ! misho    60965:         $this->ui->outputData($data, $command);
        !          60966:         return true;
1.1       misho    60967:     }
                   60968: 
1.1.1.2 ! misho    60969:     function doConfigGet($command, $options, $params)
1.1       misho    60970:     {
1.1.1.2 ! misho    60971:         $args_cnt = is_array($params) ? count($params) : 0;
        !          60972:         switch ($args_cnt) {
        !          60973:             case 1:
        !          60974:                 $config_key = $params[0];
        !          60975:                 $layer = null;
        !          60976:                 break;
        !          60977:             case 2:
        !          60978:                 $config_key = $params[0];
        !          60979:                 $layer = $params[1];
        !          60980:                 if ($error = $this->_checkLayer($layer)) {
        !          60981:                     return $this->raiseError("config-get:$error");
        !          60982:                 }
        !          60983:                 break;
        !          60984:             case 0:
        !          60985:             default:
        !          60986:                 return $this->raiseError("config-get expects 1 or 2 parameters");
1.1       misho    60987:         }
                   60988: 
1.1.1.2 ! misho    60989:         $reg = &$this->config->getRegistry();
        !          60990:         $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
        !          60991:         if (!$reg->channelExists($channel)) {
        !          60992:             return $this->raiseError('Channel "' . $channel . '" does not exist');
        !          60993:         }
        !          60994: 
        !          60995:         $channel = $reg->channelName($channel);
        !          60996:         $this->ui->outputData($this->config->get($config_key, $layer, $channel), $command);
        !          60997:         return true;
1.1       misho    60998:     }
                   60999: 
1.1.1.2 ! misho    61000:     function doConfigSet($command, $options, $params)
1.1       misho    61001:     {
1.1.1.2 ! misho    61002:         // $param[0] -> a parameter to set
        !          61003:         // $param[1] -> the value for the parameter
        !          61004:         // $param[2] -> the layer
        !          61005:         $failmsg = '';
        !          61006:         if (count($params) < 2 || count($params) > 3) {
        !          61007:             $failmsg .= "config-set expects 2 or 3 parameters";
        !          61008:             return PEAR::raiseError($failmsg);
        !          61009:         }
1.1       misho    61010: 
1.1.1.2 ! misho    61011:         if (isset($params[2]) && ($error = $this->_checkLayer($params[2]))) {
        !          61012:             $failmsg .= $error;
        !          61013:             return PEAR::raiseError("config-set:$failmsg");
        !          61014:         }
1.1       misho    61015: 
1.1.1.2 ! misho    61016:         $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
        !          61017:         $reg = &$this->config->getRegistry();
        !          61018:         if (!$reg->channelExists($channel)) {
        !          61019:             return $this->raiseError('Channel "' . $channel . '" does not exist');
1.1       misho    61020:         }
                   61021: 
1.1.1.2 ! misho    61022:         $channel = $reg->channelName($channel);
        !          61023:         if ($params[0] == 'default_channel' && !$reg->channelExists($params[1])) {
        !          61024:             return $this->raiseError('Channel "' . $params[1] . '" does not exist');
        !          61025:         }
1.1       misho    61026: 
1.1.1.2 ! misho    61027:         if ($params[0] == 'preferred_mirror'
        !          61028:             && (
        !          61029:                 !$reg->mirrorExists($channel, $params[1]) &&
        !          61030:                 (!$reg->channelExists($params[1]) || $channel != $params[1])
        !          61031:             )
        !          61032:         ) {
        !          61033:             $msg  = 'Channel Mirror "' . $params[1] . '" does not exist';
        !          61034:             $msg .= ' in your registry for channel "' . $channel . '".';
        !          61035:             $msg .= "\n" . 'Attempt to run "pear channel-update ' . $channel .'"';
        !          61036:             $msg .= ' if you believe this mirror should exist as you may';
        !          61037:             $msg .= ' have outdated channel information.';
        !          61038:             return $this->raiseError($msg);
        !          61039:         }
1.1       misho    61040: 
1.1.1.2 ! misho    61041:         if (count($params) == 2) {
        !          61042:             array_push($params, 'user');
        !          61043:             $layer = 'user';
1.1       misho    61044:         } else {
1.1.1.2 ! misho    61045:             $layer = $params[2];
1.1       misho    61046:         }
                   61047: 
1.1.1.2 ! misho    61048:         array_push($params, $channel);
        !          61049:         if (!call_user_func_array(array(&$this->config, 'set'), $params)) {
        !          61050:             array_pop($params);
        !          61051:             $failmsg = "config-set (" . implode(", ", $params) . ") failed, channel $channel";
        !          61052:         } else {
        !          61053:             $this->config->store($layer);
        !          61054:         }
1.1       misho    61055: 
1.1.1.2 ! misho    61056:         if ($failmsg) {
        !          61057:             return $this->raiseError($failmsg);
1.1       misho    61058:         }
                   61059: 
1.1.1.2 ! misho    61060:         $this->ui->outputData('config-set succeeded', $command);
1.1       misho    61061:         return true;
                   61062:     }
                   61063: 
1.1.1.2 ! misho    61064:     function doConfigHelp($command, $options, $params)
1.1       misho    61065:     {
1.1.1.2 ! misho    61066:         if (empty($params)) {
        !          61067:             $params = $this->config->getKeys();
1.1       misho    61068:         }
                   61069: 
1.1.1.2 ! misho    61070:         $data['caption']  = "Config help" . ((count($params) == 1) ? " for $params[0]" : '');
        !          61071:         $data['headline'] = array('Name', 'Type', 'Description');
        !          61072:         $data['border']   = true;
        !          61073:         foreach ($params as $name) {
        !          61074:             $type = $this->config->getType($name);
        !          61075:             $docs = $this->config->getDocs($name);
        !          61076:             if ($type == 'set') {
        !          61077:                 $docs = rtrim($docs) . "\nValid set: " .
        !          61078:                     implode(' ', $this->config->getSetValues($name));
1.1       misho    61079:             }
                   61080: 
1.1.1.2 ! misho    61081:             $data['data'][] = array($name, $type, $docs);
1.1       misho    61082:         }
                   61083: 
1.1.1.2 ! misho    61084:         $this->ui->outputData($data, $command);
        !          61085:     }
1.1       misho    61086: 
1.1.1.2 ! misho    61087:     function doConfigCreate($command, $options, $params)
        !          61088:     {
        !          61089:         if (count($params) != 2) {
        !          61090:             return PEAR::raiseError('config-create: must have 2 parameters, root path and ' .
        !          61091:                 'filename to save as');
1.1       misho    61092:         }
                   61093: 
1.1.1.2 ! misho    61094:         $root = $params[0];
        !          61095:         // Clean up the DIRECTORY_SEPARATOR mess
        !          61096:         $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
        !          61097:         $root = preg_replace(array('!\\\\+!', '!/+!', "!$ds2+!"),
        !          61098:                              array('/', '/', '/'),
        !          61099:                             $root);
        !          61100:         if ($root{0} != '/') {
        !          61101:             if (!isset($options['windows'])) {
        !          61102:                 return PEAR::raiseError('Root directory must be an absolute path beginning ' .
        !          61103:                     'with "/", was: "' . $root . '"');
1.1       misho    61104:             }
                   61105: 
1.1.1.2 ! misho    61106:             if (!preg_match('/^[A-Za-z]:/', $root)) {
        !          61107:                 return PEAR::raiseError('Root directory must be an absolute path beginning ' .
        !          61108:                     'with "\\" or "C:\\", was: "' . $root . '"');
1.1       misho    61109:             }
1.1.1.2 ! misho    61110:         }
1.1       misho    61111: 
1.1.1.2 ! misho    61112:         $windows = isset($options['windows']);
        !          61113:         if ($windows) {
        !          61114:             $root = str_replace('/', '\\', $root);
1.1       misho    61115:         }
                   61116: 
1.1.1.2 ! misho    61117:         if (!file_exists($params[1]) && !@touch($params[1])) {
        !          61118:             return PEAR::raiseError('Could not create "' . $params[1] . '"');
1.1       misho    61119:         }
                   61120: 
1.1.1.2 ! misho    61121:         $params[1] = realpath($params[1]);
        !          61122:         $config = &new PEAR_Config($params[1], '#no#system#config#', false, false);
        !          61123:         if ($root{strlen($root) - 1} == '/') {
        !          61124:             $root = substr($root, 0, strlen($root) - 1);
        !          61125:         }
        !          61126: 
        !          61127:         $config->noRegistry();
        !          61128:         $config->set('php_dir', $windows ? "$root\\pear\\php" : "$root/pear/php", 'user');
        !          61129:         $config->set('data_dir', $windows ? "$root\\pear\\data" : "$root/pear/data");
        !          61130:         $config->set('www_dir', $windows ? "$root\\pear\\www" : "$root/pear/www");
        !          61131:         $config->set('cfg_dir', $windows ? "$root\\pear\\cfg" : "$root/pear/cfg");
        !          61132:         $config->set('ext_dir', $windows ? "$root\\pear\\ext" : "$root/pear/ext");
        !          61133:         $config->set('doc_dir', $windows ? "$root\\pear\\docs" : "$root/pear/docs");
        !          61134:         $config->set('test_dir', $windows ? "$root\\pear\\tests" : "$root/pear/tests");
        !          61135:         $config->set('cache_dir', $windows ? "$root\\pear\\cache" : "$root/pear/cache");
        !          61136:         $config->set('download_dir', $windows ? "$root\\pear\\download" : "$root/pear/download");
        !          61137:         $config->set('temp_dir', $windows ? "$root\\pear\\temp" : "$root/pear/temp");
        !          61138:         $config->set('bin_dir', $windows ? "$root\\pear" : "$root/pear");
        !          61139:         $config->writeConfigFile();
        !          61140:         $this->_showConfig($config);
        !          61141:         $this->ui->outputData('Successfully created default configuration file "' . $params[1] . '"',
        !          61142:             $command);
1.1       misho    61143:     }
                   61144: 
1.1.1.2 ! misho    61145:     function _showConfig(&$config)
1.1       misho    61146:     {
1.1.1.2 ! misho    61147:         $params = array('user');
        !          61148:         $keys = $config->getKeys();
        !          61149:         sort($keys);
        !          61150:         $channel = 'pear.php.net';
        !          61151:         $data = array('caption' => 'Configuration (channel ' . $channel . '):');
        !          61152:         foreach ($keys as $key) {
        !          61153:             $type = $config->getType($key);
        !          61154:             $value = $config->get($key, 'user', $channel);
        !          61155:             if ($type == 'password' && $value) {
        !          61156:                 $value = '********';
        !          61157:             }
1.1       misho    61158: 
1.1.1.2 ! misho    61159:             if ($value === false) {
        !          61160:                 $value = 'false';
        !          61161:             } elseif ($value === true) {
        !          61162:                 $value = 'true';
        !          61163:             }
        !          61164:             $data['data'][$config->getGroup($key)][] =
        !          61165:                 array($config->getPrompt($key) , $key, $value);
1.1       misho    61166:         }
                   61167: 
1.1.1.2 ! misho    61168:         foreach ($config->getLayers() as $layer) {
        !          61169:             $data['data']['Config Files'][] =
        !          61170:                 array(ucfirst($layer) . ' Configuration File', 'Filename' ,
        !          61171:                     $config->getConfFile($layer));
1.1       misho    61172:         }
                   61173: 
1.1.1.2 ! misho    61174:         $this->ui->outputData($data, 'config-show');
        !          61175:         return true;
1.1       misho    61176:     }
                   61177: 
                   61178:     /**
1.1.1.2 ! misho    61179:      * Checks if a layer is defined or not
1.1       misho    61180:      *
1.1.1.2 ! misho    61181:      * @param string $layer The layer to search for
        !          61182:      * @return mixed False on no error or the error message
1.1       misho    61183:      */
1.1.1.2 ! misho    61184:     function _checkLayer($layer = null)
1.1       misho    61185:     {
1.1.1.2 ! misho    61186:         if (!empty($layer) && $layer != 'default') {
        !          61187:             $layers = $this->config->getLayers();
        !          61188:             if (!in_array($layer, $layers)) {
        !          61189:                 return " only the layers: \"" . implode('" or "', $layers) . "\" are supported";
        !          61190:             }
1.1       misho    61191:         }
                   61192: 
1.1.1.2 ! misho    61193:         return false;
        !          61194:     }
        !          61195: }<commands version="1.0">
        !          61196:  <config-show>
        !          61197:   <summary>Show All Settings</summary>
        !          61198:   <function>doConfigShow</function>
        !          61199:   <shortcut>csh</shortcut>
        !          61200:   <options>
        !          61201:    <channel>
        !          61202:     <shortopt>c</shortopt>
        !          61203:     <doc>show configuration variables for another channel</doc>
        !          61204:     <arg>CHAN</arg>
        !          61205:    </channel>
        !          61206:   </options>
        !          61207:   <doc>[layer]
        !          61208: Displays all configuration values.  An optional argument
        !          61209: may be used to tell which configuration layer to display.  Valid
        !          61210: configuration layers are &quot;user&quot;, &quot;system&quot; and &quot;default&quot;. To display
        !          61211: configurations for different channels, set the default_channel
        !          61212: configuration variable and run config-show again.
        !          61213: </doc>
        !          61214:  </config-show>
        !          61215:  <config-get>
        !          61216:   <summary>Show One Setting</summary>
        !          61217:   <function>doConfigGet</function>
        !          61218:   <shortcut>cg</shortcut>
        !          61219:   <options>
        !          61220:    <channel>
        !          61221:     <shortopt>c</shortopt>
        !          61222:     <doc>show configuration variables for another channel</doc>
        !          61223:     <arg>CHAN</arg>
        !          61224:    </channel>
        !          61225:   </options>
        !          61226:   <doc>&lt;parameter&gt; [layer]
        !          61227: Displays the value of one configuration parameter.  The
        !          61228: first argument is the name of the parameter, an optional second argument
        !          61229: may be used to tell which configuration layer to look in.  Valid configuration
        !          61230: layers are &quot;user&quot;, &quot;system&quot; and &quot;default&quot;.  If no layer is specified, a value
        !          61231: will be picked from the first layer that defines the parameter, in the order
        !          61232: just specified.  The configuration value will be retrieved for the channel
        !          61233: specified by the default_channel configuration variable.
        !          61234: </doc>
        !          61235:  </config-get>
        !          61236:  <config-set>
        !          61237:   <summary>Change Setting</summary>
        !          61238:   <function>doConfigSet</function>
        !          61239:   <shortcut>cs</shortcut>
        !          61240:   <options>
        !          61241:    <channel>
        !          61242:     <shortopt>c</shortopt>
        !          61243:     <doc>show configuration variables for another channel</doc>
        !          61244:     <arg>CHAN</arg>
        !          61245:    </channel>
        !          61246:   </options>
        !          61247:   <doc>&lt;parameter&gt; &lt;value&gt; [layer]
        !          61248: Sets the value of one configuration parameter.  The first argument is
        !          61249: the name of the parameter, the second argument is the new value.  Some
        !          61250: parameters are subject to validation, and the command will fail with
        !          61251: an error message if the new value does not make sense.  An optional
        !          61252: third argument may be used to specify in which layer to set the
        !          61253: configuration parameter.  The default layer is &quot;user&quot;.  The
        !          61254: configuration value will be set for the current channel, which
        !          61255: is controlled by the default_channel configuration variable.
        !          61256: </doc>
        !          61257:  </config-set>
        !          61258:  <config-help>
        !          61259:   <summary>Show Information About Setting</summary>
        !          61260:   <function>doConfigHelp</function>
        !          61261:   <shortcut>ch</shortcut>
        !          61262:   <options />
        !          61263:   <doc>[parameter]
        !          61264: Displays help for a configuration parameter.  Without arguments it
        !          61265: displays help for all configuration parameters.
        !          61266: </doc>
        !          61267:  </config-help>
        !          61268:  <config-create>
        !          61269:   <summary>Create a Default configuration file</summary>
        !          61270:   <function>doConfigCreate</function>
        !          61271:   <shortcut>coc</shortcut>
        !          61272:   <options>
        !          61273:    <windows>
        !          61274:     <shortopt>w</shortopt>
        !          61275:     <doc>create a config file for a windows install</doc>
        !          61276:    </windows>
        !          61277:   </options>
        !          61278:   <doc>&lt;root path&gt; &lt;filename&gt;
        !          61279: Create a default configuration file with all directory configuration
        !          61280: variables set to subdirectories of &lt;root path&gt;, and save it as &lt;filename&gt;.
        !          61281: This is useful especially for creating a configuration file for a remote
        !          61282: PEAR installation (using the --remoteconfig option of install, upgrade,
        !          61283: and uninstall).
        !          61284: </doc>
        !          61285:  </config-create>
        !          61286: </commands><?php
1.1       misho    61287: /**
1.1.1.2 ! misho    61288:  * PEAR_Command_Install (install, upgrade, upgrade-all, uninstall, bundle, run-scripts commands)
1.1       misho    61289:  *
                   61290:  * PHP versions 4 and 5
                   61291:  *
                   61292:  * @category   pear
                   61293:  * @package    PEAR
                   61294:  * @author     Stig Bakken <ssb@php.net>
                   61295:  * @author     Greg Beaver <cellog@php.net>
                   61296:  * @copyright  1997-2009 The Authors
                   61297:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    61298:  * @version    CVS: $Id: Install.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    61299:  * @link       http://pear.php.net/package/PEAR
                   61300:  * @since      File available since Release 0.1
                   61301:  */
                   61302: 
                   61303: /**
1.1.1.2 ! misho    61304:  * base class
1.1       misho    61305:  */
1.1.1.2 ! misho    61306: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Common.php';
1.1       misho    61307: 
                   61308: /**
1.1.1.2 ! misho    61309:  * PEAR commands for installation or deinstallation/upgrading of
        !          61310:  * packages.
        !          61311:  *
        !          61312:  * @category   pear
        !          61313:  * @package    PEAR
        !          61314:  * @author     Stig Bakken <ssb@php.net>
        !          61315:  * @author     Greg Beaver <cellog@php.net>
        !          61316:  * @copyright  1997-2009 The Authors
        !          61317:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          61318:  * @version    Release: 1.9.4
        !          61319:  * @link       http://pear.php.net/package/PEAR
        !          61320:  * @since      Class available since Release 0.1
1.1       misho    61321:  */
1.1.1.2 ! misho    61322: class PEAR_Command_Install extends PEAR_Command_Common
        !          61323: {
        !          61324:     // {{{ properties
1.1       misho    61325: 
1.1.1.2 ! misho    61326:     var $commands = array(
        !          61327:         'install' => array(
        !          61328:             'summary' => 'Install Package',
        !          61329:             'function' => 'doInstall',
        !          61330:             'shortcut' => 'i',
        !          61331:             'options' => array(
        !          61332:                 'force' => array(
        !          61333:                     'shortopt' => 'f',
        !          61334:                     'doc' => 'will overwrite newer installed packages',
        !          61335:                     ),
        !          61336:                 'loose' => array(
        !          61337:                     'shortopt' => 'l',
        !          61338:                     'doc' => 'do not check for recommended dependency version',
        !          61339:                     ),
        !          61340:                 'nodeps' => array(
        !          61341:                     'shortopt' => 'n',
        !          61342:                     'doc' => 'ignore dependencies, install anyway',
        !          61343:                     ),
        !          61344:                 'register-only' => array(
        !          61345:                     'shortopt' => 'r',
        !          61346:                     'doc' => 'do not install files, only register the package as installed',
        !          61347:                     ),
        !          61348:                 'soft' => array(
        !          61349:                     'shortopt' => 's',
        !          61350:                     'doc' => 'soft install, fail silently, or upgrade if already installed',
        !          61351:                     ),
        !          61352:                 'nobuild' => array(
        !          61353:                     'shortopt' => 'B',
        !          61354:                     'doc' => 'don\'t build C extensions',
        !          61355:                     ),
        !          61356:                 'nocompress' => array(
        !          61357:                     'shortopt' => 'Z',
        !          61358:                     'doc' => 'request uncompressed files when downloading',
        !          61359:                     ),
        !          61360:                 'installroot' => array(
        !          61361:                     'shortopt' => 'R',
        !          61362:                     'arg' => 'DIR',
        !          61363:                     'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
        !          61364:                     ),
        !          61365:                 'packagingroot' => array(
        !          61366:                     'shortopt' => 'P',
        !          61367:                     'arg' => 'DIR',
        !          61368:                     'doc' => 'root directory used when packaging files, like RPM packaging',
        !          61369:                     ),
        !          61370:                 'ignore-errors' => array(
        !          61371:                     'doc' => 'force install even if there were errors',
        !          61372:                     ),
        !          61373:                 'alldeps' => array(
        !          61374:                     'shortopt' => 'a',
        !          61375:                     'doc' => 'install all required and optional dependencies',
        !          61376:                     ),
        !          61377:                 'onlyreqdeps' => array(
        !          61378:                     'shortopt' => 'o',
        !          61379:                     'doc' => 'install all required dependencies',
        !          61380:                     ),
        !          61381:                 'offline' => array(
        !          61382:                     'shortopt' => 'O',
        !          61383:                     'doc' => 'do not attempt to download any urls or contact channels',
        !          61384:                     ),
        !          61385:                 'pretend' => array(
        !          61386:                     'shortopt' => 'p',
        !          61387:                     'doc' => 'Only list the packages that would be downloaded',
        !          61388:                     ),
        !          61389:                 ),
        !          61390:             'doc' => '[channel/]<package> ...
        !          61391: Installs one or more PEAR packages.  You can specify a package to
        !          61392: install in four ways:
1.1       misho    61393: 
1.1.1.2 ! misho    61394: "Package-1.0.tgz" : installs from a local file
1.1       misho    61395: 
1.1.1.2 ! misho    61396: "http://example.com/Package-1.0.tgz" : installs from
        !          61397: anywhere on the net.
1.1       misho    61398: 
1.1.1.2 ! misho    61399: "package.xml" : installs the package described in
        !          61400: package.xml.  Useful for testing, or for wrapping a PEAR package in
        !          61401: another package manager such as RPM.
1.1       misho    61402: 
1.1.1.2 ! misho    61403: "Package[-version/state][.tar]" : queries your default channel\'s server
        !          61404: ({config master_server}) and downloads the newest package with
        !          61405: the preferred quality/state ({config preferred_state}).
1.1       misho    61406: 
1.1.1.2 ! misho    61407: To retrieve Package version 1.1, use "Package-1.1," to retrieve
        !          61408: Package state beta, use "Package-beta."  To retrieve an uncompressed
        !          61409: file, append .tar (make sure there is no file by the same name first)
1.1       misho    61410: 
1.1.1.2 ! misho    61411: To download a package from another channel, prefix with the channel name like
        !          61412: "channel/Package"
1.1       misho    61413: 
1.1.1.2 ! misho    61414: More than one package may be specified at once.  It is ok to mix these
        !          61415: four ways of specifying packages.
        !          61416: '),
        !          61417:         'upgrade' => array(
        !          61418:             'summary' => 'Upgrade Package',
        !          61419:             'function' => 'doInstall',
        !          61420:             'shortcut' => 'up',
        !          61421:             'options' => array(
        !          61422:                 'channel' => array(
        !          61423:                     'shortopt' => 'c',
        !          61424:                     'doc' => 'upgrade packages from a specific channel',
        !          61425:                     'arg' => 'CHAN',
        !          61426:                     ),
        !          61427:                 'force' => array(
        !          61428:                     'shortopt' => 'f',
        !          61429:                     'doc' => 'overwrite newer installed packages',
        !          61430:                     ),
        !          61431:                 'loose' => array(
        !          61432:                     'shortopt' => 'l',
        !          61433:                     'doc' => 'do not check for recommended dependency version',
        !          61434:                     ),
        !          61435:                 'nodeps' => array(
        !          61436:                     'shortopt' => 'n',
        !          61437:                     'doc' => 'ignore dependencies, upgrade anyway',
        !          61438:                     ),
        !          61439:                 'register-only' => array(
        !          61440:                     'shortopt' => 'r',
        !          61441:                     'doc' => 'do not install files, only register the package as upgraded',
        !          61442:                     ),
        !          61443:                 'nobuild' => array(
        !          61444:                     'shortopt' => 'B',
        !          61445:                     'doc' => 'don\'t build C extensions',
        !          61446:                     ),
        !          61447:                 'nocompress' => array(
        !          61448:                     'shortopt' => 'Z',
        !          61449:                     'doc' => 'request uncompressed files when downloading',
        !          61450:                     ),
        !          61451:                 'installroot' => array(
        !          61452:                     'shortopt' => 'R',
        !          61453:                     'arg' => 'DIR',
        !          61454:                     'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
        !          61455:                     ),
        !          61456:                 'ignore-errors' => array(
        !          61457:                     'doc' => 'force install even if there were errors',
        !          61458:                     ),
        !          61459:                 'alldeps' => array(
        !          61460:                     'shortopt' => 'a',
        !          61461:                     'doc' => 'install all required and optional dependencies',
        !          61462:                     ),
        !          61463:                 'onlyreqdeps' => array(
        !          61464:                     'shortopt' => 'o',
        !          61465:                     'doc' => 'install all required dependencies',
        !          61466:                     ),
        !          61467:                 'offline' => array(
        !          61468:                     'shortopt' => 'O',
        !          61469:                     'doc' => 'do not attempt to download any urls or contact channels',
        !          61470:                     ),
        !          61471:                 'pretend' => array(
        !          61472:                     'shortopt' => 'p',
        !          61473:                     'doc' => 'Only list the packages that would be downloaded',
        !          61474:                     ),
        !          61475:                 ),
        !          61476:             'doc' => '<package> ...
        !          61477: Upgrades one or more PEAR packages.  See documentation for the
        !          61478: "install" command for ways to specify a package.
        !          61479: 
        !          61480: When upgrading, your package will be updated if the provided new
        !          61481: package has a higher version number (use the -f option if you need to
        !          61482: upgrade anyway).
        !          61483: 
        !          61484: More than one package may be specified at once.
        !          61485: '),
        !          61486:         'upgrade-all' => array(
        !          61487:             'summary' => 'Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]',
        !          61488:             'function' => 'doUpgradeAll',
        !          61489:             'shortcut' => 'ua',
        !          61490:             'options' => array(
        !          61491:                 'channel' => array(
        !          61492:                     'shortopt' => 'c',
        !          61493:                     'doc' => 'upgrade packages from a specific channel',
        !          61494:                     'arg' => 'CHAN',
        !          61495:                     ),
        !          61496:                 'nodeps' => array(
        !          61497:                     'shortopt' => 'n',
        !          61498:                     'doc' => 'ignore dependencies, upgrade anyway',
        !          61499:                     ),
        !          61500:                 'register-only' => array(
        !          61501:                     'shortopt' => 'r',
        !          61502:                     'doc' => 'do not install files, only register the package as upgraded',
        !          61503:                     ),
        !          61504:                 'nobuild' => array(
        !          61505:                     'shortopt' => 'B',
        !          61506:                     'doc' => 'don\'t build C extensions',
        !          61507:                     ),
        !          61508:                 'nocompress' => array(
        !          61509:                     'shortopt' => 'Z',
        !          61510:                     'doc' => 'request uncompressed files when downloading',
        !          61511:                     ),
        !          61512:                 'installroot' => array(
        !          61513:                     'shortopt' => 'R',
        !          61514:                     'arg' => 'DIR',
        !          61515:                     'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
        !          61516:                     ),
        !          61517:                 'ignore-errors' => array(
        !          61518:                     'doc' => 'force install even if there were errors',
        !          61519:                     ),
        !          61520:                 'loose' => array(
        !          61521:                     'doc' => 'do not check for recommended dependency version',
        !          61522:                     ),
        !          61523:                 ),
        !          61524:             'doc' => '
        !          61525: WARNING: This function is deprecated in favor of using the upgrade command with no params
        !          61526: 
        !          61527: Upgrades all packages that have a newer release available.  Upgrades are
        !          61528: done only if there is a release available of the state specified in
        !          61529: "preferred_state" (currently {config preferred_state}), or a state considered
        !          61530: more stable.
        !          61531: '),
        !          61532:         'uninstall' => array(
        !          61533:             'summary' => 'Un-install Package',
        !          61534:             'function' => 'doUninstall',
        !          61535:             'shortcut' => 'un',
        !          61536:             'options' => array(
        !          61537:                 'nodeps' => array(
        !          61538:                     'shortopt' => 'n',
        !          61539:                     'doc' => 'ignore dependencies, uninstall anyway',
        !          61540:                     ),
        !          61541:                 'register-only' => array(
        !          61542:                     'shortopt' => 'r',
        !          61543:                     'doc' => 'do not remove files, only register the packages as not installed',
        !          61544:                     ),
        !          61545:                 'installroot' => array(
        !          61546:                     'shortopt' => 'R',
        !          61547:                     'arg' => 'DIR',
        !          61548:                     'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
        !          61549:                     ),
        !          61550:                 'ignore-errors' => array(
        !          61551:                     'doc' => 'force install even if there were errors',
        !          61552:                     ),
        !          61553:                 'offline' => array(
        !          61554:                     'shortopt' => 'O',
        !          61555:                     'doc' => 'do not attempt to uninstall remotely',
        !          61556:                     ),
        !          61557:                 ),
        !          61558:             'doc' => '[channel/]<package> ...
        !          61559: Uninstalls one or more PEAR packages.  More than one package may be
        !          61560: specified at once.  Prefix with channel name to uninstall from a
        !          61561: channel not in your default channel ({config default_channel})
        !          61562: '),
        !          61563:         'bundle' => array(
        !          61564:             'summary' => 'Unpacks a Pecl Package',
        !          61565:             'function' => 'doBundle',
        !          61566:             'shortcut' => 'bun',
        !          61567:             'options' => array(
        !          61568:                 'destination' => array(
        !          61569:                    'shortopt' => 'd',
        !          61570:                     'arg' => 'DIR',
        !          61571:                     'doc' => 'Optional destination directory for unpacking (defaults to current path or "ext" if exists)',
        !          61572:                     ),
        !          61573:                 'force' => array(
        !          61574:                     'shortopt' => 'f',
        !          61575:                     'doc' => 'Force the unpacking even if there were errors in the package',
        !          61576:                 ),
        !          61577:             ),
        !          61578:             'doc' => '<package>
        !          61579: Unpacks a Pecl Package into the selected location. It will download the
        !          61580: package if needed.
        !          61581: '),
        !          61582:         'run-scripts' => array(
        !          61583:             'summary' => 'Run Post-Install Scripts bundled with a package',
        !          61584:             'function' => 'doRunScripts',
        !          61585:             'shortcut' => 'rs',
        !          61586:             'options' => array(
        !          61587:             ),
        !          61588:             'doc' => '<package>
        !          61589: Run post-installation scripts in package <package>, if any exist.
        !          61590: '),
        !          61591:     );
        !          61592: 
        !          61593:     // }}}
        !          61594:     // {{{ constructor
        !          61595: 
        !          61596:     /**
        !          61597:      * PEAR_Command_Install constructor.
        !          61598:      *
        !          61599:      * @access public
        !          61600:      */
        !          61601:     function PEAR_Command_Install(&$ui, &$config)
        !          61602:     {
        !          61603:         parent::PEAR_Command_Common($ui, $config);
        !          61604:     }
        !          61605: 
        !          61606:     // }}}
        !          61607: 
        !          61608:     /**
        !          61609:      * For unit testing purposes
        !          61610:      */
        !          61611:     function &getDownloader(&$ui, $options, &$config)
        !          61612:     {
        !          61613:         if (!class_exists('PEAR_Downloader')) {
        !          61614:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Downloader.php';
        !          61615:         }
        !          61616:         $a = &new PEAR_Downloader($ui, $options, $config);
        !          61617:         return $a;
        !          61618:     }
        !          61619: 
        !          61620:     /**
        !          61621:      * For unit testing purposes
        !          61622:      */
        !          61623:     function &getInstaller(&$ui)
        !          61624:     {
        !          61625:         if (!class_exists('PEAR_Installer')) {
        !          61626:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Installer.php';
        !          61627:         }
        !          61628:         $a = &new PEAR_Installer($ui);
        !          61629:         return $a;
        !          61630:     }
        !          61631: 
        !          61632:     function enableExtension($binaries, $type)
        !          61633:     {
        !          61634:         if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) {
        !          61635:             return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location');
        !          61636:         }
        !          61637:         $ini = $this->_parseIni($phpini);
        !          61638:         if (PEAR::isError($ini)) {
        !          61639:             return $ini;
        !          61640:         }
        !          61641:         $line = 0;
        !          61642:         if ($type == 'extsrc' || $type == 'extbin') {
        !          61643:             $search = 'extensions';
        !          61644:             $enable = 'extension';
        !          61645:         } else {
        !          61646:             $search = 'zend_extensions';
        !          61647:             ob_start();
        !          61648:             phpinfo(INFO_GENERAL);
        !          61649:             $info = ob_get_contents();
        !          61650:             ob_end_clean();
        !          61651:             $debug = function_exists('leak') ? '_debug' : '';
        !          61652:             $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
        !          61653:             $enable = 'zend_extension' . $debug . $ts;
        !          61654:         }
        !          61655:         foreach ($ini[$search] as $line => $extension) {
        !          61656:             if (in_array($extension, $binaries, true) || in_array(
        !          61657:                   $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) {
        !          61658:                 // already enabled - assume if one is, all are
        !          61659:                 return true;
        !          61660:             }
        !          61661:         }
        !          61662:         if ($line) {
        !          61663:             $newini = array_slice($ini['all'], 0, $line);
        !          61664:         } else {
        !          61665:             $newini = array();
        !          61666:         }
        !          61667:         foreach ($binaries as $binary) {
        !          61668:             if ($ini['extension_dir']) {
        !          61669:                 $binary = basename($binary);
        !          61670:             }
        !          61671:             $newini[] = $enable . '="' . $binary . '"' . (OS_UNIX ? "\n" : "\r\n");
        !          61672:         }
        !          61673:         $newini = array_merge($newini, array_slice($ini['all'], $line));
        !          61674:         $fp = @fopen($phpini, 'wb');
        !          61675:         if (!$fp) {
        !          61676:             return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing');
        !          61677:         }
        !          61678:         foreach ($newini as $line) {
        !          61679:             fwrite($fp, $line);
        !          61680:         }
        !          61681:         fclose($fp);
        !          61682:         return true;
        !          61683:     }
        !          61684: 
        !          61685:     function disableExtension($binaries, $type)
        !          61686:     {
        !          61687:         if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) {
        !          61688:             return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location');
        !          61689:         }
        !          61690:         $ini = $this->_parseIni($phpini);
        !          61691:         if (PEAR::isError($ini)) {
        !          61692:             return $ini;
        !          61693:         }
        !          61694:         $line = 0;
        !          61695:         if ($type == 'extsrc' || $type == 'extbin') {
        !          61696:             $search = 'extensions';
        !          61697:             $enable = 'extension';
        !          61698:         } else {
        !          61699:             $search = 'zend_extensions';
        !          61700:             ob_start();
        !          61701:             phpinfo(INFO_GENERAL);
        !          61702:             $info = ob_get_contents();
        !          61703:             ob_end_clean();
        !          61704:             $debug = function_exists('leak') ? '_debug' : '';
        !          61705:             $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
        !          61706:             $enable = 'zend_extension' . $debug . $ts;
        !          61707:         }
        !          61708:         $found = false;
        !          61709:         foreach ($ini[$search] as $line => $extension) {
        !          61710:             if (in_array($extension, $binaries, true) || in_array(
        !          61711:                   $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) {
        !          61712:                 $found = true;
        !          61713:                 break;
        !          61714:             }
        !          61715:         }
        !          61716:         if (!$found) {
        !          61717:             // not enabled
        !          61718:             return true;
        !          61719:         }
        !          61720:         $fp = @fopen($phpini, 'wb');
        !          61721:         if (!$fp) {
        !          61722:             return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing');
        !          61723:         }
        !          61724:         if ($line) {
        !          61725:             $newini = array_slice($ini['all'], 0, $line);
        !          61726:             // delete the enable line
        !          61727:             $newini = array_merge($newini, array_slice($ini['all'], $line + 1));
        !          61728:         } else {
        !          61729:             $newini = array_slice($ini['all'], 1);
        !          61730:         }
        !          61731:         foreach ($newini as $line) {
        !          61732:             fwrite($fp, $line);
        !          61733:         }
        !          61734:         fclose($fp);
        !          61735:         return true;
        !          61736:     }
        !          61737: 
        !          61738:     function _parseIni($filename)
        !          61739:     {
        !          61740:         if (!file_exists($filename)) {
        !          61741:             return PEAR::raiseError('php.ini "' . $filename . '" does not exist');
        !          61742:         }
        !          61743: 
        !          61744:         if (filesize($filename) > 300000) {
        !          61745:             return PEAR::raiseError('php.ini "' . $filename . '" is too large, aborting');
        !          61746:         }
        !          61747: 
        !          61748:         ob_start();
        !          61749:         phpinfo(INFO_GENERAL);
        !          61750:         $info = ob_get_contents();
        !          61751:         ob_end_clean();
        !          61752:         $debug = function_exists('leak') ? '_debug' : '';
        !          61753:         $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
        !          61754:         $zend_extension_line = 'zend_extension' . $debug . $ts;
        !          61755:         $all = @file($filename);
        !          61756:         if (!$all) {
        !          61757:             return PEAR::raiseError('php.ini "' . $filename .'" could not be read');
        !          61758:         }
        !          61759:         $zend_extensions = $extensions = array();
        !          61760:         // assume this is right, but pull from the php.ini if it is found
        !          61761:         $extension_dir = ini_get('extension_dir');
        !          61762:         foreach ($all as $linenum => $line) {
        !          61763:             $line = trim($line);
        !          61764:             if (!$line) {
        !          61765:                 continue;
        !          61766:             }
        !          61767:             if ($line[0] == ';') {
        !          61768:                 continue;
        !          61769:             }
        !          61770:             if (strtolower(substr($line, 0, 13)) == 'extension_dir') {
        !          61771:                 $line = trim(substr($line, 13));
        !          61772:                 if ($line[0] == '=') {
        !          61773:                     $x = trim(substr($line, 1));
        !          61774:                     $x = explode(';', $x);
        !          61775:                     $extension_dir = str_replace('"', '', array_shift($x));
        !          61776:                     continue;
        !          61777:                 }
        !          61778:             }
        !          61779:             if (strtolower(substr($line, 0, 9)) == 'extension') {
        !          61780:                 $line = trim(substr($line, 9));
        !          61781:                 if ($line[0] == '=') {
        !          61782:                     $x = trim(substr($line, 1));
        !          61783:                     $x = explode(';', $x);
        !          61784:                     $extensions[$linenum] = str_replace('"', '', array_shift($x));
        !          61785:                     continue;
        !          61786:                 }
        !          61787:             }
        !          61788:             if (strtolower(substr($line, 0, strlen($zend_extension_line))) ==
        !          61789:                   $zend_extension_line) {
        !          61790:                 $line = trim(substr($line, strlen($zend_extension_line)));
        !          61791:                 if ($line[0] == '=') {
        !          61792:                     $x = trim(substr($line, 1));
        !          61793:                     $x = explode(';', $x);
        !          61794:                     $zend_extensions[$linenum] = str_replace('"', '', array_shift($x));
        !          61795:                     continue;
        !          61796:                 }
        !          61797:             }
        !          61798:         }
        !          61799:         return array(
        !          61800:             'extensions' => $extensions,
        !          61801:             'zend_extensions' => $zend_extensions,
        !          61802:             'extension_dir' => $extension_dir,
        !          61803:             'all' => $all,
        !          61804:         );
        !          61805:     }
        !          61806: 
        !          61807:     // {{{ doInstall()
        !          61808: 
        !          61809:     function doInstall($command, $options, $params)
        !          61810:     {
        !          61811:         if (!class_exists('PEAR_PackageFile')) {
        !          61812:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile.php';
        !          61813:         }
        !          61814: 
        !          61815:         if (isset($options['installroot']) && isset($options['packagingroot'])) {
        !          61816:             return $this->raiseError('ERROR: cannot use both --installroot and --packagingroot');
        !          61817:         }
        !          61818: 
        !          61819:         $reg = &$this->config->getRegistry();
        !          61820:         $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
        !          61821:         if (!$reg->channelExists($channel)) {
        !          61822:             return $this->raiseError('Channel "' . $channel . '" does not exist');
        !          61823:         }
        !          61824: 
        !          61825:         if (empty($this->installer)) {
        !          61826:             $this->installer = &$this->getInstaller($this->ui);
        !          61827:         }
        !          61828: 
        !          61829:         if ($command == 'upgrade' || $command == 'upgrade-all') {
        !          61830:             // If people run the upgrade command but pass nothing, emulate a upgrade-all
        !          61831:             if ($command == 'upgrade' && empty($params)) {
        !          61832:                 return $this->doUpgradeAll($command, $options, $params);
        !          61833:             }
        !          61834:             $options['upgrade'] = true;
        !          61835:         } else {
        !          61836:             $packages = $params;
        !          61837:         }
        !          61838: 
        !          61839:         $instreg = &$reg; // instreg used to check if package is installed
        !          61840:         if (isset($options['packagingroot']) && !isset($options['upgrade'])) {
        !          61841:             $packrootphp_dir = $this->installer->_prependPath(
        !          61842:                 $this->config->get('php_dir', null, 'pear.php.net'),
        !          61843:                 $options['packagingroot']);
        !          61844:             $instreg = new PEAR_Registry($packrootphp_dir); // other instreg!
        !          61845: 
        !          61846:             if ($this->config->get('verbose') > 2) {
        !          61847:                 $this->ui->outputData('using package root: ' . $options['packagingroot']);
        !          61848:             }
        !          61849:         }
        !          61850: 
        !          61851:         $abstractpackages = $otherpackages = array();
        !          61852:         // parse params
        !          61853:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          61854: 
        !          61855:         foreach ($params as $param) {
        !          61856:             if (strpos($param, 'http://') === 0) {
        !          61857:                 $otherpackages[] = $param;
        !          61858:                 continue;
        !          61859:             }
        !          61860: 
        !          61861:             if (strpos($param, 'channel://') === false && @file_exists($param)) {
        !          61862:                 if (isset($options['force'])) {
        !          61863:                     $otherpackages[] = $param;
        !          61864:                     continue;
        !          61865:                 }
        !          61866: 
        !          61867:                 $pkg = new PEAR_PackageFile($this->config);
        !          61868:                 $pf  = $pkg->fromAnyFile($param, PEAR_VALIDATE_DOWNLOADING);
        !          61869:                 if (PEAR::isError($pf)) {
        !          61870:                     $otherpackages[] = $param;
        !          61871:                     continue;
        !          61872:                 }
        !          61873: 
        !          61874:                 $exists   = $reg->packageExists($pf->getPackage(), $pf->getChannel());
        !          61875:                 $pversion = $reg->packageInfo($pf->getPackage(), 'version', $pf->getChannel());
        !          61876:                 $version_compare = version_compare($pf->getVersion(), $pversion, '<=');
        !          61877:                 if ($exists && $version_compare) {
        !          61878:                     if ($this->config->get('verbose')) {
        !          61879:                         $this->ui->outputData('Ignoring installed package ' .
        !          61880:                             $reg->parsedPackageNameToString(
        !          61881:                             array('package' => $pf->getPackage(),
        !          61882:                                   'channel' => $pf->getChannel()), true));
        !          61883:                     }
        !          61884:                     continue;
        !          61885:                 }
        !          61886:                 $otherpackages[] = $param;
        !          61887:                 continue;
        !          61888:             }
        !          61889: 
        !          61890:             $e = $reg->parsePackageName($param, $channel);
        !          61891:             if (PEAR::isError($e)) {
        !          61892:                 $otherpackages[] = $param;
        !          61893:             } else {
        !          61894:                 $abstractpackages[] = $e;
        !          61895:             }
        !          61896:         }
        !          61897:         PEAR::staticPopErrorHandling();
        !          61898: 
        !          61899:         // if there are any local package .tgz or remote static url, we can't
        !          61900:         // filter.  The filter only works for abstract packages
        !          61901:         if (count($abstractpackages) && !isset($options['force'])) {
        !          61902:             // when not being forced, only do necessary upgrades/installs
        !          61903:             if (isset($options['upgrade'])) {
        !          61904:                 $abstractpackages = $this->_filterUptodatePackages($abstractpackages, $command);
        !          61905:             } else {
        !          61906:                 $count = count($abstractpackages);
        !          61907:                 foreach ($abstractpackages as $i => $package) {
        !          61908:                     if (isset($package['group'])) {
        !          61909:                         // do not filter out install groups
        !          61910:                         continue;
        !          61911:                     }
        !          61912: 
        !          61913:                     if ($instreg->packageExists($package['package'], $package['channel'])) {
        !          61914:                         if ($count > 1) {
        !          61915:                             if ($this->config->get('verbose')) {
        !          61916:                                 $this->ui->outputData('Ignoring installed package ' .
        !          61917:                                     $reg->parsedPackageNameToString($package, true));
        !          61918:                             }
        !          61919:                             unset($abstractpackages[$i]);
        !          61920:                         } elseif ($count === 1) {
        !          61921:                             // Lets try to upgrade it since it's already installed
        !          61922:                             $options['upgrade'] = true;
        !          61923:                         }
        !          61924:                     }
        !          61925:                 }
        !          61926:             }
        !          61927:             $abstractpackages =
        !          61928:                 array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages);
        !          61929:         } elseif (count($abstractpackages)) {
        !          61930:             $abstractpackages =
        !          61931:                 array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages);
        !          61932:         }
        !          61933: 
        !          61934:         $packages = array_merge($abstractpackages, $otherpackages);
        !          61935:         if (!count($packages)) {
        !          61936:             $c = '';
        !          61937:             if (isset($options['channel'])){
        !          61938:                 $c .= ' in channel "' . $options['channel'] . '"';
        !          61939:             }
        !          61940:             $this->ui->outputData('Nothing to ' . $command . $c);
        !          61941:             return true;
        !          61942:         }
        !          61943: 
        !          61944:         $this->downloader = &$this->getDownloader($this->ui, $options, $this->config);
        !          61945:         $errors = $downloaded = $binaries = array();
        !          61946:         $downloaded = &$this->downloader->download($packages);
        !          61947:         if (PEAR::isError($downloaded)) {
        !          61948:             return $this->raiseError($downloaded);
        !          61949:         }
        !          61950: 
        !          61951:         $errors = $this->downloader->getErrorMsgs();
        !          61952:         if (count($errors)) {
        !          61953:             $err = array();
        !          61954:             $err['data'] = array();
        !          61955:             foreach ($errors as $error) {
        !          61956:                 if ($error !== null) {
        !          61957:                     $err['data'][] = array($error);
        !          61958:                 }
        !          61959:             }
        !          61960: 
        !          61961:             if (!empty($err['data'])) {
        !          61962:                 $err['headline'] = 'Install Errors';
        !          61963:                 $this->ui->outputData($err);
        !          61964:             }
        !          61965: 
        !          61966:             if (!count($downloaded)) {
        !          61967:                 return $this->raiseError("$command failed");
        !          61968:             }
        !          61969:         }
        !          61970: 
        !          61971:         $data = array(
        !          61972:             'headline' => 'Packages that would be Installed'
        !          61973:         );
        !          61974: 
        !          61975:         if (isset($options['pretend'])) {
        !          61976:             foreach ($downloaded as $package) {
        !          61977:                 $data['data'][] = array($reg->parsedPackageNameToString($package->getParsedPackage()));
        !          61978:             }
        !          61979:             $this->ui->outputData($data, 'pretend');
        !          61980:             return true;
        !          61981:         }
        !          61982: 
        !          61983:         $this->installer->setOptions($options);
        !          61984:         $this->installer->sortPackagesForInstall($downloaded);
        !          61985:         if (PEAR::isError($err = $this->installer->setDownloadedPackages($downloaded))) {
        !          61986:             $this->raiseError($err->getMessage());
        !          61987:             return true;
        !          61988:         }
        !          61989: 
        !          61990:         $binaries = $extrainfo = array();
        !          61991:         foreach ($downloaded as $param) {
        !          61992:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          61993:             $info = $this->installer->install($param, $options);
        !          61994:             PEAR::staticPopErrorHandling();
        !          61995:             if (PEAR::isError($info)) {
        !          61996:                 $oldinfo = $info;
        !          61997:                 $pkg = &$param->getPackageFile();
        !          61998:                 if ($info->getCode() != PEAR_INSTALLER_NOBINARY) {
        !          61999:                     if (!($info = $pkg->installBinary($this->installer))) {
        !          62000:                         $this->ui->outputData('ERROR: ' .$oldinfo->getMessage());
        !          62001:                         continue;
        !          62002:                     }
        !          62003: 
        !          62004:                     // we just installed a different package than requested,
        !          62005:                     // let's change the param and info so that the rest of this works
        !          62006:                     $param = $info[0];
        !          62007:                     $info  = $info[1];
        !          62008:                 }
        !          62009:             }
        !          62010: 
        !          62011:             if (!is_array($info)) {
        !          62012:                 return $this->raiseError("$command failed");
        !          62013:             }
        !          62014: 
        !          62015:             if ($param->getPackageType() == 'extsrc' ||
        !          62016:                   $param->getPackageType() == 'extbin' ||
        !          62017:                   $param->getPackageType() == 'zendextsrc' ||
        !          62018:                   $param->getPackageType() == 'zendextbin'
        !          62019:             ) {
        !          62020:                 $pkg = &$param->getPackageFile();
        !          62021:                 if ($instbin = $pkg->getInstalledBinary()) {
        !          62022:                     $instpkg = &$instreg->getPackage($instbin, $pkg->getChannel());
        !          62023:                 } else {
        !          62024:                     $instpkg = &$instreg->getPackage($pkg->getPackage(), $pkg->getChannel());
        !          62025:                 }
        !          62026: 
        !          62027:                 foreach ($instpkg->getFilelist() as $name => $atts) {
        !          62028:                     $pinfo = pathinfo($atts['installed_as']);
        !          62029:                     if (!isset($pinfo['extension']) ||
        !          62030:                           in_array($pinfo['extension'], array('c', 'h'))
        !          62031:                     ) {
        !          62032:                         continue; // make sure we don't match php_blah.h
        !          62033:                     }
        !          62034: 
        !          62035:                     if ((strpos($pinfo['basename'], 'php_') === 0 &&
        !          62036:                           $pinfo['extension'] == 'dll') ||
        !          62037:                           // most unices
        !          62038:                           $pinfo['extension'] == 'so' ||
        !          62039:                           // hp-ux
        !          62040:                           $pinfo['extension'] == 'sl') {
        !          62041:                         $binaries[] = array($atts['installed_as'], $pinfo);
        !          62042:                         break;
        !          62043:                     }
        !          62044:                 }
        !          62045: 
        !          62046:                 if (count($binaries)) {
        !          62047:                     foreach ($binaries as $pinfo) {
        !          62048:                         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          62049:                         $ret = $this->enableExtension(array($pinfo[0]), $param->getPackageType());
        !          62050:                         PEAR::staticPopErrorHandling();
        !          62051:                         if (PEAR::isError($ret)) {
        !          62052:                             $extrainfo[] = $ret->getMessage();
        !          62053:                             if ($param->getPackageType() == 'extsrc' ||
        !          62054:                                   $param->getPackageType() == 'extbin') {
        !          62055:                                 $exttype = 'extension';
        !          62056:                             } else {
        !          62057:                                 ob_start();
        !          62058:                                 phpinfo(INFO_GENERAL);
        !          62059:                                 $info = ob_get_contents();
        !          62060:                                 ob_end_clean();
        !          62061:                                 $debug = function_exists('leak') ? '_debug' : '';
        !          62062:                                 $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
        !          62063:                                 $exttype = 'zend_extension' . $debug . $ts;
        !          62064:                             }
        !          62065:                             $extrainfo[] = 'You should add "' . $exttype . '=' .
        !          62066:                                 $pinfo[1]['basename'] . '" to php.ini';
        !          62067:                         } else {
        !          62068:                             $extrainfo[] = 'Extension ' . $instpkg->getProvidesExtension() .
        !          62069:                                 ' enabled in php.ini';
        !          62070:                         }
        !          62071:                     }
        !          62072:                 }
        !          62073:             }
        !          62074: 
        !          62075:             if ($this->config->get('verbose') > 0) {
        !          62076:                 $chan = $param->getChannel();
        !          62077:                 $label = $reg->parsedPackageNameToString(
        !          62078:                     array(
        !          62079:                         'channel' => $chan,
        !          62080:                         'package' => $param->getPackage(),
        !          62081:                         'version' => $param->getVersion(),
        !          62082:                     ));
        !          62083:                 $out = array('data' => "$command ok: $label");
        !          62084:                 if (isset($info['release_warnings'])) {
        !          62085:                     $out['release_warnings'] = $info['release_warnings'];
        !          62086:                 }
        !          62087:                 $this->ui->outputData($out, $command);
        !          62088: 
        !          62089:                 if (!isset($options['register-only']) && !isset($options['offline'])) {
        !          62090:                     if ($this->config->isDefinedLayer('ftp')) {
        !          62091:                         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          62092:                         $info = $this->installer->ftpInstall($param);
        !          62093:                         PEAR::staticPopErrorHandling();
        !          62094:                         if (PEAR::isError($info)) {
        !          62095:                             $this->ui->outputData($info->getMessage());
        !          62096:                             $this->ui->outputData("remote install failed: $label");
        !          62097:                         } else {
        !          62098:                             $this->ui->outputData("remote install ok: $label");
        !          62099:                         }
        !          62100:                     }
        !          62101:                 }
        !          62102:             }
        !          62103: 
        !          62104:             $deps = $param->getDeps();
        !          62105:             if ($deps) {
        !          62106:                 if (isset($deps['group'])) {
        !          62107:                     $groups = $deps['group'];
        !          62108:                     if (!isset($groups[0])) {
        !          62109:                         $groups = array($groups);
        !          62110:                     }
        !          62111: 
        !          62112:                     foreach ($groups as $group) {
        !          62113:                         if ($group['attribs']['name'] == 'default') {
        !          62114:                             // default group is always installed, unless the user
        !          62115:                             // explicitly chooses to install another group
        !          62116:                             continue;
        !          62117:                         }
        !          62118:                         $extrainfo[] = $param->getPackage() . ': Optional feature ' .
        !          62119:                             $group['attribs']['name'] . ' available (' .
        !          62120:                             $group['attribs']['hint'] . ')';
        !          62121:                     }
        !          62122: 
        !          62123:                     $extrainfo[] = $param->getPackage() .
        !          62124:                         ': To install optional features use "pear install ' .
        !          62125:                         $reg->parsedPackageNameToString(
        !          62126:                             array('package' => $param->getPackage(),
        !          62127:                                   'channel' => $param->getChannel()), true) .
        !          62128:                               '#featurename"';
        !          62129:                 }
        !          62130:             }
        !          62131: 
        !          62132:             $pkg = &$instreg->getPackage($param->getPackage(), $param->getChannel());
        !          62133:             // $pkg may be NULL if install is a 'fake' install via --packagingroot
        !          62134:             if (is_object($pkg)) {
        !          62135:                 $pkg->setConfig($this->config);
        !          62136:                 if ($list = $pkg->listPostinstallScripts()) {
        !          62137:                     $pn = $reg->parsedPackageNameToString(array('channel' =>
        !          62138:                        $param->getChannel(), 'package' => $param->getPackage()), true);
        !          62139:                     $extrainfo[] = $pn . ' has post-install scripts:';
        !          62140:                     foreach ($list as $file) {
        !          62141:                         $extrainfo[] = $file;
        !          62142:                     }
        !          62143:                     $extrainfo[] = $param->getPackage() .
        !          62144:                         ': Use "pear run-scripts ' . $pn . '" to finish setup.';
        !          62145:                     $extrainfo[] = 'DO NOT RUN SCRIPTS FROM UNTRUSTED SOURCES';
        !          62146:                 }
        !          62147:             }
        !          62148:         }
        !          62149: 
        !          62150:         if (count($extrainfo)) {
        !          62151:             foreach ($extrainfo as $info) {
        !          62152:                 $this->ui->outputData($info);
        !          62153:             }
        !          62154:         }
        !          62155: 
        !          62156:         return true;
        !          62157:     }
        !          62158: 
        !          62159:     // }}}
        !          62160:     // {{{ doUpgradeAll()
        !          62161: 
        !          62162:     function doUpgradeAll($command, $options, $params)
        !          62163:     {
        !          62164:         $reg = &$this->config->getRegistry();
        !          62165:         $upgrade = array();
        !          62166: 
        !          62167:         if (isset($options['channel'])) {
        !          62168:             $channels = array($options['channel']);
        !          62169:         } else {
        !          62170:             $channels = $reg->listChannels();
        !          62171:         }
        !          62172: 
        !          62173:         foreach ($channels as $channel) {
        !          62174:             if ($channel == '__uri') {
        !          62175:                 continue;
        !          62176:             }
        !          62177: 
        !          62178:             // parse name with channel
        !          62179:             foreach ($reg->listPackages($channel) as $name) {
        !          62180:                 $upgrade[] = $reg->parsedPackageNameToString(array(
        !          62181:                         'channel' => $channel,
        !          62182:                         'package' => $name
        !          62183:                     ));
        !          62184:             }
        !          62185:         }
        !          62186: 
        !          62187:         $err = $this->doInstall($command, $options, $upgrade);
        !          62188:         if (PEAR::isError($err)) {
        !          62189:             $this->ui->outputData($err->getMessage(), $command);
        !          62190:         }
        !          62191:    }
        !          62192: 
        !          62193:     // }}}
        !          62194:     // {{{ doUninstall()
        !          62195: 
        !          62196:     function doUninstall($command, $options, $params)
        !          62197:     {
        !          62198:         if (count($params) < 1) {
        !          62199:             return $this->raiseError("Please supply the package(s) you want to uninstall");
        !          62200:         }
        !          62201: 
        !          62202:         if (empty($this->installer)) {
        !          62203:             $this->installer = &$this->getInstaller($this->ui);
        !          62204:         }
        !          62205: 
        !          62206:         if (isset($options['remoteconfig'])) {
        !          62207:             $e = $this->config->readFTPConfigFile($options['remoteconfig']);
        !          62208:             if (!PEAR::isError($e)) {
        !          62209:                 $this->installer->setConfig($this->config);
        !          62210:             }
        !          62211:         }
        !          62212: 
        !          62213:         $reg = &$this->config->getRegistry();
        !          62214:         $newparams = array();
        !          62215:         $binaries = array();
        !          62216:         $badparams = array();
        !          62217:         foreach ($params as $pkg) {
        !          62218:             $channel = $this->config->get('default_channel');
        !          62219:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          62220:             $parsed = $reg->parsePackageName($pkg, $channel);
        !          62221:             PEAR::staticPopErrorHandling();
        !          62222:             if (!$parsed || PEAR::isError($parsed)) {
        !          62223:                 $badparams[] = $pkg;
        !          62224:                 continue;
        !          62225:             }
        !          62226:             $package = $parsed['package'];
        !          62227:             $channel = $parsed['channel'];
        !          62228:             $info = &$reg->getPackage($package, $channel);
        !          62229:             if ($info === null &&
        !          62230:                  ($channel == 'pear.php.net' || $channel == 'pecl.php.net')) {
        !          62231:                 // make sure this isn't a package that has flipped from pear to pecl but
        !          62232:                 // used a package.xml 1.0
        !          62233:                 $testc = ($channel == 'pear.php.net') ? 'pecl.php.net' : 'pear.php.net';
        !          62234:                 $info = &$reg->getPackage($package, $testc);
        !          62235:                 if ($info !== null) {
        !          62236:                     $channel = $testc;
        !          62237:                 }
        !          62238:             }
        !          62239:             if ($info === null) {
        !          62240:                 $badparams[] = $pkg;
        !          62241:             } else {
        !          62242:                 $newparams[] = &$info;
        !          62243:                 // check for binary packages (this is an alias for those packages if so)
        !          62244:                 if ($installedbinary = $info->getInstalledBinary()) {
        !          62245:                     $this->ui->log('adding binary package ' .
        !          62246:                         $reg->parsedPackageNameToString(array('channel' => $channel,
        !          62247:                             'package' => $installedbinary), true));
        !          62248:                     $newparams[] = &$reg->getPackage($installedbinary, $channel);
        !          62249:                 }
        !          62250:                 // add the contents of a dependency group to the list of installed packages
        !          62251:                 if (isset($parsed['group'])) {
        !          62252:                     $group = $info->getDependencyGroup($parsed['group']);
        !          62253:                     if ($group) {
        !          62254:                         $installed = $reg->getInstalledGroup($group);
        !          62255:                         if ($installed) {
        !          62256:                             foreach ($installed as $i => $p) {
        !          62257:                                 $newparams[] = &$installed[$i];
        !          62258:                             }
        !          62259:                         }
        !          62260:                     }
        !          62261:                 }
        !          62262:             }
        !          62263:         }
        !          62264:         $err = $this->installer->sortPackagesForUninstall($newparams);
        !          62265:         if (PEAR::isError($err)) {
        !          62266:             $this->ui->outputData($err->getMessage(), $command);
        !          62267:             return true;
        !          62268:         }
        !          62269:         $params = $newparams;
        !          62270:         // twist this to use it to check on whether dependent packages are also being uninstalled
        !          62271:         // for circular dependencies like subpackages
        !          62272:         $this->installer->setUninstallPackages($newparams);
        !          62273:         $params = array_merge($params, $badparams);
        !          62274:         $binaries = array();
        !          62275:         foreach ($params as $pkg) {
        !          62276:             $this->installer->pushErrorHandling(PEAR_ERROR_RETURN);
        !          62277:             if ($err = $this->installer->uninstall($pkg, $options)) {
        !          62278:                 $this->installer->popErrorHandling();
        !          62279:                 if (PEAR::isError($err)) {
        !          62280:                     $this->ui->outputData($err->getMessage(), $command);
        !          62281:                     continue;
        !          62282:                 }
        !          62283:                 if ($pkg->getPackageType() == 'extsrc' ||
        !          62284:                       $pkg->getPackageType() == 'extbin' ||
        !          62285:                       $pkg->getPackageType() == 'zendextsrc' ||
        !          62286:                       $pkg->getPackageType() == 'zendextbin') {
        !          62287:                     if ($instbin = $pkg->getInstalledBinary()) {
        !          62288:                         continue; // this will be uninstalled later
        !          62289:                     }
        !          62290: 
        !          62291:                     foreach ($pkg->getFilelist() as $name => $atts) {
        !          62292:                         $pinfo = pathinfo($atts['installed_as']);
        !          62293:                         if (!isset($pinfo['extension']) ||
        !          62294:                               in_array($pinfo['extension'], array('c', 'h'))) {
        !          62295:                             continue; // make sure we don't match php_blah.h
        !          62296:                         }
        !          62297:                         if ((strpos($pinfo['basename'], 'php_') === 0 &&
        !          62298:                               $pinfo['extension'] == 'dll') ||
        !          62299:                               // most unices
        !          62300:                               $pinfo['extension'] == 'so' ||
        !          62301:                               // hp-ux
        !          62302:                               $pinfo['extension'] == 'sl') {
        !          62303:                             $binaries[] = array($atts['installed_as'], $pinfo);
        !          62304:                             break;
        !          62305:                         }
        !          62306:                     }
        !          62307:                     if (count($binaries)) {
        !          62308:                         foreach ($binaries as $pinfo) {
        !          62309:                             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          62310:                             $ret = $this->disableExtension(array($pinfo[0]), $pkg->getPackageType());
        !          62311:                             PEAR::staticPopErrorHandling();
        !          62312:                             if (PEAR::isError($ret)) {
        !          62313:                                 $extrainfo[] = $ret->getMessage();
        !          62314:                                 if ($pkg->getPackageType() == 'extsrc' ||
        !          62315:                                       $pkg->getPackageType() == 'extbin') {
        !          62316:                                     $exttype = 'extension';
        !          62317:                                 } else {
        !          62318:                                     ob_start();
        !          62319:                                     phpinfo(INFO_GENERAL);
        !          62320:                                     $info = ob_get_contents();
        !          62321:                                     ob_end_clean();
        !          62322:                                     $debug = function_exists('leak') ? '_debug' : '';
        !          62323:                                     $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
        !          62324:                                     $exttype = 'zend_extension' . $debug . $ts;
        !          62325:                                 }
        !          62326:                                 $this->ui->outputData('Unable to remove "' . $exttype . '=' .
        !          62327:                                     $pinfo[1]['basename'] . '" from php.ini', $command);
        !          62328:                             } else {
        !          62329:                                 $this->ui->outputData('Extension ' . $pkg->getProvidesExtension() .
        !          62330:                                     ' disabled in php.ini', $command);
        !          62331:                             }
        !          62332:                         }
        !          62333:                     }
        !          62334:                 }
        !          62335:                 $savepkg = $pkg;
        !          62336:                 if ($this->config->get('verbose') > 0) {
        !          62337:                     if (is_object($pkg)) {
        !          62338:                         $pkg = $reg->parsedPackageNameToString($pkg);
        !          62339:                     }
        !          62340:                     $this->ui->outputData("uninstall ok: $pkg", $command);
        !          62341:                 }
        !          62342:                 if (!isset($options['offline']) && is_object($savepkg) &&
        !          62343:                       defined('PEAR_REMOTEINSTALL_OK')) {
        !          62344:                     if ($this->config->isDefinedLayer('ftp')) {
        !          62345:                         $this->installer->pushErrorHandling(PEAR_ERROR_RETURN);
        !          62346:                         $info = $this->installer->ftpUninstall($savepkg);
        !          62347:                         $this->installer->popErrorHandling();
        !          62348:                         if (PEAR::isError($info)) {
        !          62349:                             $this->ui->outputData($info->getMessage());
        !          62350:                             $this->ui->outputData("remote uninstall failed: $pkg");
        !          62351:                         } else {
        !          62352:                             $this->ui->outputData("remote uninstall ok: $pkg");
        !          62353:                         }
        !          62354:                     }
        !          62355:                 }
        !          62356:             } else {
        !          62357:                 $this->installer->popErrorHandling();
        !          62358:                 if (!is_object($pkg)) {
        !          62359:                     return $this->raiseError("uninstall failed: $pkg");
        !          62360:                 }
        !          62361:                 $pkg = $reg->parsedPackageNameToString($pkg);
        !          62362:             }
        !          62363:         }
        !          62364: 
        !          62365:         return true;
        !          62366:     }
        !          62367: 
        !          62368:     // }}}
        !          62369: 
        !          62370: 
        !          62371:     // }}}
        !          62372:     // {{{ doBundle()
        !          62373:     /*
        !          62374:     (cox) It just downloads and untars the package, does not do
        !          62375:             any check that the PEAR_Installer::_installFile() does.
        !          62376:     */
        !          62377: 
        !          62378:     function doBundle($command, $options, $params)
        !          62379:     {
        !          62380:         $opts = array(
        !          62381:             'force'        => true,
        !          62382:             'nodeps'       => true,
        !          62383:             'soft'         => true,
        !          62384:             'downloadonly' => true
        !          62385:         );
        !          62386:         $downloader = &$this->getDownloader($this->ui, $opts, $this->config);
        !          62387:         $reg = &$this->config->getRegistry();
        !          62388:         if (count($params) < 1) {
        !          62389:             return $this->raiseError("Please supply the package you want to bundle");
        !          62390:         }
        !          62391: 
        !          62392:         if (isset($options['destination'])) {
        !          62393:             if (!is_dir($options['destination'])) {
        !          62394:                 System::mkdir('-p ' . $options['destination']);
        !          62395:             }
        !          62396:             $dest = realpath($options['destination']);
        !          62397:         } else {
        !          62398:             $pwd  = getcwd();
        !          62399:             $dir  = $pwd . DIRECTORY_SEPARATOR . 'ext';
        !          62400:             $dest = is_dir($dir) ? $dir : $pwd;
        !          62401:         }
        !          62402:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          62403:         $err = $downloader->setDownloadDir($dest);
        !          62404:         PEAR::staticPopErrorHandling();
        !          62405:         if (PEAR::isError($err)) {
        !          62406:             return PEAR::raiseError('download directory "' . $dest .
        !          62407:                 '" is not writeable.');
        !          62408:         }
        !          62409:         $result = &$downloader->download(array($params[0]));
        !          62410:         if (PEAR::isError($result)) {
        !          62411:             return $result;
        !          62412:         }
        !          62413:         if (!isset($result[0])) {
        !          62414:             return $this->raiseError('unable to unpack ' . $params[0]);
        !          62415:         }
        !          62416:         $pkgfile = &$result[0]->getPackageFile();
        !          62417:         $pkgname = $pkgfile->getName();
        !          62418:         $pkgversion = $pkgfile->getVersion();
        !          62419: 
        !          62420:         // Unpacking -------------------------------------------------
        !          62421:         $dest .= DIRECTORY_SEPARATOR . $pkgname;
        !          62422:         $orig = $pkgname . '-' . $pkgversion;
        !          62423: 
        !          62424:         $tar = &new Archive_Tar($pkgfile->getArchiveFile());
        !          62425:         if (!$tar->extractModify($dest, $orig)) {
        !          62426:             return $this->raiseError('unable to unpack ' . $pkgfile->getArchiveFile());
        !          62427:         }
        !          62428:         $this->ui->outputData("Package ready at '$dest'");
        !          62429:     // }}}
        !          62430:     }
        !          62431: 
        !          62432:     // }}}
        !          62433: 
        !          62434:     function doRunScripts($command, $options, $params)
        !          62435:     {
        !          62436:         if (!isset($params[0])) {
        !          62437:             return $this->raiseError('run-scripts expects 1 parameter: a package name');
        !          62438:         }
        !          62439: 
        !          62440:         $reg = &$this->config->getRegistry();
        !          62441:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          62442:         $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
        !          62443:         PEAR::staticPopErrorHandling();
        !          62444:         if (PEAR::isError($parsed)) {
        !          62445:             return $this->raiseError($parsed);
        !          62446:         }
        !          62447: 
        !          62448:         $package = &$reg->getPackage($parsed['package'], $parsed['channel']);
        !          62449:         if (!is_object($package)) {
        !          62450:             return $this->raiseError('Could not retrieve package "' . $params[0] . '" from registry');
        !          62451:         }
        !          62452: 
        !          62453:         $package->setConfig($this->config);
        !          62454:         $package->runPostinstallScripts();
        !          62455:         $this->ui->outputData('Install scripts complete', $command);
        !          62456:         return true;
        !          62457:     }
        !          62458: 
        !          62459:     /**
        !          62460:      * Given a list of packages, filter out those ones that are already up to date
        !          62461:      *
        !          62462:      * @param $packages: packages, in parsed array format !
        !          62463:      * @return list of packages that can be upgraded
        !          62464:      */
        !          62465:     function _filterUptodatePackages($packages, $command)
        !          62466:     {
        !          62467:         $reg = &$this->config->getRegistry();
        !          62468:         $latestReleases = array();
        !          62469: 
        !          62470:         $ret = array();
        !          62471:         foreach ($packages as $package) {
        !          62472:             if (isset($package['group'])) {
        !          62473:                 $ret[] = $package;
        !          62474:                 continue;
        !          62475:             }
        !          62476: 
        !          62477:             $channel = $package['channel'];
        !          62478:             $name    = $package['package'];
        !          62479:             if (!$reg->packageExists($name, $channel)) {
        !          62480:                 $ret[] = $package;
        !          62481:                 continue;
        !          62482:             }
        !          62483: 
        !          62484:             if (!isset($latestReleases[$channel])) {
        !          62485:                 // fill in cache for this channel
        !          62486:                 $chan = &$reg->getChannel($channel);
        !          62487:                 if (PEAR::isError($chan)) {
        !          62488:                     return $this->raiseError($chan);
        !          62489:                 }
        !          62490: 
        !          62491:                 $base2 = false;
        !          62492:                 $preferred_mirror = $this->config->get('preferred_mirror', null, $channel);
        !          62493:                 if ($chan->supportsREST($preferred_mirror) &&
        !          62494:                     (
        !          62495:                        //($base2 = $chan->getBaseURL('REST1.4', $preferred_mirror)) ||
        !          62496:                        ($base  = $chan->getBaseURL('REST1.0', $preferred_mirror))
        !          62497:                     )
        !          62498:                 ) {
        !          62499:                     $dorest = true;
        !          62500:                 }
        !          62501: 
        !          62502:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          62503:                 if (!isset($package['state'])) {
        !          62504:                     $state = $this->config->get('preferred_state', null, $channel);
        !          62505:                 } else {
        !          62506:                     $state = $package['state'];
        !          62507:                 }
        !          62508: 
        !          62509:                 if ($dorest) {
        !          62510:                     if ($base2) {
        !          62511:                         $rest = &$this->config->getREST('1.4', array());
        !          62512:                         $base = $base2;
        !          62513:                     } else {
        !          62514:                         $rest = &$this->config->getREST('1.0', array());
        !          62515:                     }
        !          62516: 
        !          62517:                     $installed = array_flip($reg->listPackages($channel));
        !          62518:                     $latest    = $rest->listLatestUpgrades($base, $state, $installed, $channel, $reg);
        !          62519:                 }
        !          62520: 
        !          62521:                 PEAR::staticPopErrorHandling();
        !          62522:                 if (PEAR::isError($latest)) {
        !          62523:                     $this->ui->outputData('Error getting channel info from ' . $channel .
        !          62524:                         ': ' . $latest->getMessage());
        !          62525:                     continue;
        !          62526:                 }
        !          62527: 
        !          62528:                 $latestReleases[$channel] = array_change_key_case($latest);
        !          62529:             }
        !          62530: 
        !          62531:             // check package for latest release
        !          62532:             $name_lower = strtolower($name);
        !          62533:             if (isset($latestReleases[$channel][$name_lower])) {
        !          62534:                 // if not set, up to date
        !          62535:                 $inst_version    = $reg->packageInfo($name, 'version', $channel);
        !          62536:                 $channel_version = $latestReleases[$channel][$name_lower]['version'];
        !          62537:                 if (version_compare($channel_version, $inst_version, 'le')) {
        !          62538:                     // installed version is up-to-date
        !          62539:                     continue;
        !          62540:                 }
        !          62541: 
        !          62542:                 // maintain BC
        !          62543:                 if ($command == 'upgrade-all') {
        !          62544:                     $this->ui->outputData(array('data' => 'Will upgrade ' .
        !          62545:                         $reg->parsedPackageNameToString($package)), $command);
        !          62546:                 }
        !          62547:                 $ret[] = $package;
        !          62548:             }
        !          62549:         }
        !          62550: 
        !          62551:         return $ret;
        !          62552:     }
        !          62553: }<commands version="1.0">
        !          62554:  <install>
        !          62555:   <summary>Install Package</summary>
        !          62556:   <function>doInstall</function>
        !          62557:   <shortcut>i</shortcut>
        !          62558:   <options>
        !          62559:    <force>
        !          62560:     <shortopt>f</shortopt>
        !          62561:     <doc>will overwrite newer installed packages</doc>
        !          62562:    </force>
        !          62563:    <loose>
        !          62564:     <shortopt>l</shortopt>
        !          62565:     <doc>do not check for recommended dependency version</doc>
        !          62566:    </loose>
        !          62567:    <nodeps>
        !          62568:     <shortopt>n</shortopt>
        !          62569:     <doc>ignore dependencies, install anyway</doc>
        !          62570:    </nodeps>
        !          62571:    <register-only>
        !          62572:     <shortopt>r</shortopt>
        !          62573:     <doc>do not install files, only register the package as installed</doc>
        !          62574:    </register-only>
        !          62575:    <soft>
        !          62576:     <shortopt>s</shortopt>
        !          62577:     <doc>soft install, fail silently, or upgrade if already installed</doc>
        !          62578:    </soft>
        !          62579:    <nobuild>
        !          62580:     <shortopt>B</shortopt>
        !          62581:     <doc>don&#039;t build C extensions</doc>
        !          62582:    </nobuild>
        !          62583:    <nocompress>
        !          62584:     <shortopt>Z</shortopt>
        !          62585:     <doc>request uncompressed files when downloading</doc>
        !          62586:    </nocompress>
        !          62587:    <installroot>
        !          62588:     <shortopt>R</shortopt>
        !          62589:     <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT), use packagingroot for RPM</doc>
        !          62590:     <arg>DIR</arg>
        !          62591:    </installroot>
        !          62592:    <packagingroot>
        !          62593:     <shortopt>P</shortopt>
        !          62594:     <doc>root directory used when packaging files, like RPM packaging</doc>
        !          62595:     <arg>DIR</arg>
        !          62596:    </packagingroot>
        !          62597:    <ignore-errors>
        !          62598:     <shortopt></shortopt>
        !          62599:     <doc>force install even if there were errors</doc>
        !          62600:    </ignore-errors>
        !          62601:    <alldeps>
        !          62602:     <shortopt>a</shortopt>
        !          62603:     <doc>install all required and optional dependencies</doc>
        !          62604:    </alldeps>
        !          62605:    <onlyreqdeps>
        !          62606:     <shortopt>o</shortopt>
        !          62607:     <doc>install all required dependencies</doc>
        !          62608:    </onlyreqdeps>
        !          62609:    <offline>
        !          62610:     <shortopt>O</shortopt>
        !          62611:     <doc>do not attempt to download any urls or contact channels</doc>
        !          62612:    </offline>
        !          62613:    <pretend>
        !          62614:     <shortopt>p</shortopt>
        !          62615:     <doc>Only list the packages that would be downloaded</doc>
        !          62616:    </pretend>
        !          62617:   </options>
        !          62618:   <doc>[channel/]&lt;package&gt; ...
        !          62619: Installs one or more PEAR packages.  You can specify a package to
        !          62620: install in four ways:
        !          62621: 
        !          62622: &quot;Package-1.0.tgz&quot; : installs from a local file
        !          62623: 
        !          62624: &quot;http://example.com/Package-1.0.tgz&quot; : installs from
        !          62625: anywhere on the net.
        !          62626: 
        !          62627: &quot;package.xml&quot; : installs the package described in
        !          62628: package.xml.  Useful for testing, or for wrapping a PEAR package in
        !          62629: another package manager such as RPM.
        !          62630: 
        !          62631: &quot;Package[-version/state][.tar]&quot; : queries your default channel&#039;s server
        !          62632: ({config master_server}) and downloads the newest package with
        !          62633: the preferred quality/state ({config preferred_state}).
        !          62634: 
        !          62635: To retrieve Package version 1.1, use &quot;Package-1.1,&quot; to retrieve
        !          62636: Package state beta, use &quot;Package-beta.&quot;  To retrieve an uncompressed
        !          62637: file, append .tar (make sure there is no file by the same name first)
        !          62638: 
        !          62639: To download a package from another channel, prefix with the channel name like
        !          62640: &quot;channel/Package&quot;
        !          62641: 
        !          62642: More than one package may be specified at once.  It is ok to mix these
        !          62643: four ways of specifying packages.
        !          62644: </doc>
        !          62645:  </install>
        !          62646:  <upgrade>
        !          62647:   <summary>Upgrade Package</summary>
        !          62648:   <function>doInstall</function>
        !          62649:   <shortcut>up</shortcut>
        !          62650:   <options>
        !          62651:    <channel>
        !          62652:     <shortopt>c</shortopt>
        !          62653:     <doc>upgrade packages from a specific channel</doc>
        !          62654:     <arg>CHAN</arg>
        !          62655:    </channel>
        !          62656:    <force>
        !          62657:     <shortopt>f</shortopt>
        !          62658:     <doc>overwrite newer installed packages</doc>
        !          62659:    </force>
        !          62660:    <loose>
        !          62661:     <shortopt>l</shortopt>
        !          62662:     <doc>do not check for recommended dependency version</doc>
        !          62663:    </loose>
        !          62664:    <nodeps>
        !          62665:     <shortopt>n</shortopt>
        !          62666:     <doc>ignore dependencies, upgrade anyway</doc>
        !          62667:    </nodeps>
        !          62668:    <register-only>
        !          62669:     <shortopt>r</shortopt>
        !          62670:     <doc>do not install files, only register the package as upgraded</doc>
        !          62671:    </register-only>
        !          62672:    <nobuild>
        !          62673:     <shortopt>B</shortopt>
        !          62674:     <doc>don&#039;t build C extensions</doc>
        !          62675:    </nobuild>
        !          62676:    <nocompress>
        !          62677:     <shortopt>Z</shortopt>
        !          62678:     <doc>request uncompressed files when downloading</doc>
        !          62679:    </nocompress>
        !          62680:    <installroot>
        !          62681:     <shortopt>R</shortopt>
        !          62682:     <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT)</doc>
        !          62683:     <arg>DIR</arg>
        !          62684:    </installroot>
        !          62685:    <ignore-errors>
        !          62686:     <shortopt></shortopt>
        !          62687:     <doc>force install even if there were errors</doc>
        !          62688:    </ignore-errors>
        !          62689:    <alldeps>
        !          62690:     <shortopt>a</shortopt>
        !          62691:     <doc>install all required and optional dependencies</doc>
        !          62692:    </alldeps>
        !          62693:    <onlyreqdeps>
        !          62694:     <shortopt>o</shortopt>
        !          62695:     <doc>install all required dependencies</doc>
        !          62696:    </onlyreqdeps>
        !          62697:    <offline>
        !          62698:     <shortopt>O</shortopt>
        !          62699:     <doc>do not attempt to download any urls or contact channels</doc>
        !          62700:    </offline>
        !          62701:    <pretend>
        !          62702:     <shortopt>p</shortopt>
        !          62703:     <doc>Only list the packages that would be downloaded</doc>
        !          62704:    </pretend>
        !          62705:   </options>
        !          62706:   <doc>&lt;package&gt; ...
        !          62707: Upgrades one or more PEAR packages.  See documentation for the
        !          62708: &quot;install&quot; command for ways to specify a package.
        !          62709: 
        !          62710: When upgrading, your package will be updated if the provided new
        !          62711: package has a higher version number (use the -f option if you need to
        !          62712: upgrade anyway).
        !          62713: 
        !          62714: More than one package may be specified at once.
        !          62715: </doc>
        !          62716:  </upgrade>
        !          62717:  <upgrade-all>
        !          62718:   <summary>Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]</summary>
        !          62719:   <function>doUpgradeAll</function>
        !          62720:   <shortcut>ua</shortcut>
        !          62721:   <options>
        !          62722:    <channel>
        !          62723:     <shortopt>c</shortopt>
        !          62724:     <doc>upgrade packages from a specific channel</doc>
        !          62725:     <arg>CHAN</arg>
        !          62726:    </channel>
        !          62727:    <nodeps>
        !          62728:     <shortopt>n</shortopt>
        !          62729:     <doc>ignore dependencies, upgrade anyway</doc>
        !          62730:    </nodeps>
        !          62731:    <register-only>
        !          62732:     <shortopt>r</shortopt>
        !          62733:     <doc>do not install files, only register the package as upgraded</doc>
        !          62734:    </register-only>
        !          62735:    <nobuild>
        !          62736:     <shortopt>B</shortopt>
        !          62737:     <doc>don&#039;t build C extensions</doc>
        !          62738:    </nobuild>
        !          62739:    <nocompress>
        !          62740:     <shortopt>Z</shortopt>
        !          62741:     <doc>request uncompressed files when downloading</doc>
        !          62742:    </nocompress>
        !          62743:    <installroot>
        !          62744:     <shortopt>R</shortopt>
        !          62745:     <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT), use packagingroot for RPM</doc>
        !          62746:     <arg>DIR</arg>
        !          62747:    </installroot>
        !          62748:    <ignore-errors>
        !          62749:     <shortopt></shortopt>
        !          62750:     <doc>force install even if there were errors</doc>
        !          62751:    </ignore-errors>
        !          62752:    <loose>
        !          62753:     <shortopt></shortopt>
        !          62754:     <doc>do not check for recommended dependency version</doc>
        !          62755:    </loose>
        !          62756:   </options>
        !          62757:   <doc>
        !          62758: WARNING: This function is deprecated in favor of using the upgrade command with no params
        !          62759: 
        !          62760: Upgrades all packages that have a newer release available.  Upgrades are
        !          62761: done only if there is a release available of the state specified in
        !          62762: &quot;preferred_state&quot; (currently {config preferred_state}), or a state considered
        !          62763: more stable.
        !          62764: </doc>
        !          62765:  </upgrade-all>
        !          62766:  <uninstall>
        !          62767:   <summary>Un-install Package</summary>
        !          62768:   <function>doUninstall</function>
        !          62769:   <shortcut>un</shortcut>
        !          62770:   <options>
        !          62771:    <nodeps>
        !          62772:     <shortopt>n</shortopt>
        !          62773:     <doc>ignore dependencies, uninstall anyway</doc>
        !          62774:    </nodeps>
        !          62775:    <register-only>
        !          62776:     <shortopt>r</shortopt>
        !          62777:     <doc>do not remove files, only register the packages as not installed</doc>
        !          62778:    </register-only>
        !          62779:    <installroot>
        !          62780:     <shortopt>R</shortopt>
        !          62781:     <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT)</doc>
        !          62782:     <arg>DIR</arg>
        !          62783:    </installroot>
        !          62784:    <ignore-errors>
        !          62785:     <shortopt></shortopt>
        !          62786:     <doc>force install even if there were errors</doc>
        !          62787:    </ignore-errors>
        !          62788:    <offline>
        !          62789:     <shortopt>O</shortopt>
        !          62790:     <doc>do not attempt to uninstall remotely</doc>
        !          62791:    </offline>
        !          62792:   </options>
        !          62793:   <doc>[channel/]&lt;package&gt; ...
        !          62794: Uninstalls one or more PEAR packages.  More than one package may be
        !          62795: specified at once.  Prefix with channel name to uninstall from a
        !          62796: channel not in your default channel ({config default_channel})
        !          62797: </doc>
        !          62798:  </uninstall>
        !          62799:  <bundle>
        !          62800:   <summary>Unpacks a Pecl Package</summary>
        !          62801:   <function>doBundle</function>
        !          62802:   <shortcut>bun</shortcut>
        !          62803:   <options>
        !          62804:    <destination>
        !          62805:     <shortopt>d</shortopt>
        !          62806:     <doc>Optional destination directory for unpacking (defaults to current path or &quot;ext&quot; if exists)</doc>
        !          62807:     <arg>DIR</arg>
        !          62808:    </destination>
        !          62809:    <force>
        !          62810:     <shortopt>f</shortopt>
        !          62811:     <doc>Force the unpacking even if there were errors in the package</doc>
        !          62812:    </force>
        !          62813:   </options>
        !          62814:   <doc>&lt;package&gt;
        !          62815: Unpacks a Pecl Package into the selected location. It will download the
        !          62816: package if needed.
        !          62817: </doc>
        !          62818:  </bundle>
        !          62819:  <run-scripts>
        !          62820:   <summary>Run Post-Install Scripts bundled with a package</summary>
        !          62821:   <function>doRunScripts</function>
        !          62822:   <shortcut>rs</shortcut>
        !          62823:   <options />
        !          62824:   <doc>&lt;package&gt;
        !          62825: Run post-installation scripts in package &lt;package&gt;, if any exist.
        !          62826: </doc>
        !          62827:  </run-scripts>
        !          62828: </commands><?php
        !          62829: /**
        !          62830:  * PEAR_Command_Mirror (download-all command)
        !          62831:  *
        !          62832:  * PHP versions 4 and 5
        !          62833:  *
        !          62834:  * @category   pear
        !          62835:  * @package    PEAR
        !          62836:  * @author     Alexander Merz <alexmerz@php.net>
        !          62837:  * @copyright  1997-2009 The Authors
        !          62838:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          62839:  * @version    CVS: $Id: Mirror.php 313023 2011-07-06 19:17:11Z dufuz $
        !          62840:  * @link       http://pear.php.net/package/PEAR
        !          62841:  * @since      File available since Release 1.2.0
        !          62842:  */
        !          62843: 
        !          62844: /**
        !          62845:  * base class
        !          62846:  */
        !          62847: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Common.php';
        !          62848: 
        !          62849: /**
        !          62850:  * PEAR commands for providing file mirrors
        !          62851:  *
        !          62852:  * @category   pear
        !          62853:  * @package    PEAR
        !          62854:  * @author     Alexander Merz <alexmerz@php.net>
        !          62855:  * @copyright  1997-2009 The Authors
        !          62856:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          62857:  * @version    Release: 1.9.4
        !          62858:  * @link       http://pear.php.net/package/PEAR
        !          62859:  * @since      Class available since Release 1.2.0
        !          62860:  */
        !          62861: class PEAR_Command_Mirror extends PEAR_Command_Common
        !          62862: {
        !          62863:     var $commands = array(
        !          62864:         'download-all' => array(
        !          62865:             'summary' => 'Downloads each available package from the default channel',
        !          62866:             'function' => 'doDownloadAll',
        !          62867:             'shortcut' => 'da',
        !          62868:             'options' => array(
        !          62869:                 'channel' =>
        !          62870:                     array(
        !          62871:                     'shortopt' => 'c',
        !          62872:                     'doc' => 'specify a channel other than the default channel',
        !          62873:                     'arg' => 'CHAN',
        !          62874:                     ),
        !          62875:                 ),
        !          62876:             'doc' => '
        !          62877: Requests a list of available packages from the default channel ({config default_channel})
        !          62878: and downloads them to current working directory.  Note: only
        !          62879: packages within preferred_state ({config preferred_state}) will be downloaded'
        !          62880:             ),
        !          62881:         );
        !          62882: 
        !          62883:     /**
        !          62884:      * PEAR_Command_Mirror constructor.
        !          62885:      *
        !          62886:      * @access public
        !          62887:      * @param object PEAR_Frontend a reference to an frontend
        !          62888:      * @param object PEAR_Config a reference to the configuration data
        !          62889:      */
        !          62890:     function PEAR_Command_Mirror(&$ui, &$config)
        !          62891:     {
        !          62892:         parent::PEAR_Command_Common($ui, $config);
        !          62893:     }
        !          62894: 
        !          62895:     /**
        !          62896:      * For unit-testing
        !          62897:      */
        !          62898:     function &factory($a)
        !          62899:     {
        !          62900:         $a = &PEAR_Command::factory($a, $this->config);
        !          62901:         return $a;
        !          62902:     }
        !          62903: 
        !          62904:     /**
        !          62905:     * retrieves a list of avaible Packages from master server
        !          62906:     * and downloads them
        !          62907:     *
        !          62908:     * @access public
        !          62909:     * @param string $command the command
        !          62910:     * @param array $options the command options before the command
        !          62911:     * @param array $params the stuff after the command name
        !          62912:     * @return bool true if succesful
        !          62913:     * @throw PEAR_Error
        !          62914:     */
        !          62915:     function doDownloadAll($command, $options, $params)
        !          62916:     {
        !          62917:         $savechannel = $this->config->get('default_channel');
        !          62918:         $reg = &$this->config->getRegistry();
        !          62919:         $channel = isset($options['channel']) ? $options['channel'] :
        !          62920:             $this->config->get('default_channel');
        !          62921:         if (!$reg->channelExists($channel)) {
        !          62922:             $this->config->set('default_channel', $savechannel);
        !          62923:             return $this->raiseError('Channel "' . $channel . '" does not exist');
        !          62924:         }
        !          62925:         $this->config->set('default_channel', $channel);
        !          62926: 
        !          62927:         $this->ui->outputData('Using Channel ' . $this->config->get('default_channel'));
        !          62928:         $chan = $reg->getChannel($channel);
        !          62929:         if (PEAR::isError($chan)) {
        !          62930:             return $this->raiseError($chan);
        !          62931:         }
        !          62932: 
        !          62933:         if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
        !          62934:               $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
        !          62935:             $rest = &$this->config->getREST('1.0', array());
        !          62936:             $remoteInfo = array_flip($rest->listPackages($base, $channel));
        !          62937:         }
        !          62938: 
        !          62939:         if (PEAR::isError($remoteInfo)) {
        !          62940:             return $remoteInfo;
        !          62941:         }
        !          62942: 
        !          62943:         $cmd = &$this->factory("download");
        !          62944:         if (PEAR::isError($cmd)) {
        !          62945:             return $cmd;
        !          62946:         }
        !          62947: 
        !          62948:         $this->ui->outputData('Using Preferred State of ' .
        !          62949:             $this->config->get('preferred_state'));
        !          62950:         $this->ui->outputData('Gathering release information, please wait...');
        !          62951: 
        !          62952:         /**
        !          62953:          * Error handling not necessary, because already done by
        !          62954:          * the download command
        !          62955:          */
        !          62956:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          62957:         $err = $cmd->run('download', array('downloadonly' => true), array_keys($remoteInfo));
        !          62958:         PEAR::staticPopErrorHandling();
        !          62959:         $this->config->set('default_channel', $savechannel);
        !          62960:         if (PEAR::isError($err)) {
        !          62961:             $this->ui->outputData($err->getMessage());
        !          62962:         }
        !          62963: 
        !          62964:         return true;
        !          62965:     }
        !          62966: }<commands version="1.0">
        !          62967:  <download-all>
        !          62968:   <summary>Downloads each available package from the default channel</summary>
        !          62969:   <function>doDownloadAll</function>
        !          62970:   <shortcut>da</shortcut>
        !          62971:   <options>
        !          62972:    <channel>
        !          62973:     <shortopt>c</shortopt>
        !          62974:     <doc>specify a channel other than the default channel</doc>
        !          62975:     <arg>CHAN</arg>
        !          62976:    </channel>
        !          62977:   </options>
        !          62978:   <doc>
        !          62979: Requests a list of available packages from the default channel ({config default_channel})
        !          62980: and downloads them to current working directory.  Note: only
        !          62981: packages within preferred_state ({config preferred_state}) will be downloaded</doc>
        !          62982:  </download-all>
        !          62983: </commands><?php
        !          62984: /**
        !          62985:  * PEAR_Command_Package (package, package-validate, cvsdiff, cvstag, package-dependencies,
        !          62986:  * sign, makerpm, convert commands)
        !          62987:  *
        !          62988:  * PHP versions 4 and 5
        !          62989:  *
        !          62990:  * @category   pear
        !          62991:  * @package    PEAR
        !          62992:  * @author     Stig Bakken <ssb@php.net>
        !          62993:  * @author     Martin Jansen <mj@php.net>
        !          62994:  * @author     Greg Beaver <cellog@php.net>
        !          62995:  * @copyright  1997-2009 The Authors
        !          62996:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          62997:  * @version    CVS: $Id: Package.php 313024 2011-07-06 19:51:24Z dufuz $
        !          62998:  * @link       http://pear.php.net/package/PEAR
        !          62999:  * @since      File available since Release 0.1
        !          63000:  */
        !          63001: 
        !          63002: /**
        !          63003:  * base class
        !          63004:  */
        !          63005: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Common.php';
        !          63006: 
        !          63007: /**
        !          63008:  * PEAR commands for login/logout
        !          63009:  *
        !          63010:  * @category   pear
        !          63011:  * @package    PEAR
        !          63012:  * @author     Stig Bakken <ssb@php.net>
        !          63013:  * @author     Martin Jansen <mj@php.net>
        !          63014:  * @author     Greg Beaver <cellog@php.net>
        !          63015:  * @copyright  1997-2009 The Authors
        !          63016:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          63017:  * @version    Release: 1.10.0beta1
        !          63018:  * @link       http://pear.php.net/package/PEAR
        !          63019:  * @since      Class available since Release 0.1
        !          63020:  */
        !          63021: 
        !          63022: class PEAR_Command_Package extends PEAR_Command_Common
        !          63023: {
        !          63024:     var $commands = array(
        !          63025:         'package' => array(
        !          63026:             'summary' => 'Build Package',
        !          63027:             'function' => 'doPackage',
        !          63028:             'shortcut' => 'p',
        !          63029:             'options' => array(
        !          63030:                 'nocompress' => array(
        !          63031:                     'shortopt' => 'Z',
        !          63032:                     'doc' => 'Do not gzip the package file'
        !          63033:                     ),
        !          63034:                 'showname' => array(
        !          63035:                     'shortopt' => 'n',
        !          63036:                     'doc' => 'Print the name of the packaged file.',
        !          63037:                     ),
        !          63038:                 ),
        !          63039:             'doc' => '[descfile] [descfile2]
        !          63040: Creates a PEAR package from its description file (usually called
        !          63041: package.xml).  If a second packagefile is passed in, then
        !          63042: the packager will check to make sure that one is a package.xml
        !          63043: version 1.0, and the other is a package.xml version 2.0.  The
        !          63044: package.xml version 1.0 will be saved as "package.xml" in the archive,
        !          63045: and the other as "package2.xml" in the archive"
        !          63046: '
        !          63047:             ),
        !          63048:         'package-validate' => array(
        !          63049:             'summary' => 'Validate Package Consistency',
        !          63050:             'function' => 'doPackageValidate',
        !          63051:             'shortcut' => 'pv',
        !          63052:             'options' => array(),
        !          63053:             'doc' => '
        !          63054: ',
        !          63055:             ),
        !          63056:         'cvsdiff' => array(
        !          63057:             'summary' => 'Run a "cvs diff" for all files in a package',
        !          63058:             'function' => 'doCvsDiff',
        !          63059:             'shortcut' => 'cd',
        !          63060:             'options' => array(
        !          63061:                 'quiet' => array(
        !          63062:                     'shortopt' => 'q',
        !          63063:                     'doc' => 'Be quiet',
        !          63064:                     ),
        !          63065:                 'reallyquiet' => array(
        !          63066:                     'shortopt' => 'Q',
        !          63067:                     'doc' => 'Be really quiet',
        !          63068:                     ),
        !          63069:                 'date' => array(
        !          63070:                     'shortopt' => 'D',
        !          63071:                     'doc' => 'Diff against revision of DATE',
        !          63072:                     'arg' => 'DATE',
        !          63073:                     ),
        !          63074:                 'release' => array(
        !          63075:                     'shortopt' => 'R',
        !          63076:                     'doc' => 'Diff against tag for package release REL',
        !          63077:                     'arg' => 'REL',
        !          63078:                     ),
        !          63079:                 'revision' => array(
        !          63080:                     'shortopt' => 'r',
        !          63081:                     'doc' => 'Diff against revision REV',
        !          63082:                     'arg' => 'REV',
        !          63083:                     ),
        !          63084:                 'context' => array(
        !          63085:                     'shortopt' => 'c',
        !          63086:                     'doc' => 'Generate context diff',
        !          63087:                     ),
        !          63088:                 'unified' => array(
        !          63089:                     'shortopt' => 'u',
        !          63090:                     'doc' => 'Generate unified diff',
        !          63091:                     ),
        !          63092:                 'ignore-case' => array(
        !          63093:                     'shortopt' => 'i',
        !          63094:                     'doc' => 'Ignore case, consider upper- and lower-case letters equivalent',
        !          63095:                     ),
        !          63096:                 'ignore-whitespace' => array(
        !          63097:                     'shortopt' => 'b',
        !          63098:                     'doc' => 'Ignore changes in amount of white space',
        !          63099:                     ),
        !          63100:                 'ignore-blank-lines' => array(
        !          63101:                     'shortopt' => 'B',
        !          63102:                     'doc' => 'Ignore changes that insert or delete blank lines',
        !          63103:                     ),
        !          63104:                 'brief' => array(
        !          63105:                     'doc' => 'Report only whether the files differ, no details',
        !          63106:                     ),
        !          63107:                 'dry-run' => array(
        !          63108:                     'shortopt' => 'n',
        !          63109:                     'doc' => 'Don\'t do anything, just pretend',
        !          63110:                     ),
        !          63111:                 ),
        !          63112:             'doc' => '<package.xml>
        !          63113: Compares all the files in a package.  Without any options, this
        !          63114: command will compare the current code with the last checked-in code.
        !          63115: Using the -r or -R option you may compare the current code with that
        !          63116: of a specific release.
        !          63117: ',
        !          63118:             ),
        !          63119:          'svntag' => array(
        !          63120:              'summary' => 'Set SVN Release Tag',
        !          63121:              'function' => 'doSvnTag',
        !          63122:              'shortcut' => 'sv',
        !          63123:              'options' => array(
        !          63124:                  'quiet' => array(
        !          63125:                      'shortopt' => 'q',
        !          63126:                      'doc' => 'Be quiet',
        !          63127:                      ),
        !          63128:                  'slide' => array(
        !          63129:                      'shortopt' => 'F',
        !          63130:                      'doc' => 'Move (slide) tag if it exists',
        !          63131:                      ),
        !          63132:                  'delete' => array(
        !          63133:                      'shortopt' => 'd',
        !          63134:                      'doc' => 'Remove tag',
        !          63135:                      ),
        !          63136:                  'dry-run' => array(
        !          63137:                      'shortopt' => 'n',
        !          63138:                      'doc' => 'Don\'t do anything, just pretend',
        !          63139:                      ),
        !          63140:                  ),
        !          63141:              'doc' => '<package.xml> [files...]
        !          63142:  Sets a SVN tag on all files in a package.  Use this command after you have
        !          63143:  packaged a distribution tarball with the "package" command to tag what
        !          63144:  revisions of what files were in that release.  If need to fix something
        !          63145:  after running svntag once, but before the tarball is released to the public,
        !          63146:  use the "slide" option to move the release tag.
        !          63147: 
        !          63148:  to include files (such as a second package.xml, or tests not included in the
        !          63149:  release), pass them as additional parameters.
        !          63150:  ',
        !          63151:              ),
        !          63152:         'cvstag' => array(
        !          63153:             'summary' => 'Set CVS Release Tag',
        !          63154:             'function' => 'doCvsTag',
        !          63155:             'shortcut' => 'ct',
        !          63156:             'options' => array(
        !          63157:                 'quiet' => array(
        !          63158:                     'shortopt' => 'q',
        !          63159:                     'doc' => 'Be quiet',
        !          63160:                     ),
        !          63161:                 'reallyquiet' => array(
        !          63162:                     'shortopt' => 'Q',
        !          63163:                     'doc' => 'Be really quiet',
        !          63164:                     ),
        !          63165:                 'slide' => array(
        !          63166:                     'shortopt' => 'F',
        !          63167:                     'doc' => 'Move (slide) tag if it exists',
        !          63168:                     ),
        !          63169:                 'delete' => array(
        !          63170:                     'shortopt' => 'd',
        !          63171:                     'doc' => 'Remove tag',
        !          63172:                     ),
        !          63173:                 'dry-run' => array(
        !          63174:                     'shortopt' => 'n',
        !          63175:                     'doc' => 'Don\'t do anything, just pretend',
        !          63176:                     ),
        !          63177:                 ),
        !          63178:             'doc' => '<package.xml> [files...]
        !          63179: Sets a CVS tag on all files in a package.  Use this command after you have
        !          63180: packaged a distribution tarball with the "package" command to tag what
        !          63181: revisions of what files were in that release.  If need to fix something
        !          63182: after running cvstag once, but before the tarball is released to the public,
        !          63183: use the "slide" option to move the release tag.
        !          63184: 
        !          63185: to include files (such as a second package.xml, or tests not included in the
        !          63186: release), pass them as additional parameters.
        !          63187: ',
        !          63188:             ),
        !          63189:         'package-dependencies' => array(
        !          63190:             'summary' => 'Show package dependencies',
        !          63191:             'function' => 'doPackageDependencies',
        !          63192:             'shortcut' => 'pd',
        !          63193:             'options' => array(),
        !          63194:             'doc' => '<package-file> or <package.xml> or <install-package-name>
        !          63195: List all dependencies the package has.
        !          63196: Can take a tgz / tar file, package.xml or a package name of an installed package.'
        !          63197:             ),
        !          63198:         'sign' => array(
        !          63199:             'summary' => 'Sign a package distribution file',
        !          63200:             'function' => 'doSign',
        !          63201:             'shortcut' => 'si',
        !          63202:             'options' => array(
        !          63203:                 'verbose' => array(
        !          63204:                     'shortopt' => 'v',
        !          63205:                     'doc' => 'Display GnuPG output',
        !          63206:                     ),
        !          63207:             ),
        !          63208:             'doc' => '<package-file>
        !          63209: Signs a package distribution (.tar or .tgz) file with GnuPG.',
        !          63210:             ),
        !          63211:         'makerpm' => array(
        !          63212:             'summary' => 'Builds an RPM spec file from a PEAR package',
        !          63213:             'function' => 'doMakeRPM',
        !          63214:             'shortcut' => 'rpm',
        !          63215:             'options' => array(
        !          63216:                 'spec-template' => array(
        !          63217:                     'shortopt' => 't',
        !          63218:                     'arg' => 'FILE',
        !          63219:                     'doc' => 'Use FILE as RPM spec file template'
        !          63220:                     ),
        !          63221:                 'rpm-pkgname' => array(
        !          63222:                     'shortopt' => 'p',
        !          63223:                     'arg' => 'FORMAT',
        !          63224:                     'doc' => 'Use FORMAT as format string for RPM package name, %s is replaced
        !          63225: by the PEAR package name, defaults to "PEAR::%s".',
        !          63226:                     ),
        !          63227:                 ),
        !          63228:             'doc' => '<package-file>
        !          63229: 
        !          63230: Creates an RPM .spec file for wrapping a PEAR package inside an RPM
        !          63231: package.  Intended to be used from the SPECS directory, with the PEAR
        !          63232: package tarball in the SOURCES directory:
        !          63233: 
        !          63234: $ pear makerpm ../SOURCES/Net_Socket-1.0.tgz
        !          63235: Wrote RPM spec file PEAR::Net_Geo-1.0.spec
        !          63236: $ rpm -bb PEAR::Net_Socket-1.0.spec
        !          63237: ...
        !          63238: Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
        !          63239: ',
        !          63240:             ),
        !          63241:         'convert' => array(
        !          63242:             'summary' => 'Convert a package.xml 1.0 to package.xml 2.0 format',
        !          63243:             'function' => 'doConvert',
        !          63244:             'shortcut' => 'c2',
        !          63245:             'options' => array(
        !          63246:                 'flat' => array(
        !          63247:                     'shortopt' => 'f',
        !          63248:                     'doc' => 'do not beautify the filelist.',
        !          63249:                     ),
        !          63250:                 ),
        !          63251:             'doc' => '[descfile] [descfile2]
        !          63252: Converts a package.xml in 1.0 format into a package.xml
        !          63253: in 2.0 format.  The new file will be named package2.xml by default,
        !          63254: and package.xml will be used as the old file by default.
        !          63255: This is not the most intelligent conversion, and should only be
        !          63256: used for automated conversion or learning the format.
        !          63257: '
        !          63258:             ),
        !          63259:         );
        !          63260: 
        !          63261:     var $output;
        !          63262: 
        !          63263:     /**
        !          63264:      * PEAR_Command_Package constructor.
        !          63265:      *
        !          63266:      * @access public
        !          63267:      */
        !          63268:     function PEAR_Command_Package(&$ui, &$config)
        !          63269:     {
        !          63270:         parent::PEAR_Command_Common($ui, $config);
        !          63271:     }
        !          63272: 
        !          63273:     function _displayValidationResults($err, $warn, $strict = false)
        !          63274:     {
        !          63275:         foreach ($err as $e) {
        !          63276:             $this->output .= "Error: $e\n";
        !          63277:         }
        !          63278:         foreach ($warn as $w) {
        !          63279:             $this->output .= "Warning: $w\n";
        !          63280:         }
        !          63281:         $this->output .= sprintf('Validation: %d error(s), %d warning(s)'."\n",
        !          63282:                                        sizeof($err), sizeof($warn));
        !          63283:         if ($strict && count($err) > 0) {
        !          63284:             $this->output .= "Fix these errors and try again.";
        !          63285:             return false;
        !          63286:         }
        !          63287:         return true;
        !          63288:     }
        !          63289: 
        !          63290:     function &getPackager()
        !          63291:     {
        !          63292:         if (!class_exists('PEAR_Packager')) {
        !          63293:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Packager.php';
        !          63294:         }
        !          63295:         $a = &new PEAR_Packager;
        !          63296:         return $a;
        !          63297:     }
        !          63298: 
        !          63299:     function &getPackageFile($config, $debug = false)
        !          63300:     {
        !          63301:         if (!class_exists('PEAR_Common')) {
        !          63302:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
        !          63303:         }
        !          63304:         if (!class_exists('PEAR_PackageFile')) {
        !          63305:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile.php';
        !          63306:         }
        !          63307:         $a = &new PEAR_PackageFile($config, $debug);
        !          63308:         $common = new PEAR_Common;
        !          63309:         $common->ui = $this->ui;
        !          63310:         $a->setLogger($common);
        !          63311:         return $a;
        !          63312:     }
        !          63313: 
        !          63314:     function doPackage($command, $options, $params)
        !          63315:     {
        !          63316:         $this->output = '';
        !          63317:         $pkginfofile = isset($params[0]) ? $params[0] : 'package.xml';
        !          63318:         $pkg2 = isset($params[1]) ? $params[1] : null;
        !          63319:         if (!$pkg2 && !isset($params[0]) && file_exists('package2.xml')) {
        !          63320:             $pkg2 = 'package2.xml';
        !          63321:         }
        !          63322: 
        !          63323:         $packager = &$this->getPackager();
        !          63324:         $compress = empty($options['nocompress']) ? true : false;
        !          63325:         $result   = $packager->package($pkginfofile, $compress, $pkg2);
        !          63326:         if (PEAR::isError($result)) {
        !          63327:             return $this->raiseError($result);
        !          63328:         }
        !          63329: 
        !          63330:         // Don't want output, only the package file name just created
        !          63331:         if (isset($options['showname'])) {
        !          63332:             $this->output = $result;
        !          63333:         }
        !          63334: 
        !          63335:         if ($this->output) {
        !          63336:             $this->ui->outputData($this->output, $command);
        !          63337:         }
        !          63338: 
        !          63339:         return true;
        !          63340:     }
        !          63341: 
        !          63342:     function doPackageValidate($command, $options, $params)
        !          63343:     {
        !          63344:         $this->output = '';
        !          63345:         if (count($params) < 1) {
        !          63346:             $params[0] = 'package.xml';
        !          63347:         }
        !          63348: 
        !          63349:         $obj = &$this->getPackageFile($this->config, $this->_debug);
        !          63350:         $obj->rawReturn();
        !          63351:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          63352:         $info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL);
        !          63353:         if (PEAR::isError($info)) {
        !          63354:             $info = $obj->fromPackageFile($params[0], PEAR_VALIDATE_NORMAL);
        !          63355:         } else {
        !          63356:             $archive = $info->getArchiveFile();
        !          63357:             $tar = &new Archive_Tar($archive);
        !          63358:             $tar->extract(dirname($info->getPackageFile()));
        !          63359:             $info->setPackageFile(dirname($info->getPackageFile()) . DIRECTORY_SEPARATOR .
        !          63360:                 $info->getPackage() . '-' . $info->getVersion() . DIRECTORY_SEPARATOR .
        !          63361:                 basename($info->getPackageFile()));
        !          63362:         }
        !          63363: 
        !          63364:         PEAR::staticPopErrorHandling();
        !          63365:         if (PEAR::isError($info)) {
        !          63366:             return $this->raiseError($info);
        !          63367:         }
        !          63368: 
        !          63369:         $valid = false;
        !          63370:         if ($info->getPackagexmlVersion() == '2.0') {
        !          63371:             if ($valid = $info->validate(PEAR_VALIDATE_NORMAL)) {
        !          63372:                 $info->flattenFileList();
        !          63373:                 $valid = $info->validate(PEAR_VALIDATE_PACKAGING);
        !          63374:             }
        !          63375:         } else {
        !          63376:             $valid = $info->validate(PEAR_VALIDATE_PACKAGING);
        !          63377:         }
        !          63378: 
        !          63379:         $err = $warn = array();
        !          63380:         if ($errors = $info->getValidationWarnings()) {
        !          63381:             foreach ($errors as $error) {
        !          63382:                 if ($error['level'] == 'warning') {
        !          63383:                     $warn[] = $error['message'];
        !          63384:                 } else {
        !          63385:                     $err[] = $error['message'];
        !          63386:                 }
        !          63387:             }
        !          63388:         }
        !          63389: 
        !          63390:         $this->_displayValidationResults($err, $warn);
        !          63391:         $this->ui->outputData($this->output, $command);
        !          63392:         return true;
        !          63393:     }
        !          63394: 
        !          63395:     function doSvnTag($command, $options, $params)
        !          63396:     {
        !          63397:         $this->output = '';
        !          63398:         $_cmd = $command;
        !          63399:         if (count($params) < 1) {
        !          63400:             $help = $this->getHelp($command);
        !          63401:             return $this->raiseError("$command: missing parameter: $help[0]");
        !          63402:         }
        !          63403: 
        !          63404:         $packageFile = realpath($params[0]);
        !          63405:         $dir = dirname($packageFile);
        !          63406:         $dir = substr($dir, strrpos($dir, DIRECTORY_SEPARATOR) + 1);
        !          63407:         $obj  = &$this->getPackageFile($this->config, $this->_debug);
        !          63408:         $info = $obj->fromAnyFile($packageFile, PEAR_VALIDATE_NORMAL);
        !          63409:         if (PEAR::isError($info)) {
        !          63410:             return $this->raiseError($info);
        !          63411:         }
        !          63412: 
        !          63413:         $err = $warn = array();
        !          63414:         if (!$info->validate()) {
        !          63415:             foreach ($info->getValidationWarnings() as $error) {
        !          63416:                 if ($error['level'] == 'warning') {
        !          63417:                     $warn[] = $error['message'];
        !          63418:                 } else {
        !          63419:                     $err[] = $error['message'];
        !          63420:                 }
        !          63421:             }
        !          63422:         }
        !          63423: 
        !          63424:         if (!$this->_displayValidationResults($err, $warn, true)) {
        !          63425:             $this->ui->outputData($this->output, $command);
        !          63426:             return $this->raiseError('SVN tag failed');
        !          63427:         }
        !          63428: 
        !          63429:         $version    = $info->getVersion();
        !          63430:         $package    = $info->getName();
        !          63431:         $svntag     = "$package-$version";
        !          63432: 
        !          63433:         if (isset($options['delete'])) {
        !          63434:             return $this->_svnRemoveTag($version, $package, $svntag, $packageFile, $options);
        !          63435:         }
        !          63436: 
        !          63437:         $path = $this->_svnFindPath($packageFile);
        !          63438: 
        !          63439:         // Check if there are any modified files
        !          63440:         $fp = popen('svn st --xml ' . dirname($packageFile), "r");
        !          63441:         $out = '';
        !          63442:         while ($line = fgets($fp, 1024)) {
        !          63443:             $out .= rtrim($line)."\n";
        !          63444:         }
        !          63445:         pclose($fp);
        !          63446: 
        !          63447:         if (!isset($options['quiet']) && strpos($out, 'item="modified"')) {
        !          63448:             $params = array(array(
        !          63449:                 'name' => 'modified',
        !          63450:                 'type' => 'yesno',
        !          63451:                 'default' => 'no',
        !          63452:                 'prompt' => 'You have files in your SVN checkout (' . $path['from']  . ') that have been modified but not commited, do you still want to tag ' . $version . '?',
        !          63453:             ));
        !          63454:             $answers = $this->ui->confirmDialog($params);
        !          63455: 
        !          63456:             if (!in_array($answers['modified'], array('y', 'yes', 'on', '1'))) {
        !          63457:                 return true;
        !          63458:             }
        !          63459:         }
        !          63460: 
        !          63461:         if (isset($options['slide'])) {
        !          63462:             $this->_svnRemoveTag($version, $package, $svntag, $packageFile, $options);
        !          63463:         }
        !          63464: 
        !          63465:         // Check if tag already exists
        !          63466:         $releaseTag = $path['local']['base'] . 'tags' . DIRECTORY_SEPARATOR . $svntag;
        !          63467:         $existsCommand = 'svn ls ' . $path['base'] . 'tags/';
        !          63468: 
        !          63469:         $fp = popen($existsCommand, "r");
        !          63470:         $out = '';
        !          63471:         while ($line = fgets($fp, 1024)) {
        !          63472:             $out .= rtrim($line)."\n";
        !          63473:         }
        !          63474:         pclose($fp);
        !          63475: 
        !          63476:         if (in_array($svntag . DIRECTORY_SEPARATOR, explode("\n", $out))) {
        !          63477:             $this->ui->outputData($this->output, $command);
        !          63478:             return $this->raiseError('SVN tag ' . $svntag . ' for ' . $package . ' already exists.');
        !          63479:         } elseif (file_exists($path['local']['base'] . 'tags') === false) {
        !          63480:             return $this->raiseError('Can not locate the tags directory at ' . $path['local']['base'] . 'tags');
        !          63481:         } elseif (is_writeable($path['local']['base'] . 'tags') === false) {
        !          63482:             return $this->raiseError('Can not write to the tag directory at ' . $path['local']['base'] . 'tags');
        !          63483:         } else {
        !          63484:             $makeCommand = 'svn mkdir ' . $releaseTag;
        !          63485:             $this->output .= "+ $makeCommand\n";
        !          63486:             if (empty($options['dry-run'])) {
        !          63487:                 // We need to create the tag dir.
        !          63488:                 $fp = popen($makeCommand, "r");
        !          63489:                 $out = '';
        !          63490:                 while ($line = fgets($fp, 1024)) {
        !          63491:                     $out .= rtrim($line)."\n";
        !          63492:                 }
        !          63493:                 pclose($fp);
        !          63494:                 $this->output .= "$out\n";
        !          63495:             }
        !          63496:         }
        !          63497: 
        !          63498:         $command = 'svn';
        !          63499:         if (isset($options['quiet'])) {
        !          63500:             $command .= ' -q';
        !          63501:         }
        !          63502: 
        !          63503:         $command .= ' copy --parents ';
        !          63504: 
        !          63505:         $dir   = dirname($packageFile);
        !          63506:         $dir   = substr($dir, strrpos($dir, DIRECTORY_SEPARATOR) + 1);
        !          63507:         $files = array_keys($info->getFilelist());
        !          63508:         if (!in_array(basename($packageFile), $files)) {
        !          63509:             $files[] = basename($packageFile);
        !          63510:         }
        !          63511: 
        !          63512:         array_shift($params);
        !          63513:         if (count($params)) {
        !          63514:             // add in additional files to be tagged (package files and such)
        !          63515:             $files = array_merge($files, $params);
        !          63516:         }
        !          63517: 
        !          63518:         $commands = array();
        !          63519:         foreach ($files as $file) {
        !          63520:             if (!file_exists($file)) {
        !          63521:                 $file = $dir . DIRECTORY_SEPARATOR . $file;
        !          63522:             }
        !          63523:             $commands[] = $command . ' ' . escapeshellarg($file) . ' ' .
        !          63524:                           escapeshellarg($releaseTag . DIRECTORY_SEPARATOR . $file);
        !          63525:         }
        !          63526: 
        !          63527:         $this->output .= implode("\n", $commands) . "\n";
        !          63528:         if (empty($options['dry-run'])) {
        !          63529:             foreach ($commands as $command) {
        !          63530:                 $fp = popen($command, "r");
        !          63531:                 while ($line = fgets($fp, 1024)) {
        !          63532:                     $this->output .= rtrim($line)."\n";
        !          63533:                 }
        !          63534:                 pclose($fp);
        !          63535:             }
        !          63536:         }
        !          63537: 
        !          63538:         $command = 'svn ci -m "Tagging the ' . $version  . ' release" ' . $releaseTag . "\n";
        !          63539:         $this->output .= "+ $command\n";
        !          63540:         if (empty($options['dry-run'])) {
        !          63541:             $fp = popen($command, "r");
        !          63542:             while ($line = fgets($fp, 1024)) {
        !          63543:                 $this->output .= rtrim($line)."\n";
        !          63544:             }
        !          63545:             pclose($fp);
        !          63546:         }
        !          63547: 
        !          63548:         $this->ui->outputData($this->output, $_cmd);
        !          63549:         return true;
        !          63550:     }
        !          63551: 
        !          63552:     function _svnFindPath($file)
        !          63553:     {
        !          63554:         $xml = '';
        !          63555:         $command = "svn info --xml $file";
        !          63556:         $fp = popen($command, "r");
        !          63557:         while ($line = fgets($fp, 1024)) {
        !          63558:             $xml .= rtrim($line)."\n";
        !          63559:         }
        !          63560:         pclose($fp);
        !          63561:         $url_tag = strpos($xml, '<url>');
        !          63562:         $url = substr($xml, $url_tag + 5, strpos($xml, '</url>', $url_tag + 5) - ($url_tag + 5));
        !          63563: 
        !          63564:         $path = array();
        !          63565:         $path['from'] = substr($url, 0, strrpos($url, '/'));
        !          63566:         $path['base'] = substr($path['from'], 0, strrpos($path['from'], '/') + 1);
        !          63567: 
        !          63568:         // Figure out the local paths - see http://pear.php.net/bugs/17463
        !          63569:         $pos = strpos($file, DIRECTORY_SEPARATOR . 'trunk' . DIRECTORY_SEPARATOR);
        !          63570:         if ($pos === false) {
        !          63571:             $pos = strpos($file, DIRECTORY_SEPARATOR . 'branches' . DIRECTORY_SEPARATOR);
        !          63572:         }
        !          63573:         $path['local']['base'] = substr($file, 0, $pos + 1);
        !          63574: 
        !          63575:         return $path;
        !          63576:     }
        !          63577: 
        !          63578:     function _svnRemoveTag($version, $package, $tag, $packageFile, $options)
        !          63579:     {
        !          63580:         $command = 'svn';
        !          63581: 
        !          63582:         if (isset($options['quiet'])) {
        !          63583:             $command .= ' -q';
        !          63584:         }
        !          63585: 
        !          63586:         $command .= ' remove';
        !          63587:         $command .= ' -m "Removing tag for the ' . $version  . ' release."';
        !          63588: 
        !          63589:         $path = $this->_svnFindPath($packageFile);
        !          63590:         $command .= ' ' . $path['base'] . 'tags/' . $tag;
        !          63591: 
        !          63592: 
        !          63593:         if ($this->config->get('verbose') > 1) {
        !          63594:             $this->output .= "+ $command\n";
        !          63595:         }
        !          63596: 
        !          63597:         $this->output .= "+ $command\n";
        !          63598:         if (empty($options['dry-run'])) {
        !          63599:             $fp = popen($command, "r");
        !          63600:             while ($line = fgets($fp, 1024)) {
        !          63601:                 $this->output .= rtrim($line)."\n";
        !          63602:             }
        !          63603:             pclose($fp);
        !          63604:         }
        !          63605: 
        !          63606:         $this->ui->outputData($this->output, $command);
        !          63607:         return true;
        !          63608:     }
        !          63609: 
        !          63610:     function doCvsTag($command, $options, $params)
        !          63611:     {
        !          63612:         $this->output = '';
        !          63613:         $_cmd = $command;
        !          63614:         if (count($params) < 1) {
        !          63615:             $help = $this->getHelp($command);
        !          63616:             return $this->raiseError("$command: missing parameter: $help[0]");
        !          63617:         }
        !          63618: 
        !          63619:         $packageFile = realpath($params[0]);
        !          63620:         $obj  = &$this->getPackageFile($this->config, $this->_debug);
        !          63621:         $info = $obj->fromAnyFile($packageFile, PEAR_VALIDATE_NORMAL);
        !          63622:         if (PEAR::isError($info)) {
        !          63623:             return $this->raiseError($info);
        !          63624:         }
        !          63625: 
        !          63626:         $err = $warn = array();
        !          63627:         if (!$info->validate()) {
        !          63628:             foreach ($info->getValidationWarnings() as $error) {
        !          63629:                 if ($error['level'] == 'warning') {
        !          63630:                     $warn[] = $error['message'];
        !          63631:                 } else {
        !          63632:                     $err[] = $error['message'];
        !          63633:                 }
        !          63634:             }
        !          63635:         }
        !          63636: 
        !          63637:         if (!$this->_displayValidationResults($err, $warn, true)) {
        !          63638:             $this->ui->outputData($this->output, $command);
        !          63639:             return $this->raiseError('CVS tag failed');
        !          63640:         }
        !          63641: 
        !          63642:         $version    = $info->getVersion();
        !          63643:         $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $version);
        !          63644:         $cvstag     = "RELEASE_$cvsversion";
        !          63645:         $files      = array_keys($info->getFilelist());
        !          63646:         $command = 'cvs';
        !          63647:         if (isset($options['quiet'])) {
        !          63648:             $command .= ' -q';
        !          63649:         }
        !          63650: 
        !          63651:         if (isset($options['reallyquiet'])) {
        !          63652:             $command .= ' -Q';
        !          63653:         }
        !          63654: 
        !          63655:         $command .= ' tag';
        !          63656:         if (isset($options['slide'])) {
        !          63657:             $command .= ' -F';
        !          63658:         }
        !          63659: 
        !          63660:         if (isset($options['delete'])) {
        !          63661:             $command .= ' -d';
        !          63662:         }
        !          63663: 
        !          63664:         $command .= ' ' . $cvstag . ' ' . escapeshellarg($params[0]);
        !          63665:         array_shift($params);
        !          63666:         if (count($params)) {
        !          63667:             // add in additional files to be tagged
        !          63668:             $files = array_merge($files, $params);
        !          63669:         }
        !          63670: 
        !          63671:         $dir = dirname($packageFile);
        !          63672:         $dir = substr($dir, strrpos($dir, '/') + 1);
        !          63673:         foreach ($files as $file) {
        !          63674:             if (!file_exists($file)) {
        !          63675:                 $file = $dir . DIRECTORY_SEPARATOR . $file;
        !          63676:             }
        !          63677:             $command .= ' ' . escapeshellarg($file);
        !          63678:         }
        !          63679: 
        !          63680:         if ($this->config->get('verbose') > 1) {
        !          63681:             $this->output .= "+ $command\n";
        !          63682:         }
        !          63683: 
        !          63684:         $this->output .= "+ $command\n";
        !          63685:         if (empty($options['dry-run'])) {
        !          63686:             $fp = popen($command, "r");
        !          63687:             while ($line = fgets($fp, 1024)) {
        !          63688:                 $this->output .= rtrim($line)."\n";
        !          63689:             }
        !          63690:             pclose($fp);
        !          63691:         }
        !          63692: 
        !          63693:         $this->ui->outputData($this->output, $_cmd);
        !          63694:         return true;
        !          63695:     }
        !          63696: 
        !          63697:     function doCvsDiff($command, $options, $params)
        !          63698:     {
        !          63699:         $this->output = '';
        !          63700:         if (sizeof($params) < 1) {
        !          63701:             $help = $this->getHelp($command);
        !          63702:             return $this->raiseError("$command: missing parameter: $help[0]");
        !          63703:         }
        !          63704: 
        !          63705:         $file = realpath($params[0]);
        !          63706:         $obj  = &$this->getPackageFile($this->config, $this->_debug);
        !          63707:         $info = $obj->fromAnyFile($file, PEAR_VALIDATE_NORMAL);
        !          63708:         if (PEAR::isError($info)) {
        !          63709:             return $this->raiseError($info);
        !          63710:         }
        !          63711: 
        !          63712:         $err = $warn = array();
        !          63713:         if (!$info->validate()) {
        !          63714:             foreach ($info->getValidationWarnings() as $error) {
        !          63715:                 if ($error['level'] == 'warning') {
        !          63716:                     $warn[] = $error['message'];
        !          63717:                 } else {
        !          63718:                     $err[] = $error['message'];
        !          63719:                 }
        !          63720:             }
        !          63721:         }
        !          63722: 
        !          63723:         if (!$this->_displayValidationResults($err, $warn, true)) {
        !          63724:             $this->ui->outputData($this->output, $command);
        !          63725:             return $this->raiseError('CVS diff failed');
        !          63726:         }
        !          63727: 
        !          63728:         $info1 = $info->getFilelist();
        !          63729:         $files = $info1;
        !          63730:         $cmd = "cvs";
        !          63731:         if (isset($options['quiet'])) {
        !          63732:             $cmd .= ' -q';
        !          63733:             unset($options['quiet']);
        !          63734:         }
        !          63735: 
        !          63736:         if (isset($options['reallyquiet'])) {
        !          63737:             $cmd .= ' -Q';
        !          63738:             unset($options['reallyquiet']);
        !          63739:         }
        !          63740: 
        !          63741:         if (isset($options['release'])) {
        !          63742:             $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $options['release']);
        !          63743:             $cvstag = "RELEASE_$cvsversion";
        !          63744:             $options['revision'] = $cvstag;
        !          63745:             unset($options['release']);
        !          63746:         }
        !          63747: 
        !          63748:         $execute = true;
        !          63749:         if (isset($options['dry-run'])) {
        !          63750:             $execute = false;
        !          63751:             unset($options['dry-run']);
        !          63752:         }
        !          63753: 
        !          63754:         $cmd .= ' diff';
        !          63755:         // the rest of the options are passed right on to "cvs diff"
        !          63756:         foreach ($options as $option => $optarg) {
        !          63757:             $arg = $short = false;
        !          63758:             if (isset($this->commands[$command]['options'][$option])) {
        !          63759:                 $arg = $this->commands[$command]['options'][$option]['arg'];
        !          63760:                 $short = $this->commands[$command]['options'][$option]['shortopt'];
        !          63761:             }
        !          63762:             $cmd .= $short ? " -$short" : " --$option";
        !          63763:             if ($arg && $optarg) {
        !          63764:                 $cmd .= ($short ? '' : '=') . escapeshellarg($optarg);
        !          63765:             }
        !          63766:         }
        !          63767: 
        !          63768:         foreach ($files as $file) {
        !          63769:             $cmd .= ' ' . escapeshellarg($file['name']);
        !          63770:         }
        !          63771: 
        !          63772:         if ($this->config->get('verbose') > 1) {
        !          63773:             $this->output .= "+ $cmd\n";
        !          63774:         }
        !          63775: 
        !          63776:         if ($execute) {
        !          63777:             $fp = popen($cmd, "r");
        !          63778:             while ($line = fgets($fp, 1024)) {
        !          63779:                 $this->output .= rtrim($line)."\n";
        !          63780:             }
        !          63781:             pclose($fp);
        !          63782:         }
        !          63783: 
        !          63784:         $this->ui->outputData($this->output, $command);
        !          63785:         return true;
        !          63786:     }
        !          63787: 
        !          63788:     function doPackageDependencies($command, $options, $params)
        !          63789:     {
        !          63790:         // $params[0] -> the PEAR package to list its information
        !          63791:         if (count($params) !== 1) {
        !          63792:             return $this->raiseError("bad parameter(s), try \"help $command\"");
        !          63793:         }
        !          63794: 
        !          63795:         $obj = &$this->getPackageFile($this->config, $this->_debug);
        !          63796:         if (is_file($params[0]) || strpos($params[0], '.xml') > 0) {
        !          63797:            $info = $obj->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
        !          63798:         } else {
        !          63799:             $reg  = $this->config->getRegistry();
        !          63800:             $info = $obj->fromArray($reg->packageInfo($params[0]));
        !          63801:         }
        !          63802: 
        !          63803:         if (PEAR::isError($info)) {
        !          63804:             return $this->raiseError($info);
        !          63805:         }
        !          63806: 
        !          63807:         $deps = $info->getDeps();
        !          63808:         if (is_array($deps)) {
        !          63809:             if ($info->getPackagexmlVersion() == '1.0') {
        !          63810:                 $data = array(
        !          63811:                     'caption' => 'Dependencies for pear/' . $info->getPackage(),
        !          63812:                     'border' => true,
        !          63813:                     'headline' => array("Required?", "Type", "Name", "Relation", "Version"),
        !          63814:                     );
        !          63815: 
        !          63816:                 foreach ($deps as $d) {
        !          63817:                     if (isset($d['optional'])) {
        !          63818:                         if ($d['optional'] == 'yes') {
        !          63819:                             $req = 'No';
        !          63820:                         } else {
        !          63821:                             $req = 'Yes';
        !          63822:                         }
        !          63823:                     } else {
        !          63824:                         $req = 'Yes';
        !          63825:                     }
        !          63826: 
        !          63827:                     if (isset($this->_deps_rel_trans[$d['rel']])) {
        !          63828:                         $rel = $this->_deps_rel_trans[$d['rel']];
        !          63829:                     } else {
        !          63830:                         $rel = $d['rel'];
        !          63831:                     }
        !          63832: 
        !          63833:                     if (isset($this->_deps_type_trans[$d['type']])) {
        !          63834:                         $type = ucfirst($this->_deps_type_trans[$d['type']]);
        !          63835:                     } else {
        !          63836:                         $type = $d['type'];
        !          63837:                     }
        !          63838: 
        !          63839:                     if (isset($d['name'])) {
        !          63840:                         $name = $d['name'];
        !          63841:                     } else {
        !          63842:                         $name = '';
        !          63843:                     }
        !          63844: 
        !          63845:                     if (isset($d['version'])) {
        !          63846:                         $version = $d['version'];
        !          63847:                     } else {
        !          63848:                         $version = '';
        !          63849:                     }
        !          63850: 
        !          63851:                     $data['data'][] = array($req, $type, $name, $rel, $version);
        !          63852:                 }
        !          63853:             } else { // package.xml 2.0 dependencies display
        !          63854:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Dependency2.php';
        !          63855:                 $deps = $info->getDependencies();
        !          63856:                 $reg = &$this->config->getRegistry();
        !          63857:                 if (is_array($deps)) {
        !          63858:                     $d = new PEAR_Dependency2($this->config, array(), '');
        !          63859:                     $data = array(
        !          63860:                         'caption' => 'Dependencies for ' . $info->getPackage(),
        !          63861:                         'border' => true,
        !          63862:                         'headline' => array("Required?", "Type", "Name", 'Versioning', 'Group'),
        !          63863:                         );
        !          63864:                     foreach ($deps as $type => $subd) {
        !          63865:                         $req = ($type == 'required') ? 'Yes' : 'No';
        !          63866:                         if ($type == 'group') {
        !          63867:                             $group = $subd['attribs']['name'];
        !          63868:                         } else {
        !          63869:                             $group = '';
        !          63870:                         }
        !          63871: 
        !          63872:                         if (!isset($subd[0])) {
        !          63873:                             $subd = array($subd);
        !          63874:                         }
        !          63875: 
        !          63876:                         foreach ($subd as $groupa) {
        !          63877:                             foreach ($groupa as $deptype => $depinfo) {
        !          63878:                                 if ($deptype == 'attribs') {
        !          63879:                                     continue;
        !          63880:                                 }
        !          63881: 
        !          63882:                                 if ($deptype == 'pearinstaller') {
        !          63883:                                     $deptype = 'pear Installer';
        !          63884:                                 }
        !          63885: 
        !          63886:                                 if (!isset($depinfo[0])) {
        !          63887:                                     $depinfo = array($depinfo);
        !          63888:                                 }
        !          63889: 
        !          63890:                                 foreach ($depinfo as $inf) {
        !          63891:                                     $name = '';
        !          63892:                                     if (isset($inf['channel'])) {
        !          63893:                                         $alias = $reg->channelAlias($inf['channel']);
        !          63894:                                         if (!$alias) {
        !          63895:                                             $alias = '(channel?) ' .$inf['channel'];
        !          63896:                                         }
        !          63897:                                         $name = $alias . '/';
        !          63898: 
        !          63899:                                     }
        !          63900:                                     if (isset($inf['name'])) {
        !          63901:                                         $name .= $inf['name'];
        !          63902:                                     } elseif (isset($inf['pattern'])) {
        !          63903:                                         $name .= $inf['pattern'];
        !          63904:                                     } else {
        !          63905:                                         $name .= '';
        !          63906:                                     }
        !          63907: 
        !          63908:                                     if (isset($inf['uri'])) {
        !          63909:                                         $name .= ' [' . $inf['uri'] .  ']';
        !          63910:                                     }
        !          63911: 
        !          63912:                                     if (isset($inf['conflicts'])) {
        !          63913:                                         $ver = 'conflicts';
        !          63914:                                     } else {
        !          63915:                                         $ver = $d->_getExtraString($inf);
        !          63916:                                     }
        !          63917: 
        !          63918:                                     $data['data'][] = array($req, ucfirst($deptype), $name,
        !          63919:                                         $ver, $group);
        !          63920:                                 }
        !          63921:                             }
        !          63922:                         }
        !          63923:                     }
        !          63924:                 }
        !          63925:             }
        !          63926: 
        !          63927:             $this->ui->outputData($data, $command);
        !          63928:             return true;
        !          63929:         }
        !          63930: 
        !          63931:         // Fallback
        !          63932:         $this->ui->outputData("This package does not have any dependencies.", $command);
        !          63933:     }
        !          63934: 
        !          63935:     function doSign($command, $options, $params)
        !          63936:     {
        !          63937:         // should move most of this code into PEAR_Packager
        !          63938:         // so it'll be easy to implement "pear package --sign"
        !          63939:         if (count($params) !== 1) {
        !          63940:             return $this->raiseError("bad parameter(s), try \"help $command\"");
        !          63941:         }
        !          63942: 
        !          63943:         require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
        !          63944:         require_once 'phar://install-pear-nozlib.phar/' . 'Archive/Tar.php';
        !          63945: 
        !          63946:         if (!file_exists($params[0])) {
        !          63947:             return $this->raiseError("file does not exist: $params[0]");
        !          63948:         }
        !          63949: 
        !          63950:         $obj = $this->getPackageFile($this->config, $this->_debug);
        !          63951:         $info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL);
        !          63952:         if (PEAR::isError($info)) {
        !          63953:             return $this->raiseError($info);
        !          63954:         }
        !          63955: 
        !          63956:         $tar = new Archive_Tar($params[0]);
        !          63957: 
        !          63958:         $tmpdir = $this->config->get('temp_dir');
        !          63959:         $tmpdir = System::mktemp(' -t "' . $tmpdir . '" -d pearsign');
        !          63960:         if (!$tar->extractList('package2.xml package.xml package.sig', $tmpdir)) {
        !          63961:             return $this->raiseError("failed to extract tar file");
        !          63962:         }
        !          63963: 
        !          63964:         if (file_exists("$tmpdir/package.sig")) {
        !          63965:             return $this->raiseError("package already signed");
        !          63966:         }
        !          63967: 
        !          63968:         $packagexml = 'package.xml';
        !          63969:         if (file_exists("$tmpdir/package2.xml")) {
        !          63970:             $packagexml = 'package2.xml';
        !          63971:         }
        !          63972: 
        !          63973:         if (file_exists("$tmpdir/package.sig")) {
        !          63974:             unlink("$tmpdir/package.sig");
        !          63975:         }
        !          63976: 
        !          63977:         if (!file_exists("$tmpdir/$packagexml")) {
        !          63978:             return $this->raiseError("Extracted file $tmpdir/$packagexml not found.");
        !          63979:         }
        !          63980: 
        !          63981:         $input = $this->ui->userDialog($command,
        !          63982:                                        array('GnuPG Passphrase'),
        !          63983:                                        array('password'));
        !          63984:         if (!isset($input[0])) {
        !          63985:             //use empty passphrase
        !          63986:             $input[0] = '';
        !          63987:         }
        !          63988: 
        !          63989:         $devnull = (isset($options['verbose'])) ? '' : ' 2>/dev/null';
        !          63990:         $gpg = popen("gpg --batch --passphrase-fd 0 --armor --detach-sign --output $tmpdir/package.sig $tmpdir/$packagexml" . $devnull, "w");
        !          63991:         if (!$gpg) {
        !          63992:             return $this->raiseError("gpg command failed");
        !          63993:         }
        !          63994: 
        !          63995:         fwrite($gpg, "$input[0]\n");
        !          63996:         if (pclose($gpg) || !file_exists("$tmpdir/package.sig")) {
        !          63997:             return $this->raiseError("gpg sign failed");
        !          63998:         }
        !          63999: 
        !          64000:         if (!$tar->addModify("$tmpdir/package.sig", '', $tmpdir)) {
        !          64001:             return $this->raiseError('failed adding signature to file');
        !          64002:         }
        !          64003: 
        !          64004:         $this->ui->outputData("Package signed.", $command);
        !          64005:         return true;
        !          64006:     }
        !          64007: 
        !          64008:     /**
        !          64009:      * For unit testing purposes
        !          64010:      */
        !          64011:     function &getInstaller(&$ui)
        !          64012:     {
        !          64013:         if (!class_exists('PEAR_Installer')) {
        !          64014:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Installer.php';
        !          64015:         }
        !          64016:         $a = &new PEAR_Installer($ui);
        !          64017:         return $a;
        !          64018:     }
        !          64019: 
        !          64020:     /**
        !          64021:      * For unit testing purposes
        !          64022:      */
        !          64023:     function &getCommandPackaging(&$ui, &$config)
        !          64024:     {
        !          64025:         if (!class_exists('PEAR_Command_Packaging')) {
        !          64026:             if ($fp = @fopen('PEAR/Command/Packaging.php', 'r', true)) {
        !          64027:                 fclose($fp);
        !          64028:                 include_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Packaging.php';
        !          64029:             }
        !          64030:         }
        !          64031: 
        !          64032:         if (class_exists('PEAR_Command_Packaging')) {
        !          64033:             $a = &new PEAR_Command_Packaging($ui, $config);
        !          64034:         } else {
        !          64035:             $a = null;
        !          64036:         }
        !          64037: 
        !          64038:         return $a;
        !          64039:     }
        !          64040: 
        !          64041:     function doMakeRPM($command, $options, $params)
        !          64042:     {
        !          64043: 
        !          64044:         // Check to see if PEAR_Command_Packaging is installed, and
        !          64045:         // transparently switch to use the "make-rpm-spec" command from it
        !          64046:         // instead, if it does. Otherwise, continue to use the old version
        !          64047:         // of "makerpm" supplied with this package (PEAR).
        !          64048:         $packaging_cmd = $this->getCommandPackaging($this->ui, $this->config);
        !          64049:         if ($packaging_cmd !== null) {
        !          64050:             $this->ui->outputData('PEAR_Command_Packaging is installed; using '.
        !          64051:                 'newer "make-rpm-spec" command instead');
        !          64052:             return $packaging_cmd->run('make-rpm-spec', $options, $params);
        !          64053:         }
        !          64054: 
        !          64055:         $this->ui->outputData('WARNING: "pear makerpm" is no longer available; an '.
        !          64056:           'improved version is available via "pear make-rpm-spec", which '.
        !          64057:           'is available by installing PEAR_Command_Packaging');
        !          64058:         return true;
        !          64059:     }
        !          64060: 
        !          64061:     function doConvert($command, $options, $params)
        !          64062:     {
        !          64063:         $packagexml    = isset($params[0]) ? $params[0] : 'package.xml';
        !          64064:         $newpackagexml = isset($params[1]) ? $params[1] : dirname($packagexml) .
        !          64065:             DIRECTORY_SEPARATOR . 'package2.xml';
        !          64066:         $pkg = &$this->getPackageFile($this->config, $this->_debug);
        !          64067:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          64068:         $pf = $pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL);
        !          64069:         PEAR::staticPopErrorHandling();
        !          64070:         if (PEAR::isError($pf)) {
        !          64071:             if (is_array($pf->getUserInfo())) {
        !          64072:                 foreach ($pf->getUserInfo() as $warning) {
        !          64073:                     $this->ui->outputData($warning['message']);
        !          64074:                 }
        !          64075:             }
        !          64076:             return $this->raiseError($pf);
        !          64077:         }
        !          64078: 
        !          64079:         if (is_a($pf, 'PEAR_PackageFile_v2')) {
        !          64080:             $this->ui->outputData($packagexml . ' is already a package.xml version 2.0');
        !          64081:             return true;
        !          64082:         }
        !          64083: 
        !          64084:         $gen   = &$pf->getDefaultGenerator();
        !          64085:         $newpf = &$gen->toV2();
        !          64086:         $newpf->setPackagefile($newpackagexml);
        !          64087:         $gen = &$newpf->getDefaultGenerator();
        !          64088:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          64089:         $state = (isset($options['flat']) ? PEAR_VALIDATE_PACKAGING : PEAR_VALIDATE_NORMAL);
        !          64090:         $saved = $gen->toPackageFile(dirname($newpackagexml), $state, basename($newpackagexml));
        !          64091:         PEAR::staticPopErrorHandling();
        !          64092:         if (PEAR::isError($saved)) {
        !          64093:             if (is_array($saved->getUserInfo())) {
        !          64094:                 foreach ($saved->getUserInfo() as $warning) {
        !          64095:                     $this->ui->outputData($warning['message']);
        !          64096:                 }
        !          64097:             }
        !          64098: 
        !          64099:             $this->ui->outputData($saved->getMessage());
        !          64100:             return true;
        !          64101:         }
        !          64102: 
        !          64103:         $this->ui->outputData('Wrote new version 2.0 package.xml to "' . $saved . '"');
        !          64104:         return true;
        !          64105:     }
        !          64106: }<commands version="1.0">
        !          64107:  <package>
        !          64108:   <summary>Build Package</summary>
        !          64109:   <function>doPackage</function>
        !          64110:   <shortcut>p</shortcut>
        !          64111:   <options>
        !          64112:    <nocompress>
        !          64113:     <shortopt>Z</shortopt>
        !          64114:     <doc>Do not gzip the package file</doc>
        !          64115:    </nocompress>
        !          64116:    <showname>
        !          64117:     <shortopt>n</shortopt>
        !          64118:     <doc>Print the name of the packaged file.</doc>
        !          64119:    </showname>
        !          64120:   </options>
        !          64121:   <doc>[descfile] [descfile2]
        !          64122: Creates a PEAR package from its description file (usually called
        !          64123: package.xml).  If a second packagefile is passed in, then
        !          64124: the packager will check to make sure that one is a package.xml
        !          64125: version 1.0, and the other is a package.xml version 2.0.  The
        !          64126: package.xml version 1.0 will be saved as &quot;package.xml&quot; in the archive,
        !          64127: and the other as &quot;package2.xml&quot; in the archive&quot;
        !          64128: </doc>
        !          64129:  </package>
        !          64130:  <package-validate>
        !          64131:   <summary>Validate Package Consistency</summary>
        !          64132:   <function>doPackageValidate</function>
        !          64133:   <shortcut>pv</shortcut>
        !          64134:   <options />
        !          64135:   <doc>
        !          64136: </doc>
        !          64137:  </package-validate>
        !          64138:  <cvsdiff>
        !          64139:   <summary>Run a &quot;cvs diff&quot; for all files in a package</summary>
        !          64140:   <function>doCvsDiff</function>
        !          64141:   <shortcut>cd</shortcut>
        !          64142:   <options>
        !          64143:    <quiet>
        !          64144:     <shortopt>q</shortopt>
        !          64145:     <doc>Be quiet</doc>
        !          64146:    </quiet>
        !          64147:    <reallyquiet>
        !          64148:     <shortopt>Q</shortopt>
        !          64149:     <doc>Be really quiet</doc>
        !          64150:    </reallyquiet>
        !          64151:    <date>
        !          64152:     <shortopt>D</shortopt>
        !          64153:     <doc>Diff against revision of DATE</doc>
        !          64154:     <arg>DATE</arg>
        !          64155:    </date>
        !          64156:    <release>
        !          64157:     <shortopt>R</shortopt>
        !          64158:     <doc>Diff against tag for package release REL</doc>
        !          64159:     <arg>REL</arg>
        !          64160:    </release>
        !          64161:    <revision>
        !          64162:     <shortopt>r</shortopt>
        !          64163:     <doc>Diff against revision REV</doc>
        !          64164:     <arg>REV</arg>
        !          64165:    </revision>
        !          64166:    <context>
        !          64167:     <shortopt>c</shortopt>
        !          64168:     <doc>Generate context diff</doc>
        !          64169:    </context>
        !          64170:    <unified>
        !          64171:     <shortopt>u</shortopt>
        !          64172:     <doc>Generate unified diff</doc>
        !          64173:    </unified>
        !          64174:    <ignore-case>
        !          64175:     <shortopt>i</shortopt>
        !          64176:     <doc>Ignore case, consider upper- and lower-case letters equivalent</doc>
        !          64177:    </ignore-case>
        !          64178:    <ignore-whitespace>
        !          64179:     <shortopt>b</shortopt>
        !          64180:     <doc>Ignore changes in amount of white space</doc>
        !          64181:    </ignore-whitespace>
        !          64182:    <ignore-blank-lines>
        !          64183:     <shortopt>B</shortopt>
        !          64184:     <doc>Ignore changes that insert or delete blank lines</doc>
        !          64185:    </ignore-blank-lines>
        !          64186:    <brief>
        !          64187:     <shortopt></shortopt>
        !          64188:     <doc>Report only whether the files differ, no details</doc>
        !          64189:    </brief>
        !          64190:    <dry-run>
        !          64191:     <shortopt>n</shortopt>
        !          64192:     <doc>Don&#039;t do anything, just pretend</doc>
        !          64193:    </dry-run>
        !          64194:   </options>
        !          64195:   <doc>&lt;package.xml&gt;
        !          64196: Compares all the files in a package.  Without any options, this
        !          64197: command will compare the current code with the last checked-in code.
        !          64198: Using the -r or -R option you may compare the current code with that
        !          64199: of a specific release.
        !          64200: </doc>
        !          64201:  </cvsdiff>
        !          64202:  <svntag>
        !          64203:   <summary>Set SVN Release Tag</summary>
        !          64204:   <function>doSvnTag</function>
        !          64205:   <shortcut>sv</shortcut>
        !          64206:   <options>
        !          64207:    <quiet>
        !          64208:     <shortopt>q</shortopt>
        !          64209:     <doc>Be quiet</doc>
        !          64210:    </quiet>
        !          64211:    <slide>
        !          64212:     <shortopt>F</shortopt>
        !          64213:     <doc>Move (slide) tag if it exists</doc>
        !          64214:    </slide>
        !          64215:    <delete>
        !          64216:     <shortopt>d</shortopt>
        !          64217:     <doc>Remove tag</doc>
        !          64218:    </delete>
        !          64219:    <dry-run>
        !          64220:     <shortopt>n</shortopt>
        !          64221:     <doc>Don&#039;t do anything, just pretend</doc>
        !          64222:    </dry-run>
        !          64223:   </options>
        !          64224:   <doc>&lt;package.xml&gt; [files...]
        !          64225:  Sets a SVN tag on all files in a package.  Use this command after you have
        !          64226:  packaged a distribution tarball with the &quot;package&quot; command to tag what
        !          64227:  revisions of what files were in that release.  If need to fix something
        !          64228:  after running svntag once, but before the tarball is released to the public,
        !          64229:  use the &quot;slide&quot; option to move the release tag.
        !          64230: 
        !          64231:  to include files (such as a second package.xml, or tests not included in the
        !          64232:  release), pass them as additional parameters.
        !          64233:  </doc>
        !          64234:  </svntag>
        !          64235:  <cvstag>
        !          64236:   <summary>Set CVS Release Tag</summary>
        !          64237:   <function>doCvsTag</function>
        !          64238:   <shortcut>ct</shortcut>
        !          64239:   <options>
        !          64240:    <quiet>
        !          64241:     <shortopt>q</shortopt>
        !          64242:     <doc>Be quiet</doc>
        !          64243:    </quiet>
        !          64244:    <reallyquiet>
        !          64245:     <shortopt>Q</shortopt>
        !          64246:     <doc>Be really quiet</doc>
        !          64247:    </reallyquiet>
        !          64248:    <slide>
        !          64249:     <shortopt>F</shortopt>
        !          64250:     <doc>Move (slide) tag if it exists</doc>
        !          64251:    </slide>
        !          64252:    <delete>
        !          64253:     <shortopt>d</shortopt>
        !          64254:     <doc>Remove tag</doc>
        !          64255:    </delete>
        !          64256:    <dry-run>
        !          64257:     <shortopt>n</shortopt>
        !          64258:     <doc>Don&#039;t do anything, just pretend</doc>
        !          64259:    </dry-run>
        !          64260:   </options>
        !          64261:   <doc>&lt;package.xml&gt; [files...]
        !          64262: Sets a CVS tag on all files in a package.  Use this command after you have
        !          64263: packaged a distribution tarball with the &quot;package&quot; command to tag what
        !          64264: revisions of what files were in that release.  If need to fix something
        !          64265: after running cvstag once, but before the tarball is released to the public,
        !          64266: use the &quot;slide&quot; option to move the release tag.
        !          64267: 
        !          64268: to include files (such as a second package.xml, or tests not included in the
        !          64269: release), pass them as additional parameters.
        !          64270: </doc>
        !          64271:  </cvstag>
        !          64272:  <package-dependencies>
        !          64273:   <summary>Show package dependencies</summary>
        !          64274:   <function>doPackageDependencies</function>
        !          64275:   <shortcut>pd</shortcut>
        !          64276:   <options />
        !          64277:   <doc>&lt;package-file&gt; or &lt;package.xml&gt; or &lt;install-package-name&gt;
        !          64278: List all dependencies the package has.
        !          64279: Can take a tgz / tar file, package.xml or a package name of an installed package.</doc>
        !          64280:  </package-dependencies>
        !          64281:  <sign>
        !          64282:   <summary>Sign a package distribution file</summary>
        !          64283:   <function>doSign</function>
        !          64284:   <shortcut>si</shortcut>
        !          64285:   <options>
        !          64286:    <verbose>
        !          64287:     <shortopt>v</shortopt>
        !          64288:     <doc>Display GnuPG output</doc>
        !          64289:    </verbose>
        !          64290:   </options>
        !          64291:   <doc>&lt;package-file&gt;
        !          64292: Signs a package distribution (.tar or .tgz) file with GnuPG.</doc>
        !          64293:  </sign>
        !          64294:  <makerpm>
        !          64295:   <summary>Builds an RPM spec file from a PEAR package</summary>
        !          64296:   <function>doMakeRPM</function>
        !          64297:   <shortcut>rpm</shortcut>
        !          64298:   <options>
        !          64299:    <spec-template>
        !          64300:     <shortopt>t</shortopt>
        !          64301:     <doc>Use FILE as RPM spec file template</doc>
        !          64302:     <arg>FILE</arg>
        !          64303:    </spec-template>
        !          64304:    <rpm-pkgname>
        !          64305:     <shortopt>p</shortopt>
        !          64306:     <doc>Use FORMAT as format string for RPM package name, %s is replaced
        !          64307: by the PEAR package name, defaults to &quot;PEAR::%s&quot;.</doc>
        !          64308:     <arg>FORMAT</arg>
        !          64309:    </rpm-pkgname>
        !          64310:   </options>
        !          64311:   <doc>&lt;package-file&gt;
        !          64312: 
        !          64313: Creates an RPM .spec file for wrapping a PEAR package inside an RPM
        !          64314: package.  Intended to be used from the SPECS directory, with the PEAR
        !          64315: package tarball in the SOURCES directory:
        !          64316: 
        !          64317: $ pear makerpm ../SOURCES/Net_Socket-1.0.tgz
        !          64318: Wrote RPM spec file PEAR::Net_Geo-1.0.spec
        !          64319: $ rpm -bb PEAR::Net_Socket-1.0.spec
        !          64320: ...
        !          64321: Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
        !          64322: </doc>
        !          64323:  </makerpm>
        !          64324:  <convert>
        !          64325:   <summary>Convert a package.xml 1.0 to package.xml 2.0 format</summary>
        !          64326:   <function>doConvert</function>
        !          64327:   <shortcut>c2</shortcut>
        !          64328:   <options>
        !          64329:    <flat>
        !          64330:     <shortopt>f</shortopt>
        !          64331:     <doc>do not beautify the filelist.</doc>
        !          64332:    </flat>
        !          64333:   </options>
        !          64334:   <doc>[descfile] [descfile2]
        !          64335: Converts a package.xml in 1.0 format into a package.xml
        !          64336: in 2.0 format.  The new file will be named package2.xml by default,
        !          64337: and package.xml will be used as the old file by default.
        !          64338: This is not the most intelligent conversion, and should only be
        !          64339: used for automated conversion or learning the format.
        !          64340: </doc>
        !          64341:  </convert>
        !          64342: </commands><?php
        !          64343: /**
        !          64344:  * PEAR_Command_Pickle (pickle command)
        !          64345:  *
        !          64346:  * PHP versions 4 and 5
        !          64347:  *
        !          64348:  * @category   pear
        !          64349:  * @package    PEAR
        !          64350:  * @author     Greg Beaver <cellog@php.net>
        !          64351:  * @copyright  2005-2009 The Authors
        !          64352:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          64353:  * @version    CVS: $Id: Pickle.php 313023 2011-07-06 19:17:11Z dufuz $
        !          64354:  * @link       http://pear.php.net/package/PEAR
        !          64355:  * @since      File available since Release 1.4.1
        !          64356:  */
        !          64357: 
        !          64358: /**
        !          64359:  * base class
        !          64360:  */
        !          64361: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Common.php';
        !          64362: 
        !          64363: /**
        !          64364:  * PEAR commands for login/logout
        !          64365:  *
        !          64366:  * @category   pear
        !          64367:  * @package    PEAR
        !          64368:  * @author     Greg Beaver <cellog@php.net>
        !          64369:  * @copyright  2005-2009 The Authors
        !          64370:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          64371:  * @version    Release: 1.9.4
        !          64372:  * @link       http://pear.php.net/package/PEAR
        !          64373:  * @since      Class available since Release 1.4.1
        !          64374:  */
        !          64375: 
        !          64376: class PEAR_Command_Pickle extends PEAR_Command_Common
        !          64377: {
        !          64378:     var $commands = array(
        !          64379:         'pickle' => array(
        !          64380:             'summary' => 'Build PECL Package',
        !          64381:             'function' => 'doPackage',
        !          64382:             'shortcut' => 'pi',
        !          64383:             'options' => array(
        !          64384:                 'nocompress' => array(
        !          64385:                     'shortopt' => 'Z',
        !          64386:                     'doc' => 'Do not gzip the package file'
        !          64387:                     ),
        !          64388:                 'showname' => array(
        !          64389:                     'shortopt' => 'n',
        !          64390:                     'doc' => 'Print the name of the packaged file.',
        !          64391:                     ),
        !          64392:                 ),
        !          64393:             'doc' => '[descfile]
        !          64394: Creates a PECL package from its package2.xml file.
        !          64395: 
        !          64396: An automatic conversion will be made to a package.xml 1.0 and written out to
        !          64397: disk in the current directory as "package.xml".  Note that
        !          64398: only simple package.xml 2.0 will be converted.  package.xml 2.0 with:
        !          64399: 
        !          64400:  - dependency types other than required/optional PECL package/ext/php/pearinstaller
        !          64401:  - more than one extsrcrelease or zendextsrcrelease
        !          64402:  - zendextbinrelease, extbinrelease, phprelease, or bundle release type
        !          64403:  - dependency groups
        !          64404:  - ignore tags in release filelist
        !          64405:  - tasks other than replace
        !          64406:  - custom roles
        !          64407: 
        !          64408: will cause pickle to fail, and output an error message.  If your package2.xml
        !          64409: uses any of these features, you are best off using PEAR_PackageFileManager to
        !          64410: generate both package.xml.
        !          64411: '
        !          64412:             ),
        !          64413:         );
        !          64414: 
        !          64415:     /**
        !          64416:      * PEAR_Command_Package constructor.
        !          64417:      *
        !          64418:      * @access public
        !          64419:      */
        !          64420:     function PEAR_Command_Pickle(&$ui, &$config)
        !          64421:     {
        !          64422:         parent::PEAR_Command_Common($ui, $config);
        !          64423:     }
        !          64424: 
        !          64425:     /**
        !          64426:      * For unit-testing ease
        !          64427:      *
        !          64428:      * @return PEAR_Packager
        !          64429:      */
        !          64430:     function &getPackager()
        !          64431:     {
        !          64432:         if (!class_exists('PEAR_Packager')) {
        !          64433:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Packager.php';
        !          64434:         }
        !          64435: 
        !          64436:         $a = &new PEAR_Packager;
        !          64437:         return $a;
        !          64438:     }
        !          64439: 
        !          64440:     /**
        !          64441:      * For unit-testing ease
        !          64442:      *
        !          64443:      * @param PEAR_Config $config
        !          64444:      * @param bool $debug
        !          64445:      * @param string|null $tmpdir
        !          64446:      * @return PEAR_PackageFile
        !          64447:      */
        !          64448:     function &getPackageFile($config, $debug = false)
        !          64449:     {
        !          64450:         if (!class_exists('PEAR_Common')) {
        !          64451:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
        !          64452:         }
        !          64453: 
        !          64454:         if (!class_exists('PEAR_PackageFile')) {
        !          64455:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile.php';
        !          64456:         }
        !          64457: 
        !          64458:         $a = &new PEAR_PackageFile($config, $debug);
        !          64459:         $common = new PEAR_Common;
        !          64460:         $common->ui = $this->ui;
        !          64461:         $a->setLogger($common);
        !          64462:         return $a;
        !          64463:     }
        !          64464: 
        !          64465:     function doPackage($command, $options, $params)
        !          64466:     {
        !          64467:         $this->output = '';
        !          64468:         $pkginfofile = isset($params[0]) ? $params[0] : 'package2.xml';
        !          64469:         $packager = &$this->getPackager();
        !          64470:         if (PEAR::isError($err = $this->_convertPackage($pkginfofile))) {
        !          64471:             return $err;
        !          64472:         }
        !          64473: 
        !          64474:         $compress = empty($options['nocompress']) ? true : false;
        !          64475:         $result = $packager->package($pkginfofile, $compress, 'package.xml');
        !          64476:         if (PEAR::isError($result)) {
        !          64477:             return $this->raiseError($result);
        !          64478:         }
        !          64479: 
        !          64480:         // Don't want output, only the package file name just created
        !          64481:         if (isset($options['showname'])) {
        !          64482:             $this->ui->outputData($result, $command);
        !          64483:         }
        !          64484: 
        !          64485:         return true;
        !          64486:     }
        !          64487: 
        !          64488:     function _convertPackage($packagexml)
        !          64489:     {
        !          64490:         $pkg = &$this->getPackageFile($this->config);
        !          64491:         $pf2 = &$pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL);
        !          64492:         if (!is_a($pf2, 'PEAR_PackageFile_v2')) {
        !          64493:             return $this->raiseError('Cannot process "' .
        !          64494:                 $packagexml . '", is not a package.xml 2.0');
        !          64495:         }
        !          64496: 
        !          64497:         require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v1.php';
        !          64498:         $pf = new PEAR_PackageFile_v1;
        !          64499:         $pf->setConfig($this->config);
        !          64500:         if ($pf2->getPackageType() != 'extsrc' && $pf2->getPackageType() != 'zendextsrc') {
        !          64501:             return $this->raiseError('Cannot safely convert "' . $packagexml .
        !          64502:             '", is not an extension source package.  Using a PEAR_PackageFileManager-based ' .
        !          64503:             'script is an option');
        !          64504:         }
        !          64505: 
        !          64506:         if (is_array($pf2->getUsesRole())) {
        !          64507:             return $this->raiseError('Cannot safely convert "' . $packagexml .
        !          64508:             '", contains custom roles.  Using a PEAR_PackageFileManager-based script or ' .
        !          64509:             'the convert command is an option');
        !          64510:         }
        !          64511: 
        !          64512:         if (is_array($pf2->getUsesTask())) {
        !          64513:             return $this->raiseError('Cannot safely convert "' . $packagexml .
        !          64514:             '", contains custom tasks.  Using a PEAR_PackageFileManager-based script or ' .
        !          64515:             'the convert command is an option');
        !          64516:         }
        !          64517: 
        !          64518:         $deps = $pf2->getDependencies();
        !          64519:         if (isset($deps['group'])) {
        !          64520:             return $this->raiseError('Cannot safely convert "' . $packagexml .
        !          64521:             '", contains dependency groups.  Using a PEAR_PackageFileManager-based script ' .
        !          64522:             'or the convert command is an option');
        !          64523:         }
        !          64524: 
        !          64525:         if (isset($deps['required']['subpackage']) ||
        !          64526:               isset($deps['optional']['subpackage'])) {
        !          64527:             return $this->raiseError('Cannot safely convert "' . $packagexml .
        !          64528:             '", contains subpackage dependencies.  Using a PEAR_PackageFileManager-based  '.
        !          64529:             'script is an option');
        !          64530:         }
        !          64531: 
        !          64532:         if (isset($deps['required']['os'])) {
        !          64533:             return $this->raiseError('Cannot safely convert "' . $packagexml .
        !          64534:             '", contains os dependencies.  Using a PEAR_PackageFileManager-based  '.
        !          64535:             'script is an option');
        !          64536:         }
        !          64537: 
        !          64538:         if (isset($deps['required']['arch'])) {
        !          64539:             return $this->raiseError('Cannot safely convert "' . $packagexml .
        !          64540:             '", contains arch dependencies.  Using a PEAR_PackageFileManager-based  '.
        !          64541:             'script is an option');
        !          64542:         }
        !          64543: 
        !          64544:         $pf->setPackage($pf2->getPackage());
        !          64545:         $pf->setSummary($pf2->getSummary());
        !          64546:         $pf->setDescription($pf2->getDescription());
        !          64547:         foreach ($pf2->getMaintainers() as $maintainer) {
        !          64548:             $pf->addMaintainer($maintainer['role'], $maintainer['handle'],
        !          64549:                 $maintainer['name'], $maintainer['email']);
        !          64550:         }
        !          64551: 
        !          64552:         $pf->setVersion($pf2->getVersion());
        !          64553:         $pf->setDate($pf2->getDate());
        !          64554:         $pf->setLicense($pf2->getLicense());
        !          64555:         $pf->setState($pf2->getState());
        !          64556:         $pf->setNotes($pf2->getNotes());
        !          64557:         $pf->addPhpDep($deps['required']['php']['min'], 'ge');
        !          64558:         if (isset($deps['required']['php']['max'])) {
        !          64559:             $pf->addPhpDep($deps['required']['php']['max'], 'le');
        !          64560:         }
        !          64561: 
        !          64562:         if (isset($deps['required']['package'])) {
        !          64563:             if (!isset($deps['required']['package'][0])) {
        !          64564:                 $deps['required']['package'] = array($deps['required']['package']);
        !          64565:             }
        !          64566: 
        !          64567:             foreach ($deps['required']['package'] as $dep) {
        !          64568:                 if (!isset($dep['channel'])) {
        !          64569:                     return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
        !          64570:                     ' contains uri-based dependency on a package.  Using a ' .
        !          64571:                     'PEAR_PackageFileManager-based script is an option');
        !          64572:                 }
        !          64573: 
        !          64574:                 if ($dep['channel'] != 'pear.php.net'
        !          64575:                     && $dep['channel'] != 'pecl.php.net'
        !          64576:                     && $dep['channel'] != 'doc.php.net') {
        !          64577:                     return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
        !          64578:                     ' contains dependency on a non-standard channel package.  Using a ' .
        !          64579:                     'PEAR_PackageFileManager-based script is an option');
        !          64580:                 }
        !          64581: 
        !          64582:                 if (isset($dep['conflicts'])) {
        !          64583:                     return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
        !          64584:                     ' contains conflicts dependency.  Using a ' .
        !          64585:                     'PEAR_PackageFileManager-based script is an option');
        !          64586:                 }
        !          64587: 
        !          64588:                 if (isset($dep['exclude'])) {
        !          64589:                     $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
        !          64590:                 }
        !          64591: 
        !          64592:                 if (isset($dep['min'])) {
        !          64593:                     $pf->addPackageDep($dep['name'], $dep['min'], 'ge');
        !          64594:                 }
        !          64595: 
        !          64596:                 if (isset($dep['max'])) {
        !          64597:                     $pf->addPackageDep($dep['name'], $dep['max'], 'le');
        !          64598:                 }
        !          64599:             }
        !          64600:         }
        !          64601: 
        !          64602:         if (isset($deps['required']['extension'])) {
        !          64603:             if (!isset($deps['required']['extension'][0])) {
        !          64604:                 $deps['required']['extension'] = array($deps['required']['extension']);
        !          64605:             }
        !          64606: 
        !          64607:             foreach ($deps['required']['extension'] as $dep) {
        !          64608:                 if (isset($dep['conflicts'])) {
        !          64609:                     return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
        !          64610:                     ' contains conflicts dependency.  Using a ' .
        !          64611:                     'PEAR_PackageFileManager-based script is an option');
        !          64612:                 }
        !          64613: 
        !          64614:                 if (isset($dep['exclude'])) {
        !          64615:                     $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
        !          64616:                 }
        !          64617: 
        !          64618:                 if (isset($dep['min'])) {
        !          64619:                     $pf->addExtensionDep($dep['name'], $dep['min'], 'ge');
        !          64620:                 }
        !          64621: 
        !          64622:                 if (isset($dep['max'])) {
        !          64623:                     $pf->addExtensionDep($dep['name'], $dep['max'], 'le');
        !          64624:                 }
        !          64625:             }
        !          64626:         }
        !          64627: 
        !          64628:         if (isset($deps['optional']['package'])) {
        !          64629:             if (!isset($deps['optional']['package'][0])) {
        !          64630:                 $deps['optional']['package'] = array($deps['optional']['package']);
        !          64631:             }
        !          64632: 
        !          64633:             foreach ($deps['optional']['package'] as $dep) {
        !          64634:                 if (!isset($dep['channel'])) {
        !          64635:                     return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
        !          64636:                     ' contains uri-based dependency on a package.  Using a ' .
        !          64637:                     'PEAR_PackageFileManager-based script is an option');
        !          64638:                 }
        !          64639: 
        !          64640:                 if ($dep['channel'] != 'pear.php.net'
        !          64641:                     && $dep['channel'] != 'pecl.php.net'
        !          64642:                     && $dep['channel'] != 'doc.php.net') {
        !          64643:                     return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
        !          64644:                     ' contains dependency on a non-standard channel package.  Using a ' .
        !          64645:                     'PEAR_PackageFileManager-based script is an option');
        !          64646:                 }
        !          64647: 
        !          64648:                 if (isset($dep['exclude'])) {
        !          64649:                     $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
        !          64650:                 }
        !          64651: 
        !          64652:                 if (isset($dep['min'])) {
        !          64653:                     $pf->addPackageDep($dep['name'], $dep['min'], 'ge', 'yes');
        !          64654:                 }
        !          64655: 
        !          64656:                 if (isset($dep['max'])) {
        !          64657:                     $pf->addPackageDep($dep['name'], $dep['max'], 'le', 'yes');
        !          64658:                 }
        !          64659:             }
        !          64660:         }
        !          64661: 
        !          64662:         if (isset($deps['optional']['extension'])) {
        !          64663:             if (!isset($deps['optional']['extension'][0])) {
        !          64664:                 $deps['optional']['extension'] = array($deps['optional']['extension']);
        !          64665:             }
        !          64666: 
        !          64667:             foreach ($deps['optional']['extension'] as $dep) {
        !          64668:                 if (isset($dep['exclude'])) {
        !          64669:                     $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
        !          64670:                 }
        !          64671: 
        !          64672:                 if (isset($dep['min'])) {
        !          64673:                     $pf->addExtensionDep($dep['name'], $dep['min'], 'ge', 'yes');
        !          64674:                 }
        !          64675: 
        !          64676:                 if (isset($dep['max'])) {
        !          64677:                     $pf->addExtensionDep($dep['name'], $dep['max'], 'le', 'yes');
        !          64678:                 }
        !          64679:             }
        !          64680:         }
        !          64681: 
        !          64682:         $contents = $pf2->getContents();
        !          64683:         $release  = $pf2->getReleases();
        !          64684:         if (isset($releases[0])) {
        !          64685:             return $this->raiseError('Cannot safely process "' . $packagexml . '" contains '
        !          64686:             . 'multiple extsrcrelease/zendextsrcrelease tags.  Using a PEAR_PackageFileManager-based script ' .
        !          64687:             'or the convert command is an option');
        !          64688:         }
        !          64689: 
        !          64690:         if ($configoptions = $pf2->getConfigureOptions()) {
        !          64691:             foreach ($configoptions as $option) {
        !          64692:                 $default = isset($option['default']) ? $option['default'] : false;
        !          64693:                 $pf->addConfigureOption($option['name'], $option['prompt'], $default);
        !          64694:             }
        !          64695:         }
        !          64696: 
        !          64697:         if (isset($release['filelist']['ignore'])) {
        !          64698:             return $this->raiseError('Cannot safely process "' . $packagexml . '" contains '
        !          64699:             . 'ignore tags.  Using a PEAR_PackageFileManager-based script or the convert' .
        !          64700:             ' command is an option');
        !          64701:         }
        !          64702: 
        !          64703:         if (isset($release['filelist']['install']) &&
        !          64704:               !isset($release['filelist']['install'][0])) {
        !          64705:             $release['filelist']['install'] = array($release['filelist']['install']);
        !          64706:         }
        !          64707: 
        !          64708:         if (isset($contents['dir']['attribs']['baseinstalldir'])) {
        !          64709:             $baseinstalldir = $contents['dir']['attribs']['baseinstalldir'];
        !          64710:         } else {
        !          64711:             $baseinstalldir = false;
        !          64712:         }
        !          64713: 
        !          64714:         if (!isset($contents['dir']['file'][0])) {
        !          64715:             $contents['dir']['file'] = array($contents['dir']['file']);
        !          64716:         }
        !          64717: 
        !          64718:         foreach ($contents['dir']['file'] as $file) {
        !          64719:             if ($baseinstalldir && !isset($file['attribs']['baseinstalldir'])) {
        !          64720:                 $file['attribs']['baseinstalldir'] = $baseinstalldir;
        !          64721:             }
        !          64722: 
        !          64723:             $processFile = $file;
        !          64724:             unset($processFile['attribs']);
        !          64725:             if (count($processFile)) {
        !          64726:                 foreach ($processFile as $name => $task) {
        !          64727:                     if ($name != $pf2->getTasksNs() . ':replace') {
        !          64728:                         return $this->raiseError('Cannot safely process "' . $packagexml .
        !          64729:                         '" contains tasks other than replace.  Using a ' .
        !          64730:                         'PEAR_PackageFileManager-based script is an option.');
        !          64731:                     }
        !          64732:                     $file['attribs']['replace'][] = $task;
        !          64733:                 }
        !          64734:             }
        !          64735: 
        !          64736:             if (!in_array($file['attribs']['role'], PEAR_Common::getFileRoles())) {
        !          64737:                 return $this->raiseError('Cannot safely convert "' . $packagexml .
        !          64738:                 '", contains custom roles.  Using a PEAR_PackageFileManager-based script ' .
        !          64739:                 'or the convert command is an option');
        !          64740:             }
        !          64741: 
        !          64742:             if (isset($release['filelist']['install'])) {
        !          64743:                 foreach ($release['filelist']['install'] as $installas) {
        !          64744:                     if ($installas['attribs']['name'] == $file['attribs']['name']) {
        !          64745:                         $file['attribs']['install-as'] = $installas['attribs']['as'];
        !          64746:                     }
        !          64747:                 }
        !          64748:             }
        !          64749: 
        !          64750:             $pf->addFile('/', $file['attribs']['name'], $file['attribs']);
        !          64751:         }
        !          64752: 
        !          64753:         if ($pf2->getChangeLog()) {
        !          64754:             $this->ui->outputData('WARNING: changelog is not translated to package.xml ' .
        !          64755:                 '1.0, use PEAR_PackageFileManager-based script if you need changelog-' .
        !          64756:                 'translation for package.xml 1.0');
        !          64757:         }
        !          64758: 
        !          64759:         $gen = &$pf->getDefaultGenerator();
        !          64760:         $gen->toPackageFile('.');
        !          64761:     }
        !          64762: }<commands version="1.0">
        !          64763:  <pickle>
        !          64764:   <summary>Build PECL Package</summary>
        !          64765:   <function>doPackage</function>
        !          64766:   <shortcut>pi</shortcut>
        !          64767:   <options>
        !          64768:    <nocompress>
        !          64769:     <shortopt>Z</shortopt>
        !          64770:     <doc>Do not gzip the package file</doc>
        !          64771:    </nocompress>
        !          64772:    <showname>
        !          64773:     <shortopt>n</shortopt>
        !          64774:     <doc>Print the name of the packaged file.</doc>
        !          64775:    </showname>
        !          64776:   </options>
        !          64777:   <doc>[descfile]
        !          64778: Creates a PECL package from its package2.xml file.
        !          64779: 
        !          64780: An automatic conversion will be made to a package.xml 1.0 and written out to
        !          64781: disk in the current directory as &quot;package.xml&quot;.  Note that
        !          64782: only simple package.xml 2.0 will be converted.  package.xml 2.0 with:
        !          64783: 
        !          64784:  - dependency types other than required/optional PECL package/ext/php/pearinstaller
        !          64785:  - more than one extsrcrelease or zendextsrcrelease
        !          64786:  - zendextbinrelease, extbinrelease, phprelease, or bundle release type
        !          64787:  - dependency groups
        !          64788:  - ignore tags in release filelist
        !          64789:  - tasks other than replace
        !          64790:  - custom roles
        !          64791: 
        !          64792: will cause pickle to fail, and output an error message.  If your package2.xml
        !          64793: uses any of these features, you are best off using PEAR_PackageFileManager to
        !          64794: generate both package.xml.
        !          64795: </doc>
        !          64796:  </pickle>
        !          64797: </commands><?php
        !          64798: /**
        !          64799:  * PEAR_Command_Registry (list, list-files, shell-test, info commands)
        !          64800:  *
        !          64801:  * PHP versions 4 and 5
        !          64802:  *
        !          64803:  * @category   pear
        !          64804:  * @package    PEAR
        !          64805:  * @author     Stig Bakken <ssb@php.net>
        !          64806:  * @author     Greg Beaver <cellog@php.net>
        !          64807:  * @copyright  1997-2009 The Authors
        !          64808:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          64809:  * @version    CVS: $Id: Registry.php 313023 2011-07-06 19:17:11Z dufuz $
        !          64810:  * @link       http://pear.php.net/package/PEAR
        !          64811:  * @since      File available since Release 0.1
        !          64812:  */
        !          64813: 
        !          64814: /**
        !          64815:  * base class
        !          64816:  */
        !          64817: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Common.php';
        !          64818: 
        !          64819: /**
        !          64820:  * PEAR commands for registry manipulation
        !          64821:  *
        !          64822:  * @category   pear
        !          64823:  * @package    PEAR
        !          64824:  * @author     Stig Bakken <ssb@php.net>
        !          64825:  * @author     Greg Beaver <cellog@php.net>
        !          64826:  * @copyright  1997-2009 The Authors
        !          64827:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          64828:  * @version    Release: 1.9.4
        !          64829:  * @link       http://pear.php.net/package/PEAR
        !          64830:  * @since      Class available since Release 0.1
        !          64831:  */
        !          64832: class PEAR_Command_Registry extends PEAR_Command_Common
        !          64833: {
        !          64834:     var $commands = array(
        !          64835:         'list' => array(
        !          64836:             'summary' => 'List Installed Packages In The Default Channel',
        !          64837:             'function' => 'doList',
        !          64838:             'shortcut' => 'l',
        !          64839:             'options' => array(
        !          64840:                 'channel' => array(
        !          64841:                     'shortopt' => 'c',
        !          64842:                     'doc' => 'list installed packages from this channel',
        !          64843:                     'arg' => 'CHAN',
        !          64844:                     ),
        !          64845:                 'allchannels' => array(
        !          64846:                     'shortopt' => 'a',
        !          64847:                     'doc' => 'list installed packages from all channels',
        !          64848:                     ),
        !          64849:                 'channelinfo' => array(
        !          64850:                     'shortopt' => 'i',
        !          64851:                     'doc' => 'output fully channel-aware data, even on failure',
        !          64852:                     ),
        !          64853:                 ),
        !          64854:             'doc' => '<package>
        !          64855: If invoked without parameters, this command lists the PEAR packages
        !          64856: installed in your php_dir ({config php_dir}).  With a parameter, it
        !          64857: lists the files in a package.
        !          64858: ',
        !          64859:             ),
        !          64860:         'list-files' => array(
        !          64861:             'summary' => 'List Files In Installed Package',
        !          64862:             'function' => 'doFileList',
        !          64863:             'shortcut' => 'fl',
        !          64864:             'options' => array(),
        !          64865:             'doc' => '<package>
        !          64866: List the files in an installed package.
        !          64867: '
        !          64868:             ),
        !          64869:         'shell-test' => array(
        !          64870:             'summary' => 'Shell Script Test',
        !          64871:             'function' => 'doShellTest',
        !          64872:             'shortcut' => 'st',
        !          64873:             'options' => array(),
        !          64874:             'doc' => '<package> [[relation] version]
        !          64875: Tests if a package is installed in the system. Will exit(1) if it is not.
        !          64876:    <relation>   The version comparison operator. One of:
        !          64877:                 <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne
        !          64878:    <version>    The version to compare with
        !          64879: '),
        !          64880:         'info' => array(
        !          64881:             'summary'  => 'Display information about a package',
        !          64882:             'function' => 'doInfo',
        !          64883:             'shortcut' => 'in',
        !          64884:             'options'  => array(),
        !          64885:             'doc'      => '<package>
        !          64886: Displays information about a package. The package argument may be a
        !          64887: local package file, an URL to a package file, or the name of an
        !          64888: installed package.'
        !          64889:             )
        !          64890:         );
        !          64891: 
        !          64892:     /**
        !          64893:      * PEAR_Command_Registry constructor.
        !          64894:      *
        !          64895:      * @access public
        !          64896:      */
        !          64897:     function PEAR_Command_Registry(&$ui, &$config)
        !          64898:     {
        !          64899:         parent::PEAR_Command_Common($ui, $config);
        !          64900:     }
        !          64901: 
        !          64902:     function _sortinfo($a, $b)
        !          64903:     {
        !          64904:         $apackage = isset($a['package']) ? $a['package'] : $a['name'];
        !          64905:         $bpackage = isset($b['package']) ? $b['package'] : $b['name'];
        !          64906:         return strcmp($apackage, $bpackage);
        !          64907:     }
        !          64908: 
        !          64909:     function doList($command, $options, $params)
        !          64910:     {
        !          64911:         $reg = &$this->config->getRegistry();
        !          64912:         $channelinfo = isset($options['channelinfo']);
        !          64913:         if (isset($options['allchannels']) && !$channelinfo) {
        !          64914:             return $this->doListAll($command, array(), $params);
        !          64915:         }
        !          64916: 
        !          64917:         if (isset($options['allchannels']) && $channelinfo) {
        !          64918:             // allchannels with $channelinfo
        !          64919:             unset($options['allchannels']);
        !          64920:             $channels = $reg->getChannels();
        !          64921:             $errors = array();
        !          64922:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          64923:             foreach ($channels as $channel) {
        !          64924:                 $options['channel'] = $channel->getName();
        !          64925:                 $ret = $this->doList($command, $options, $params);
        !          64926: 
        !          64927:                 if (PEAR::isError($ret)) {
        !          64928:                     $errors[] = $ret;
        !          64929:                 }
        !          64930:             }
        !          64931: 
        !          64932:             PEAR::staticPopErrorHandling();
        !          64933:             if (count($errors)) {
        !          64934:                 // for now, only give first error
        !          64935:                 return PEAR::raiseError($errors[0]);
        !          64936:             }
        !          64937: 
        !          64938:             return true;
        !          64939:         }
        !          64940: 
        !          64941:         if (count($params) === 1) {
        !          64942:             return $this->doFileList($command, $options, $params);
        !          64943:         }
        !          64944: 
        !          64945:         if (isset($options['channel'])) {
        !          64946:             if (!$reg->channelExists($options['channel'])) {
        !          64947:                 return $this->raiseError('Channel "' . $options['channel'] .'" does not exist');
        !          64948:             }
        !          64949: 
        !          64950:             $channel = $reg->channelName($options['channel']);
        !          64951:         } else {
        !          64952:             $channel = $this->config->get('default_channel');
        !          64953:         }
        !          64954: 
        !          64955:         $installed = $reg->packageInfo(null, null, $channel);
        !          64956:         usort($installed, array(&$this, '_sortinfo'));
        !          64957: 
        !          64958:         $data = array(
        !          64959:             'caption' => 'Installed packages, channel ' .
        !          64960:                 $channel . ':',
        !          64961:             'border' => true,
        !          64962:             'headline' => array('Package', 'Version', 'State'),
        !          64963:             'channel' => $channel,
        !          64964:             );
        !          64965:         if ($channelinfo) {
        !          64966:             $data['headline'] = array('Channel', 'Package', 'Version', 'State');
        !          64967:         }
        !          64968: 
        !          64969:         if (count($installed) && !isset($data['data'])) {
        !          64970:             $data['data'] = array();
        !          64971:         }
        !          64972: 
        !          64973:         foreach ($installed as $package) {
        !          64974:             $pobj = $reg->getPackage(isset($package['package']) ?
        !          64975:                                         $package['package'] : $package['name'], $channel);
        !          64976:             if ($channelinfo) {
        !          64977:                 $packageinfo = array($pobj->getChannel(), $pobj->getPackage(), $pobj->getVersion(),
        !          64978:                                     $pobj->getState() ? $pobj->getState() : null);
        !          64979:             } else {
        !          64980:                 $packageinfo = array($pobj->getPackage(), $pobj->getVersion(),
        !          64981:                                     $pobj->getState() ? $pobj->getState() : null);
        !          64982:             }
        !          64983:             $data['data'][] = $packageinfo;
        !          64984:         }
        !          64985: 
        !          64986:         if (count($installed) === 0) {
        !          64987:             if (!$channelinfo) {
        !          64988:                 $data = '(no packages installed from channel ' . $channel . ')';
        !          64989:             } else {
        !          64990:                 $data = array(
        !          64991:                     'caption' => 'Installed packages, channel ' .
        !          64992:                         $channel . ':',
        !          64993:                     'border' => true,
        !          64994:                     'channel' => $channel,
        !          64995:                     'data' => array(array('(no packages installed)')),
        !          64996:                 );
        !          64997:             }
        !          64998:         }
        !          64999: 
        !          65000:         $this->ui->outputData($data, $command);
        !          65001:         return true;
        !          65002:     }
        !          65003: 
        !          65004:     function doListAll($command, $options, $params)
        !          65005:     {
        !          65006:         // This duplicate code is deprecated over
        !          65007:         // list --channelinfo, which gives identical
        !          65008:         // output for list and list --allchannels.
        !          65009:         $reg = &$this->config->getRegistry();
        !          65010:         $installed = $reg->packageInfo(null, null, null);
        !          65011:         foreach ($installed as $channel => $packages) {
        !          65012:             usort($packages, array($this, '_sortinfo'));
        !          65013:             $data = array(
        !          65014:                 'caption'  => 'Installed packages, channel ' . $channel . ':',
        !          65015:                 'border'   => true,
        !          65016:                 'headline' => array('Package', 'Version', 'State'),
        !          65017:                 'channel'  => $channel
        !          65018:             );
        !          65019: 
        !          65020:             foreach ($packages as $package) {
        !          65021:                 $p = isset($package['package']) ? $package['package'] : $package['name'];
        !          65022:                 $pobj = $reg->getPackage($p, $channel);
        !          65023:                 $data['data'][] = array($pobj->getPackage(), $pobj->getVersion(),
        !          65024:                                         $pobj->getState() ? $pobj->getState() : null);
        !          65025:             }
        !          65026: 
        !          65027:             // Adds a blank line after each section
        !          65028:             $data['data'][] = array();
        !          65029: 
        !          65030:             if (count($packages) === 0) {
        !          65031:                 $data = array(
        !          65032:                     'caption' => 'Installed packages, channel ' . $channel . ':',
        !          65033:                     'border' => true,
        !          65034:                     'data' => array(array('(no packages installed)'), array()),
        !          65035:                     'channel' => $channel
        !          65036:                     );
        !          65037:             }
        !          65038:             $this->ui->outputData($data, $command);
        !          65039:         }
        !          65040:         return true;
        !          65041:     }
        !          65042: 
        !          65043:     function doFileList($command, $options, $params)
        !          65044:     {
        !          65045:         if (count($params) !== 1) {
        !          65046:             return $this->raiseError('list-files expects 1 parameter');
        !          65047:         }
        !          65048: 
        !          65049:         $reg = &$this->config->getRegistry();
        !          65050:         $fp = false;
        !          65051:         if (!is_dir($params[0]) && (file_exists($params[0]) || $fp = @fopen($params[0], 'r'))) {
        !          65052:             if ($fp) {
        !          65053:                 fclose($fp);
        !          65054:             }
        !          65055: 
        !          65056:             if (!class_exists('PEAR_PackageFile')) {
        !          65057:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile.php';
        !          65058:             }
        !          65059: 
        !          65060:             $pkg = &new PEAR_PackageFile($this->config, $this->_debug);
        !          65061:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          65062:             $info = &$pkg->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
        !          65063:             PEAR::staticPopErrorHandling();
        !          65064:             $headings = array('Package File', 'Install Path');
        !          65065:             $installed = false;
        !          65066:         } else {
        !          65067:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          65068:             $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
        !          65069:             PEAR::staticPopErrorHandling();
        !          65070:             if (PEAR::isError($parsed)) {
        !          65071:                 return $this->raiseError($parsed);
        !          65072:             }
        !          65073: 
        !          65074:             $info = &$reg->getPackage($parsed['package'], $parsed['channel']);
        !          65075:             $headings = array('Type', 'Install Path');
        !          65076:             $installed = true;
        !          65077:         }
        !          65078: 
        !          65079:         if (PEAR::isError($info)) {
        !          65080:             return $this->raiseError($info);
        !          65081:         }
        !          65082: 
        !          65083:         if ($info === null) {
        !          65084:             return $this->raiseError("`$params[0]' not installed");
        !          65085:         }
        !          65086: 
        !          65087:         $list = ($info->getPackagexmlVersion() == '1.0' || $installed) ?
        !          65088:             $info->getFilelist() : $info->getContents();
        !          65089:         if ($installed) {
        !          65090:             $caption = 'Installed Files For ' . $params[0];
        !          65091:         } else {
        !          65092:             $caption = 'Contents of ' . basename($params[0]);
        !          65093:         }
        !          65094: 
        !          65095:         $data = array(
        !          65096:             'caption' => $caption,
        !          65097:             'border' => true,
        !          65098:             'headline' => $headings);
        !          65099:         if ($info->getPackagexmlVersion() == '1.0' || $installed) {
        !          65100:             foreach ($list as $file => $att) {
        !          65101:                 if ($installed) {
        !          65102:                     if (empty($att['installed_as'])) {
        !          65103:                         continue;
        !          65104:                     }
        !          65105:                     $data['data'][] = array($att['role'], $att['installed_as']);
        !          65106:                 } else {
        !          65107:                     if (isset($att['baseinstalldir']) && !in_array($att['role'],
        !          65108:                           array('test', 'data', 'doc'))) {
        !          65109:                         $dest = $att['baseinstalldir'] . DIRECTORY_SEPARATOR .
        !          65110:                             $file;
        !          65111:                     } else {
        !          65112:                         $dest = $file;
        !          65113:                     }
        !          65114:                     switch ($att['role']) {
        !          65115:                         case 'test':
        !          65116:                         case 'data':
        !          65117:                         case 'doc':
        !          65118:                             $role = $att['role'];
        !          65119:                             if ($role == 'test') {
        !          65120:                                 $role .= 's';
        !          65121:                             }
        !          65122:                             $dest = $this->config->get($role . '_dir') . DIRECTORY_SEPARATOR .
        !          65123:                                 $info->getPackage() . DIRECTORY_SEPARATOR . $dest;
        !          65124:                             break;
        !          65125:                         case 'php':
        !          65126:                         default:
        !          65127:                             $dest = $this->config->get('php_dir') . DIRECTORY_SEPARATOR .
        !          65128:                                 $dest;
        !          65129:                     }
        !          65130:                     $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
        !          65131:                     $dest = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"),
        !          65132:                                                     array(DIRECTORY_SEPARATOR,
        !          65133:                                                           DIRECTORY_SEPARATOR,
        !          65134:                                                           DIRECTORY_SEPARATOR),
        !          65135:                                                     $dest);
        !          65136:                     $file = preg_replace('!/+!', '/', $file);
        !          65137:                     $data['data'][] = array($file, $dest);
        !          65138:                 }
        !          65139:             }
        !          65140:         } else { // package.xml 2.0, not installed
        !          65141:             if (!isset($list['dir']['file'][0])) {
        !          65142:                 $list['dir']['file'] = array($list['dir']['file']);
        !          65143:             }
        !          65144: 
        !          65145:             foreach ($list['dir']['file'] as $att) {
        !          65146:                 $att = $att['attribs'];
        !          65147:                 $file = $att['name'];
        !          65148:                 $role = &PEAR_Installer_Role::factory($info, $att['role'], $this->config);
        !          65149:                 $role->setup($this, $info, $att, $file);
        !          65150:                 if (!$role->isInstallable()) {
        !          65151:                     $dest = '(not installable)';
        !          65152:                 } else {
        !          65153:                     $dest = $role->processInstallation($info, $att, $file, '');
        !          65154:                     if (PEAR::isError($dest)) {
        !          65155:                         $dest = '(Unknown role "' . $att['role'] . ')';
        !          65156:                     } else {
        !          65157:                         list(,, $dest) = $dest;
        !          65158:                     }
        !          65159:                 }
        !          65160:                 $data['data'][] = array($file, $dest);
        !          65161:             }
        !          65162:         }
        !          65163: 
        !          65164:         $this->ui->outputData($data, $command);
        !          65165:         return true;
        !          65166:     }
        !          65167: 
        !          65168:     function doShellTest($command, $options, $params)
        !          65169:     {
        !          65170:         if (count($params) < 1) {
        !          65171:             return PEAR::raiseError('ERROR, usage: pear shell-test packagename [[relation] version]');
        !          65172:         }
        !          65173: 
        !          65174:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          65175:         $reg = &$this->config->getRegistry();
        !          65176:         $info = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
        !          65177:         if (PEAR::isError($info)) {
        !          65178:             exit(1); // invalid package name
        !          65179:         }
        !          65180: 
        !          65181:         $package = $info['package'];
        !          65182:         $channel = $info['channel'];
        !          65183:         // "pear shell-test Foo"
        !          65184:         if (!$reg->packageExists($package, $channel)) {
        !          65185:             if ($channel == 'pecl.php.net') {
        !          65186:                 if ($reg->packageExists($package, 'pear.php.net')) {
        !          65187:                     $channel = 'pear.php.net'; // magically change channels for extensions
        !          65188:                 }
        !          65189:             }
        !          65190:         }
        !          65191: 
        !          65192:         if (count($params) === 1) {
        !          65193:             if (!$reg->packageExists($package, $channel)) {
        !          65194:                 exit(1);
        !          65195:             }
        !          65196:             // "pear shell-test Foo 1.0"
        !          65197:         } elseif (count($params) === 2) {
        !          65198:             $v = $reg->packageInfo($package, 'version', $channel);
        !          65199:             if (!$v || !version_compare("$v", "{$params[1]}", "ge")) {
        !          65200:                 exit(1);
        !          65201:             }
        !          65202:             // "pear shell-test Foo ge 1.0"
        !          65203:         } elseif (count($params) === 3) {
        !          65204:             $v = $reg->packageInfo($package, 'version', $channel);
        !          65205:             if (!$v || !version_compare("$v", "{$params[2]}", $params[1])) {
        !          65206:                 exit(1);
        !          65207:             }
        !          65208:         } else {
        !          65209:             PEAR::staticPopErrorHandling();
        !          65210:             $this->raiseError("$command: expects 1 to 3 parameters");
        !          65211:             exit(1);
        !          65212:         }
        !          65213:     }
        !          65214: 
        !          65215:     function doInfo($command, $options, $params)
        !          65216:     {
        !          65217:         if (count($params) !== 1) {
        !          65218:             return $this->raiseError('pear info expects 1 parameter');
        !          65219:         }
        !          65220: 
        !          65221:         $info = $fp = false;
        !          65222:         $reg = &$this->config->getRegistry();
        !          65223:         if (is_file($params[0]) && !is_dir($params[0]) &&
        !          65224:             (file_exists($params[0]) || $fp = @fopen($params[0], 'r'))
        !          65225:         ) {
        !          65226:             if ($fp) {
        !          65227:                 fclose($fp);
        !          65228:             }
        !          65229: 
        !          65230:             if (!class_exists('PEAR_PackageFile')) {
        !          65231:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile.php';
        !          65232:             }
        !          65233: 
        !          65234:             $pkg = &new PEAR_PackageFile($this->config, $this->_debug);
        !          65235:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          65236:             $obj = &$pkg->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
        !          65237:             PEAR::staticPopErrorHandling();
        !          65238:             if (PEAR::isError($obj)) {
        !          65239:                 $uinfo = $obj->getUserInfo();
        !          65240:                 if (is_array($uinfo)) {
        !          65241:                     foreach ($uinfo as $message) {
        !          65242:                         if (is_array($message)) {
        !          65243:                             $message = $message['message'];
        !          65244:                         }
        !          65245:                         $this->ui->outputData($message);
        !          65246:                     }
        !          65247:                 }
        !          65248: 
        !          65249:                 return $this->raiseError($obj);
        !          65250:             }
        !          65251: 
        !          65252:             if ($obj->getPackagexmlVersion() != '1.0') {
        !          65253:                 return $this->_doInfo2($command, $options, $params, $obj, false);
        !          65254:             }
        !          65255: 
        !          65256:             $info = $obj->toArray();
        !          65257:         } else {
        !          65258:             $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
        !          65259:             if (PEAR::isError($parsed)) {
        !          65260:                 return $this->raiseError($parsed);
        !          65261:             }
        !          65262: 
        !          65263:             $package = $parsed['package'];
        !          65264:             $channel = $parsed['channel'];
        !          65265:             $info = $reg->packageInfo($package, null, $channel);
        !          65266:             if (isset($info['old'])) {
        !          65267:                 $obj = $reg->getPackage($package, $channel);
        !          65268:                 return $this->_doInfo2($command, $options, $params, $obj, true);
        !          65269:             }
        !          65270:         }
        !          65271: 
        !          65272:         if (PEAR::isError($info)) {
        !          65273:             return $info;
        !          65274:         }
        !          65275: 
        !          65276:         if (empty($info)) {
        !          65277:             $this->raiseError("No information found for `$params[0]'");
        !          65278:             return;
        !          65279:         }
        !          65280: 
        !          65281:         unset($info['filelist']);
        !          65282:         unset($info['dirtree']);
        !          65283:         unset($info['changelog']);
        !          65284:         if (isset($info['xsdversion'])) {
        !          65285:             $info['package.xml version'] = $info['xsdversion'];
        !          65286:             unset($info['xsdversion']);
        !          65287:         }
        !          65288: 
        !          65289:         if (isset($info['packagerversion'])) {
        !          65290:             $info['packaged with PEAR version'] = $info['packagerversion'];
        !          65291:             unset($info['packagerversion']);
        !          65292:         }
        !          65293: 
        !          65294:         $keys = array_keys($info);
        !          65295:         $longtext = array('description', 'summary');
        !          65296:         foreach ($keys as $key) {
        !          65297:             if (is_array($info[$key])) {
        !          65298:                 switch ($key) {
        !          65299:                     case 'maintainers': {
        !          65300:                         $i = 0;
        !          65301:                         $mstr = '';
        !          65302:                         foreach ($info[$key] as $m) {
        !          65303:                             if ($i++ > 0) {
        !          65304:                                 $mstr .= "\n";
        !          65305:                             }
        !          65306:                             $mstr .= $m['name'] . " <";
        !          65307:                             if (isset($m['email'])) {
        !          65308:                                 $mstr .= $m['email'];
        !          65309:                             } else {
        !          65310:                                 $mstr .= $m['handle'] . '@php.net';
        !          65311:                             }
        !          65312:                             $mstr .= "> ($m[role])";
        !          65313:                         }
        !          65314:                         $info[$key] = $mstr;
        !          65315:                         break;
        !          65316:                     }
        !          65317:                     case 'release_deps': {
        !          65318:                         $i = 0;
        !          65319:                         $dstr = '';
        !          65320:                         foreach ($info[$key] as $d) {
        !          65321:                             if (isset($this->_deps_rel_trans[$d['rel']])) {
        !          65322:                                 $rel = $this->_deps_rel_trans[$d['rel']];
        !          65323:                             } else {
        !          65324:                                 $rel = $d['rel'];
        !          65325:                             }
        !          65326:                             if (isset($this->_deps_type_trans[$d['type']])) {
        !          65327:                                 $type = ucfirst($this->_deps_type_trans[$d['type']]);
        !          65328:                             } else {
        !          65329:                                 $type = $d['type'];
        !          65330:                             }
        !          65331:                             if (isset($d['name'])) {
        !          65332:                                 $name = $d['name'] . ' ';
        !          65333:                             } else {
        !          65334:                                 $name = '';
        !          65335:                             }
        !          65336:                             if (isset($d['version'])) {
        !          65337:                                 $version = $d['version'] . ' ';
        !          65338:                             } else {
        !          65339:                                 $version = '';
        !          65340:                             }
        !          65341:                             if (isset($d['optional']) && $d['optional'] == 'yes') {
        !          65342:                                 $optional = ' (optional)';
        !          65343:                             } else {
        !          65344:                                 $optional = '';
        !          65345:                             }
        !          65346:                             $dstr .= "$type $name$rel $version$optional\n";
        !          65347:                         }
        !          65348:                         $info[$key] = $dstr;
        !          65349:                         break;
        !          65350:                     }
        !          65351:                     case 'provides' : {
        !          65352:                         $debug = $this->config->get('verbose');
        !          65353:                         if ($debug < 2) {
        !          65354:                             $pstr = 'Classes: ';
        !          65355:                         } else {
        !          65356:                             $pstr = '';
        !          65357:                         }
        !          65358:                         $i = 0;
        !          65359:                         foreach ($info[$key] as $p) {
        !          65360:                             if ($debug < 2 && $p['type'] != "class") {
        !          65361:                                 continue;
        !          65362:                             }
        !          65363:                             // Only print classes when verbosity mode is < 2
        !          65364:                             if ($debug < 2) {
        !          65365:                                 if ($i++ > 0) {
        !          65366:                                     $pstr .= ", ";
        !          65367:                                 }
        !          65368:                                 $pstr .= $p['name'];
        !          65369:                             } else {
        !          65370:                                 if ($i++ > 0) {
        !          65371:                                     $pstr .= "\n";
        !          65372:                                 }
        !          65373:                                 $pstr .= ucfirst($p['type']) . " " . $p['name'];
        !          65374:                                 if (isset($p['explicit']) && $p['explicit'] == 1) {
        !          65375:                                     $pstr .= " (explicit)";
        !          65376:                                 }
        !          65377:                             }
        !          65378:                         }
        !          65379:                         $info[$key] = $pstr;
        !          65380:                         break;
        !          65381:                     }
        !          65382:                     case 'configure_options' : {
        !          65383:                         foreach ($info[$key] as $i => $p) {
        !          65384:                             $info[$key][$i] = array_map(null, array_keys($p), array_values($p));
        !          65385:                             $info[$key][$i] = array_map(create_function('$a',
        !          65386:                                 'return join(" = ",$a);'), $info[$key][$i]);
        !          65387:                             $info[$key][$i] = implode(', ', $info[$key][$i]);
        !          65388:                         }
        !          65389:                         $info[$key] = implode("\n", $info[$key]);
        !          65390:                         break;
        !          65391:                     }
        !          65392:                     default: {
        !          65393:                         $info[$key] = implode(", ", $info[$key]);
        !          65394:                         break;
        !          65395:                     }
        !          65396:                 }
        !          65397:             }
        !          65398: 
        !          65399:             if ($key == '_lastmodified') {
        !          65400:                 $hdate = date('Y-m-d', $info[$key]);
        !          65401:                 unset($info[$key]);
        !          65402:                 $info['Last Modified'] = $hdate;
        !          65403:             } elseif ($key == '_lastversion') {
        !          65404:                 $info['Previous Installed Version'] = $info[$key] ? $info[$key] : '- None -';
        !          65405:                 unset($info[$key]);
        !          65406:             } else {
        !          65407:                 $info[$key] = trim($info[$key]);
        !          65408:                 if (in_array($key, $longtext)) {
        !          65409:                     $info[$key] = preg_replace('/  +/', ' ', $info[$key]);
        !          65410:                 }
        !          65411:             }
        !          65412:         }
        !          65413: 
        !          65414:         $caption = 'About ' . $info['package'] . '-' . $info['version'];
        !          65415:         $data = array(
        !          65416:             'caption' => $caption,
        !          65417:             'border' => true);
        !          65418:         foreach ($info as $key => $value) {
        !          65419:             $key = ucwords(trim(str_replace('_', ' ', $key)));
        !          65420:             $data['data'][] = array($key, $value);
        !          65421:         }
        !          65422:         $data['raw'] = $info;
        !          65423: 
        !          65424:         $this->ui->outputData($data, 'package-info');
        !          65425:     }
        !          65426: 
        !          65427:     /**
        !          65428:      * @access private
        !          65429:      */
        !          65430:     function _doInfo2($command, $options, $params, &$obj, $installed)
        !          65431:     {
        !          65432:         $reg = &$this->config->getRegistry();
        !          65433:         $caption = 'About ' . $obj->getChannel() . '/' .$obj->getPackage() . '-' .
        !          65434:             $obj->getVersion();
        !          65435:         $data = array(
        !          65436:             'caption' => $caption,
        !          65437:             'border' => true);
        !          65438:         switch ($obj->getPackageType()) {
        !          65439:             case 'php' :
        !          65440:                 $release = 'PEAR-style PHP-based Package';
        !          65441:             break;
        !          65442:             case 'extsrc' :
        !          65443:                 $release = 'PECL-style PHP extension (source code)';
        !          65444:             break;
        !          65445:             case 'zendextsrc' :
        !          65446:                 $release = 'PECL-style Zend extension (source code)';
        !          65447:             break;
        !          65448:             case 'extbin' :
        !          65449:                 $release = 'PECL-style PHP extension (binary)';
        !          65450:             break;
        !          65451:             case 'zendextbin' :
        !          65452:                 $release = 'PECL-style Zend extension (binary)';
        !          65453:             break;
        !          65454:             case 'bundle' :
        !          65455:                 $release = 'Package bundle (collection of packages)';
        !          65456:             break;
        !          65457:         }
        !          65458:         $extends = $obj->getExtends();
        !          65459:         $extends = $extends ?
        !          65460:             $obj->getPackage() . ' (extends ' . $extends . ')' : $obj->getPackage();
        !          65461:         if ($src = $obj->getSourcePackage()) {
        !          65462:             $extends .= ' (source package ' . $src['channel'] . '/' . $src['package'] . ')';
        !          65463:         }
        !          65464: 
        !          65465:         $info = array(
        !          65466:             'Release Type' => $release,
        !          65467:             'Name' => $extends,
        !          65468:             'Channel' => $obj->getChannel(),
        !          65469:             'Summary' => preg_replace('/  +/', ' ', $obj->getSummary()),
        !          65470:             'Description' => preg_replace('/  +/', ' ', $obj->getDescription()),
        !          65471:             );
        !          65472:         $info['Maintainers'] = '';
        !          65473:         foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
        !          65474:             $leads = $obj->{"get{$role}s"}();
        !          65475:             if (!$leads) {
        !          65476:                 continue;
        !          65477:             }
        !          65478: 
        !          65479:             if (isset($leads['active'])) {
        !          65480:                 $leads = array($leads);
        !          65481:             }
        !          65482: 
        !          65483:             foreach ($leads as $lead) {
        !          65484:                 if (!empty($info['Maintainers'])) {
        !          65485:                     $info['Maintainers'] .= "\n";
        !          65486:                 }
        !          65487: 
        !          65488:                 $active = $lead['active'] == 'no' ? ', inactive' : '';
        !          65489:                 $info['Maintainers'] .= $lead['name'] . ' <';
        !          65490:                 $info['Maintainers'] .= $lead['email'] . "> ($role$active)";
        !          65491:             }
        !          65492:         }
        !          65493: 
        !          65494:         $info['Release Date'] = $obj->getDate();
        !          65495:         if ($time = $obj->getTime()) {
        !          65496:             $info['Release Date'] .= ' ' . $time;
        !          65497:         }
        !          65498: 
        !          65499:         $info['Release Version'] = $obj->getVersion() . ' (' . $obj->getState() . ')';
        !          65500:         $info['API Version'] = $obj->getVersion('api') . ' (' . $obj->getState('api') . ')';
        !          65501:         $info['License'] = $obj->getLicense();
        !          65502:         $uri = $obj->getLicenseLocation();
        !          65503:         if ($uri) {
        !          65504:             if (isset($uri['uri'])) {
        !          65505:                 $info['License'] .= ' (' . $uri['uri'] . ')';
        !          65506:             } else {
        !          65507:                 $extra = $obj->getInstalledLocation($info['filesource']);
        !          65508:                 if ($extra) {
        !          65509:                     $info['License'] .= ' (' . $uri['filesource'] . ')';
        !          65510:                 }
        !          65511:             }
        !          65512:         }
        !          65513: 
        !          65514:         $info['Release Notes'] = $obj->getNotes();
        !          65515:         if ($compat = $obj->getCompatible()) {
        !          65516:             if (!isset($compat[0])) {
        !          65517:                 $compat = array($compat);
        !          65518:             }
        !          65519: 
        !          65520:             $info['Compatible with'] = '';
        !          65521:             foreach ($compat as $package) {
        !          65522:                 $info['Compatible with'] .= $package['channel'] . '/' . $package['name'] .
        !          65523:                     "\nVersions >= " . $package['min'] . ', <= ' . $package['max'];
        !          65524:                 if (isset($package['exclude'])) {
        !          65525:                     if (is_array($package['exclude'])) {
        !          65526:                         $package['exclude'] = implode(', ', $package['exclude']);
        !          65527:                     }
        !          65528: 
        !          65529:                     if (!isset($info['Not Compatible with'])) {
        !          65530:                         $info['Not Compatible with'] = '';
        !          65531:                     } else {
        !          65532:                         $info['Not Compatible with'] .= "\n";
        !          65533:                     }
        !          65534:                     $info['Not Compatible with'] .= $package['channel'] . '/' .
        !          65535:                         $package['name'] . "\nVersions " . $package['exclude'];
        !          65536:                 }
        !          65537:             }
        !          65538:         }
        !          65539: 
        !          65540:         $usesrole = $obj->getUsesrole();
        !          65541:         if ($usesrole) {
        !          65542:             if (!isset($usesrole[0])) {
        !          65543:                 $usesrole = array($usesrole);
        !          65544:             }
        !          65545: 
        !          65546:             foreach ($usesrole as $roledata) {
        !          65547:                 if (isset($info['Uses Custom Roles'])) {
        !          65548:                     $info['Uses Custom Roles'] .= "\n";
        !          65549:                 } else {
        !          65550:                     $info['Uses Custom Roles'] = '';
        !          65551:                 }
        !          65552: 
        !          65553:                 if (isset($roledata['package'])) {
        !          65554:                     $rolepackage = $reg->parsedPackageNameToString($roledata, true);
        !          65555:                 } else {
        !          65556:                     $rolepackage = $roledata['uri'];
        !          65557:                 }
        !          65558:                 $info['Uses Custom Roles'] .= $roledata['role'] . ' (' . $rolepackage . ')';
        !          65559:             }
        !          65560:         }
        !          65561: 
        !          65562:         $usestask = $obj->getUsestask();
        !          65563:         if ($usestask) {
        !          65564:             if (!isset($usestask[0])) {
        !          65565:                 $usestask = array($usestask);
        !          65566:             }
        !          65567: 
        !          65568:             foreach ($usestask as $taskdata) {
        !          65569:                 if (isset($info['Uses Custom Tasks'])) {
        !          65570:                     $info['Uses Custom Tasks'] .= "\n";
        !          65571:                 } else {
        !          65572:                     $info['Uses Custom Tasks'] = '';
        !          65573:                 }
        !          65574: 
        !          65575:                 if (isset($taskdata['package'])) {
        !          65576:                     $taskpackage = $reg->parsedPackageNameToString($taskdata, true);
        !          65577:                 } else {
        !          65578:                     $taskpackage = $taskdata['uri'];
        !          65579:                 }
        !          65580:                 $info['Uses Custom Tasks'] .= $taskdata['task'] . ' (' . $taskpackage . ')';
        !          65581:             }
        !          65582:         }
        !          65583: 
        !          65584:         $deps = $obj->getDependencies();
        !          65585:         $info['Required Dependencies'] = 'PHP version ' . $deps['required']['php']['min'];
        !          65586:         if (isset($deps['required']['php']['max'])) {
        !          65587:             $info['Required Dependencies'] .= '-' . $deps['required']['php']['max'] . "\n";
        !          65588:         } else {
        !          65589:             $info['Required Dependencies'] .= "\n";
        !          65590:         }
        !          65591: 
        !          65592:         if (isset($deps['required']['php']['exclude'])) {
        !          65593:             if (!isset($info['Not Compatible with'])) {
        !          65594:                 $info['Not Compatible with'] = '';
        !          65595:             } else {
        !          65596:                 $info['Not Compatible with'] .= "\n";
        !          65597:             }
        !          65598: 
        !          65599:             if (is_array($deps['required']['php']['exclude'])) {
        !          65600:                 $deps['required']['php']['exclude'] =
        !          65601:                     implode(', ', $deps['required']['php']['exclude']);
        !          65602:             }
        !          65603:             $info['Not Compatible with'] .= "PHP versions\n  " .
        !          65604:                 $deps['required']['php']['exclude'];
        !          65605:         }
        !          65606: 
        !          65607:         $info['Required Dependencies'] .= 'PEAR installer version';
        !          65608:         if (isset($deps['required']['pearinstaller']['max'])) {
        !          65609:             $info['Required Dependencies'] .= 's ' .
        !          65610:                 $deps['required']['pearinstaller']['min'] . '-' .
        !          65611:                 $deps['required']['pearinstaller']['max'];
        !          65612:         } else {
        !          65613:             $info['Required Dependencies'] .= ' ' .
        !          65614:                 $deps['required']['pearinstaller']['min'] . ' or newer';
        !          65615:         }
        !          65616: 
        !          65617:         if (isset($deps['required']['pearinstaller']['exclude'])) {
        !          65618:             if (!isset($info['Not Compatible with'])) {
        !          65619:                 $info['Not Compatible with'] = '';
        !          65620:             } else {
        !          65621:                 $info['Not Compatible with'] .= "\n";
        !          65622:             }
        !          65623: 
        !          65624:             if (is_array($deps['required']['pearinstaller']['exclude'])) {
        !          65625:                 $deps['required']['pearinstaller']['exclude'] =
        !          65626:                     implode(', ', $deps['required']['pearinstaller']['exclude']);
        !          65627:             }
        !          65628:             $info['Not Compatible with'] .= "PEAR installer\n  Versions " .
        !          65629:                 $deps['required']['pearinstaller']['exclude'];
        !          65630:         }
        !          65631: 
        !          65632:         foreach (array('Package', 'Extension') as $type) {
        !          65633:             $index = strtolower($type);
        !          65634:             if (isset($deps['required'][$index])) {
        !          65635:                 if (isset($deps['required'][$index]['name'])) {
        !          65636:                     $deps['required'][$index] = array($deps['required'][$index]);
        !          65637:                 }
        !          65638: 
        !          65639:                 foreach ($deps['required'][$index] as $package) {
        !          65640:                     if (isset($package['conflicts'])) {
        !          65641:                         $infoindex = 'Not Compatible with';
        !          65642:                         if (!isset($info['Not Compatible with'])) {
        !          65643:                             $info['Not Compatible with'] = '';
        !          65644:                         } else {
        !          65645:                             $info['Not Compatible with'] .= "\n";
        !          65646:                         }
        !          65647:                     } else {
        !          65648:                         $infoindex = 'Required Dependencies';
        !          65649:                         $info[$infoindex] .= "\n";
        !          65650:                     }
        !          65651: 
        !          65652:                     if ($index == 'extension') {
        !          65653:                         $name = $package['name'];
        !          65654:                     } else {
        !          65655:                         if (isset($package['channel'])) {
        !          65656:                             $name = $package['channel'] . '/' . $package['name'];
        !          65657:                         } else {
        !          65658:                             $name = '__uri/' . $package['name'] . ' (static URI)';
        !          65659:                         }
        !          65660:                     }
        !          65661: 
        !          65662:                     $info[$infoindex] .= "$type $name";
        !          65663:                     if (isset($package['uri'])) {
        !          65664:                         $info[$infoindex] .= "\n  Download URI: $package[uri]";
        !          65665:                         continue;
        !          65666:                     }
        !          65667: 
        !          65668:                     if (isset($package['max']) && isset($package['min'])) {
        !          65669:                         $info[$infoindex] .= " \n  Versions " .
        !          65670:                             $package['min'] . '-' . $package['max'];
        !          65671:                     } elseif (isset($package['min'])) {
        !          65672:                         $info[$infoindex] .= " \n  Version " .
        !          65673:                             $package['min'] . ' or newer';
        !          65674:                     } elseif (isset($package['max'])) {
        !          65675:                         $info[$infoindex] .= " \n  Version " .
        !          65676:                             $package['max'] . ' or older';
        !          65677:                     }
        !          65678: 
        !          65679:                     if (isset($package['recommended'])) {
        !          65680:                         $info[$infoindex] .= "\n  Recommended version: $package[recommended]";
        !          65681:                     }
        !          65682: 
        !          65683:                     if (isset($package['exclude'])) {
        !          65684:                         if (!isset($info['Not Compatible with'])) {
        !          65685:                             $info['Not Compatible with'] = '';
        !          65686:                         } else {
        !          65687:                             $info['Not Compatible with'] .= "\n";
        !          65688:                         }
        !          65689: 
        !          65690:                         if (is_array($package['exclude'])) {
        !          65691:                             $package['exclude'] = implode(', ', $package['exclude']);
        !          65692:                         }
        !          65693: 
        !          65694:                         $package['package'] = $package['name']; // for parsedPackageNameToString
        !          65695:                          if (isset($package['conflicts'])) {
        !          65696:                             $info['Not Compatible with'] .= '=> except ';
        !          65697:                         }
        !          65698:                        $info['Not Compatible with'] .= 'Package ' .
        !          65699:                             $reg->parsedPackageNameToString($package, true);
        !          65700:                         $info['Not Compatible with'] .= "\n  Versions " . $package['exclude'];
        !          65701:                     }
        !          65702:                 }
        !          65703:             }
        !          65704:         }
        !          65705: 
        !          65706:         if (isset($deps['required']['os'])) {
        !          65707:             if (isset($deps['required']['os']['name'])) {
        !          65708:                 $dep['required']['os']['name'] = array($dep['required']['os']['name']);
        !          65709:             }
        !          65710: 
        !          65711:             foreach ($dep['required']['os'] as $os) {
        !          65712:                 if (isset($os['conflicts']) && $os['conflicts'] == 'yes') {
        !          65713:                     if (!isset($info['Not Compatible with'])) {
        !          65714:                         $info['Not Compatible with'] = '';
        !          65715:                     } else {
        !          65716:                         $info['Not Compatible with'] .= "\n";
        !          65717:                     }
        !          65718:                     $info['Not Compatible with'] .= "$os[name] Operating System";
        !          65719:                 } else {
        !          65720:                     $info['Required Dependencies'] .= "\n";
        !          65721:                     $info['Required Dependencies'] .= "$os[name] Operating System";
        !          65722:                 }
        !          65723:             }
        !          65724:         }
        !          65725: 
        !          65726:         if (isset($deps['required']['arch'])) {
        !          65727:             if (isset($deps['required']['arch']['pattern'])) {
        !          65728:                 $dep['required']['arch']['pattern'] = array($dep['required']['os']['pattern']);
        !          65729:             }
        !          65730: 
        !          65731:             foreach ($dep['required']['arch'] as $os) {
        !          65732:                 if (isset($os['conflicts']) && $os['conflicts'] == 'yes') {
        !          65733:                     if (!isset($info['Not Compatible with'])) {
        !          65734:                         $info['Not Compatible with'] = '';
        !          65735:                     } else {
        !          65736:                         $info['Not Compatible with'] .= "\n";
        !          65737:                     }
        !          65738:                     $info['Not Compatible with'] .= "OS/Arch matching pattern '/$os[pattern]/'";
        !          65739:                 } else {
        !          65740:                     $info['Required Dependencies'] .= "\n";
        !          65741:                     $info['Required Dependencies'] .= "OS/Arch matching pattern '/$os[pattern]/'";
        !          65742:                 }
        !          65743:             }
        !          65744:         }
        !          65745: 
        !          65746:         if (isset($deps['optional'])) {
        !          65747:             foreach (array('Package', 'Extension') as $type) {
        !          65748:                 $index = strtolower($type);
        !          65749:                 if (isset($deps['optional'][$index])) {
        !          65750:                     if (isset($deps['optional'][$index]['name'])) {
        !          65751:                         $deps['optional'][$index] = array($deps['optional'][$index]);
        !          65752:                     }
        !          65753: 
        !          65754:                     foreach ($deps['optional'][$index] as $package) {
        !          65755:                         if (isset($package['conflicts']) && $package['conflicts'] == 'yes') {
        !          65756:                             $infoindex = 'Not Compatible with';
        !          65757:                             if (!isset($info['Not Compatible with'])) {
        !          65758:                                 $info['Not Compatible with'] = '';
        !          65759:                             } else {
        !          65760:                                 $info['Not Compatible with'] .= "\n";
        !          65761:                             }
        !          65762:                         } else {
        !          65763:                             $infoindex = 'Optional Dependencies';
        !          65764:                             if (!isset($info['Optional Dependencies'])) {
        !          65765:                                 $info['Optional Dependencies'] = '';
        !          65766:                             } else {
        !          65767:                                 $info['Optional Dependencies'] .= "\n";
        !          65768:                             }
        !          65769:                         }
        !          65770: 
        !          65771:                         if ($index == 'extension') {
        !          65772:                             $name = $package['name'];
        !          65773:                         } else {
        !          65774:                             if (isset($package['channel'])) {
        !          65775:                                 $name = $package['channel'] . '/' . $package['name'];
        !          65776:                             } else {
        !          65777:                                 $name = '__uri/' . $package['name'] . ' (static URI)';
        !          65778:                             }
        !          65779:                         }
        !          65780: 
        !          65781:                         $info[$infoindex] .= "$type $name";
        !          65782:                         if (isset($package['uri'])) {
        !          65783:                             $info[$infoindex] .= "\n  Download URI: $package[uri]";
        !          65784:                             continue;
        !          65785:                         }
        !          65786: 
        !          65787:                         if ($infoindex == 'Not Compatible with') {
        !          65788:                             // conflicts is only used to say that all versions conflict
        !          65789:                             continue;
        !          65790:                         }
        !          65791: 
        !          65792:                         if (isset($package['max']) && isset($package['min'])) {
        !          65793:                             $info[$infoindex] .= " \n  Versions " .
        !          65794:                                 $package['min'] . '-' . $package['max'];
        !          65795:                         } elseif (isset($package['min'])) {
        !          65796:                             $info[$infoindex] .= " \n  Version " .
        !          65797:                                 $package['min'] . ' or newer';
        !          65798:                         } elseif (isset($package['max'])) {
        !          65799:                             $info[$infoindex] .= " \n  Version " .
        !          65800:                                 $package['min'] . ' or older';
        !          65801:                         }
        !          65802: 
        !          65803:                         if (isset($package['recommended'])) {
        !          65804:                             $info[$infoindex] .= "\n  Recommended version: $package[recommended]";
        !          65805:                         }
        !          65806: 
        !          65807:                         if (isset($package['exclude'])) {
        !          65808:                             if (!isset($info['Not Compatible with'])) {
        !          65809:                                 $info['Not Compatible with'] = '';
        !          65810:                             } else {
        !          65811:                                 $info['Not Compatible with'] .= "\n";
        !          65812:                             }
        !          65813: 
        !          65814:                             if (is_array($package['exclude'])) {
        !          65815:                                 $package['exclude'] = implode(', ', $package['exclude']);
        !          65816:                             }
        !          65817: 
        !          65818:                             $info['Not Compatible with'] .= "Package $package\n  Versions " .
        !          65819:                                 $package['exclude'];
        !          65820:                         }
        !          65821:                     }
        !          65822:                 }
        !          65823:             }
        !          65824:         }
        !          65825: 
        !          65826:         if (isset($deps['group'])) {
        !          65827:             if (!isset($deps['group'][0])) {
        !          65828:                 $deps['group'] = array($deps['group']);
        !          65829:             }
        !          65830: 
        !          65831:             foreach ($deps['group'] as $group) {
        !          65832:                 $info['Dependency Group ' . $group['attribs']['name']] = $group['attribs']['hint'];
        !          65833:                 $groupindex = $group['attribs']['name'] . ' Contents';
        !          65834:                 $info[$groupindex] = '';
        !          65835:                 foreach (array('Package', 'Extension') as $type) {
        !          65836:                     $index = strtolower($type);
        !          65837:                     if (isset($group[$index])) {
        !          65838:                         if (isset($group[$index]['name'])) {
        !          65839:                             $group[$index] = array($group[$index]);
        !          65840:                         }
        !          65841: 
        !          65842:                         foreach ($group[$index] as $package) {
        !          65843:                             if (!empty($info[$groupindex])) {
        !          65844:                                 $info[$groupindex] .= "\n";
        !          65845:                             }
        !          65846: 
        !          65847:                             if ($index == 'extension') {
        !          65848:                                 $name = $package['name'];
        !          65849:                             } else {
        !          65850:                                 if (isset($package['channel'])) {
        !          65851:                                     $name = $package['channel'] . '/' . $package['name'];
        !          65852:                                 } else {
        !          65853:                                     $name = '__uri/' . $package['name'] . ' (static URI)';
        !          65854:                                 }
        !          65855:                             }
        !          65856: 
        !          65857:                             if (isset($package['uri'])) {
        !          65858:                                 if (isset($package['conflicts']) && $package['conflicts'] == 'yes') {
        !          65859:                                     $info[$groupindex] .= "Not Compatible with $type $name";
        !          65860:                                 } else {
        !          65861:                                     $info[$groupindex] .= "$type $name";
        !          65862:                                 }
        !          65863: 
        !          65864:                                 $info[$groupindex] .= "\n  Download URI: $package[uri]";
        !          65865:                                 continue;
        !          65866:                             }
        !          65867: 
        !          65868:                             if (isset($package['conflicts']) && $package['conflicts'] == 'yes') {
        !          65869:                                 $info[$groupindex] .= "Not Compatible with $type $name";
        !          65870:                                 continue;
        !          65871:                             }
        !          65872: 
        !          65873:                             $info[$groupindex] .= "$type $name";
        !          65874:                             if (isset($package['max']) && isset($package['min'])) {
        !          65875:                                 $info[$groupindex] .= " \n  Versions " .
        !          65876:                                     $package['min'] . '-' . $package['max'];
        !          65877:                             } elseif (isset($package['min'])) {
        !          65878:                                 $info[$groupindex] .= " \n  Version " .
        !          65879:                                     $package['min'] . ' or newer';
        !          65880:                             } elseif (isset($package['max'])) {
        !          65881:                                 $info[$groupindex] .= " \n  Version " .
        !          65882:                                     $package['min'] . ' or older';
        !          65883:                             }
        !          65884: 
        !          65885:                             if (isset($package['recommended'])) {
        !          65886:                                 $info[$groupindex] .= "\n  Recommended version: $package[recommended]";
        !          65887:                             }
        !          65888: 
        !          65889:                             if (isset($package['exclude'])) {
        !          65890:                                 if (!isset($info['Not Compatible with'])) {
        !          65891:                                     $info['Not Compatible with'] = '';
        !          65892:                                 } else {
        !          65893:                                     $info[$groupindex] .= "Not Compatible with\n";
        !          65894:                                 }
        !          65895: 
        !          65896:                                 if (is_array($package['exclude'])) {
        !          65897:                                     $package['exclude'] = implode(', ', $package['exclude']);
        !          65898:                                 }
        !          65899:                                 $info[$groupindex] .= "  Package $package\n  Versions " .
        !          65900:                                     $package['exclude'];
        !          65901:                             }
        !          65902:                         }
        !          65903:                     }
        !          65904:                 }
        !          65905:             }
        !          65906:         }
        !          65907: 
        !          65908:         if ($obj->getPackageType() == 'bundle') {
        !          65909:             $info['Bundled Packages'] = '';
        !          65910:             foreach ($obj->getBundledPackages() as $package) {
        !          65911:                 if (!empty($info['Bundled Packages'])) {
        !          65912:                     $info['Bundled Packages'] .= "\n";
        !          65913:                 }
        !          65914: 
        !          65915:                 if (isset($package['uri'])) {
        !          65916:                     $info['Bundled Packages'] .= '__uri/' . $package['name'];
        !          65917:                     $info['Bundled Packages'] .= "\n  (URI: $package[uri]";
        !          65918:                 } else {
        !          65919:                     $info['Bundled Packages'] .= $package['channel'] . '/' . $package['name'];
        !          65920:                 }
        !          65921:             }
        !          65922:         }
        !          65923: 
        !          65924:         $info['package.xml version'] = '2.0';
        !          65925:         if ($installed) {
        !          65926:             if ($obj->getLastModified()) {
        !          65927:                 $info['Last Modified'] = date('Y-m-d H:i', $obj->getLastModified());
        !          65928:             }
        !          65929: 
        !          65930:             $v = $obj->getLastInstalledVersion();
        !          65931:             $info['Previous Installed Version'] = $v ? $v : '- None -';
        !          65932:         }
        !          65933: 
        !          65934:         foreach ($info as $key => $value) {
        !          65935:             $data['data'][] = array($key, $value);
        !          65936:         }
        !          65937: 
        !          65938:         $data['raw'] = $obj->getArray(); // no validation needed
        !          65939:         $this->ui->outputData($data, 'package-info');
        !          65940:     }
        !          65941: }<commands version="1.0">
        !          65942:  <list>
        !          65943:   <summary>List Installed Packages In The Default Channel</summary>
        !          65944:   <function>doList</function>
        !          65945:   <shortcut>l</shortcut>
        !          65946:   <options>
        !          65947:    <channel>
        !          65948:     <shortopt>c</shortopt>
        !          65949:     <doc>list installed packages from this channel</doc>
        !          65950:     <arg>CHAN</arg>
        !          65951:    </channel>
        !          65952:    <allchannels>
        !          65953:     <shortopt>a</shortopt>
        !          65954:     <doc>list installed packages from all channels</doc>
        !          65955:    </allchannels>
        !          65956:    <channelinfo>
        !          65957:     <shortopt>i</shortopt>
        !          65958:     <doc>output fully channel-aware data, even on failure</doc>
        !          65959:    </channelinfo>
        !          65960:   </options>
        !          65961:   <doc>&lt;package&gt;
        !          65962: If invoked without parameters, this command lists the PEAR packages
        !          65963: installed in your php_dir ({config php_dir}).  With a parameter, it
        !          65964: lists the files in a package.
        !          65965: </doc>
        !          65966:  </list>
        !          65967:  <list-files>
        !          65968:   <summary>List Files In Installed Package</summary>
        !          65969:   <function>doFileList</function>
        !          65970:   <shortcut>fl</shortcut>
        !          65971:   <options />
        !          65972:   <doc>&lt;package&gt;
        !          65973: List the files in an installed package.
        !          65974: </doc>
        !          65975:  </list-files>
        !          65976:  <shell-test>
        !          65977:   <summary>Shell Script Test</summary>
        !          65978:   <function>doShellTest</function>
        !          65979:   <shortcut>st</shortcut>
        !          65980:   <options />
        !          65981:   <doc>&lt;package&gt; [[relation] version]
        !          65982: Tests if a package is installed in the system. Will exit(1) if it is not.
        !          65983:    &lt;relation&gt;   The version comparison operator. One of:
        !          65984:                 &lt;, lt, &lt;=, le, &gt;, gt, &gt;=, ge, ==, =, eq, !=, &lt;&gt;, ne
        !          65985:    &lt;version&gt;    The version to compare with
        !          65986: </doc>
        !          65987:  </shell-test>
        !          65988:  <info>
        !          65989:   <summary>Display information about a package</summary>
        !          65990:   <function>doInfo</function>
        !          65991:   <shortcut>in</shortcut>
        !          65992:   <options />
        !          65993:   <doc>&lt;package&gt;
        !          65994: Displays information about a package. The package argument may be a
        !          65995: local package file, an URL to a package file, or the name of an
        !          65996: installed package.</doc>
        !          65997:  </info>
        !          65998: </commands><?php
        !          65999: /**
        !          66000:  * PEAR_Command_Remote (remote-info, list-upgrades, remote-list, search, list-all, download,
        !          66001:  * clear-cache commands)
        !          66002:  *
        !          66003:  * PHP versions 4 and 5
        !          66004:  *
        !          66005:  * @category   pear
        !          66006:  * @package    PEAR
        !          66007:  * @author     Stig Bakken <ssb@php.net>
        !          66008:  * @author     Greg Beaver <cellog@php.net>
        !          66009:  * @copyright  1997-2009 The Authors
        !          66010:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          66011:  * @version    CVS: $Id: Remote.php 313023 2011-07-06 19:17:11Z dufuz $
        !          66012:  * @link       http://pear.php.net/package/PEAR
        !          66013:  * @since      File available since Release 0.1
        !          66014:  */
        !          66015: 
        !          66016: /**
        !          66017:  * base class
        !          66018:  */
        !          66019: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Common.php';
        !          66020: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/REST.php';
        !          66021: 
        !          66022: /**
        !          66023:  * PEAR commands for remote server querying
        !          66024:  *
        !          66025:  * @category   pear
        !          66026:  * @package    PEAR
        !          66027:  * @author     Stig Bakken <ssb@php.net>
        !          66028:  * @author     Greg Beaver <cellog@php.net>
        !          66029:  * @copyright  1997-2009 The Authors
        !          66030:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          66031:  * @version    Release: 1.9.4
        !          66032:  * @link       http://pear.php.net/package/PEAR
        !          66033:  * @since      Class available since Release 0.1
        !          66034:  */
        !          66035: class PEAR_Command_Remote extends PEAR_Command_Common
        !          66036: {
        !          66037:     var $commands = array(
        !          66038:         'remote-info' => array(
        !          66039:             'summary' => 'Information About Remote Packages',
        !          66040:             'function' => 'doRemoteInfo',
        !          66041:             'shortcut' => 'ri',
        !          66042:             'options' => array(),
        !          66043:             'doc' => '<package>
        !          66044: Get details on a package from the server.',
        !          66045:             ),
        !          66046:         'list-upgrades' => array(
        !          66047:             'summary' => 'List Available Upgrades',
        !          66048:             'function' => 'doListUpgrades',
        !          66049:             'shortcut' => 'lu',
        !          66050:             'options' => array(
        !          66051:                 'channelinfo' => array(
        !          66052:                     'shortopt' => 'i',
        !          66053:                     'doc' => 'output fully channel-aware data, even on failure',
        !          66054:                     ),
        !          66055:             ),
        !          66056:             'doc' => '[preferred_state]
        !          66057: List releases on the server of packages you have installed where
        !          66058: a newer version is available with the same release state (stable etc.)
        !          66059: or the state passed as the second parameter.'
        !          66060:             ),
        !          66061:         'remote-list' => array(
        !          66062:             'summary' => 'List Remote Packages',
        !          66063:             'function' => 'doRemoteList',
        !          66064:             'shortcut' => 'rl',
        !          66065:             'options' => array(
        !          66066:                 'channel' =>
        !          66067:                     array(
        !          66068:                     'shortopt' => 'c',
        !          66069:                     'doc' => 'specify a channel other than the default channel',
        !          66070:                     'arg' => 'CHAN',
        !          66071:                     )
        !          66072:                 ),
        !          66073:             'doc' => '
        !          66074: Lists the packages available on the configured server along with the
        !          66075: latest stable release of each package.',
        !          66076:             ),
        !          66077:         'search' => array(
        !          66078:             'summary' => 'Search remote package database',
        !          66079:             'function' => 'doSearch',
        !          66080:             'shortcut' => 'sp',
        !          66081:             'options' => array(
        !          66082:                 'channel' =>
        !          66083:                     array(
        !          66084:                     'shortopt' => 'c',
        !          66085:                     'doc' => 'specify a channel other than the default channel',
        !          66086:                     'arg' => 'CHAN',
        !          66087:                     ),
        !          66088:                 'allchannels' => array(
        !          66089:                     'shortopt' => 'a',
        !          66090:                     'doc' => 'search packages from all known channels',
        !          66091:                     ),
        !          66092:                 'channelinfo' => array(
        !          66093:                     'shortopt' => 'i',
        !          66094:                     'doc' => 'output fully channel-aware data, even on failure',
        !          66095:                     ),
        !          66096:                 ),
        !          66097:             'doc' => '[packagename] [packageinfo]
        !          66098: Lists all packages which match the search parameters.  The first
        !          66099: parameter is a fragment of a packagename.  The default channel
        !          66100: will be used unless explicitly overridden.  The second parameter
        !          66101: will be used to match any portion of the summary/description',
        !          66102:             ),
        !          66103:         'list-all' => array(
        !          66104:             'summary' => 'List All Packages',
        !          66105:             'function' => 'doListAll',
        !          66106:             'shortcut' => 'la',
        !          66107:             'options' => array(
        !          66108:                 'channel' =>
        !          66109:                     array(
        !          66110:                     'shortopt' => 'c',
        !          66111:                     'doc' => 'specify a channel other than the default channel',
        !          66112:                     'arg' => 'CHAN',
        !          66113:                     ),
        !          66114:                 'channelinfo' => array(
        !          66115:                     'shortopt' => 'i',
        !          66116:                     'doc' => 'output fully channel-aware data, even on failure',
        !          66117:                     ),
        !          66118:                 ),
        !          66119:             'doc' => '
        !          66120: Lists the packages available on the configured server along with the
        !          66121: latest stable release of each package.',
        !          66122:             ),
        !          66123:         'download' => array(
        !          66124:             'summary' => 'Download Package',
        !          66125:             'function' => 'doDownload',
        !          66126:             'shortcut' => 'd',
        !          66127:             'options' => array(
        !          66128:                 'nocompress' => array(
        !          66129:                     'shortopt' => 'Z',
        !          66130:                     'doc' => 'download an uncompressed (.tar) file',
        !          66131:                     ),
        !          66132:                 ),
        !          66133:             'doc' => '<package>...
        !          66134: Download package tarballs.  The files will be named as suggested by the
        !          66135: server, for example if you download the DB package and the latest stable
        !          66136: version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.',
        !          66137:             ),
        !          66138:         'clear-cache' => array(
        !          66139:             'summary' => 'Clear Web Services Cache',
        !          66140:             'function' => 'doClearCache',
        !          66141:             'shortcut' => 'cc',
        !          66142:             'options' => array(),
        !          66143:             'doc' => '
        !          66144: Clear the REST cache. See also the cache_ttl configuration
        !          66145: parameter.
        !          66146: ',
        !          66147:             ),
        !          66148:         );
        !          66149: 
        !          66150:     /**
        !          66151:      * PEAR_Command_Remote constructor.
        !          66152:      *
        !          66153:      * @access public
        !          66154:      */
        !          66155:     function PEAR_Command_Remote(&$ui, &$config)
        !          66156:     {
        !          66157:         parent::PEAR_Command_Common($ui, $config);
        !          66158:     }
        !          66159: 
        !          66160:     function _checkChannelForStatus($channel, $chan)
        !          66161:     {
        !          66162:         if (PEAR::isError($chan)) {
        !          66163:             $this->raiseError($chan);
        !          66164:         }
        !          66165:         if (!is_a($chan, 'PEAR_ChannelFile')) {
        !          66166:             return $this->raiseError('Internal corruption error: invalid channel "' .
        !          66167:                 $channel . '"');
        !          66168:         }
        !          66169:         $rest = new PEAR_REST($this->config);
        !          66170:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          66171:         $mirror = $this->config->get('preferred_mirror', null,
        !          66172:                                      $channel);
        !          66173:         $a = $rest->downloadHttp('http://' . $channel .
        !          66174:             '/channel.xml', $chan->lastModified());
        !          66175:         PEAR::staticPopErrorHandling();
        !          66176:         if (!PEAR::isError($a) && $a) {
        !          66177:             $this->ui->outputData('WARNING: channel "' . $channel . '" has ' .
        !          66178:                 'updated its protocols, use "' . PEAR_RUNTYPE . ' channel-update ' . $channel .
        !          66179:                 '" to update');
        !          66180:         }
        !          66181:     }
        !          66182: 
        !          66183:     function doRemoteInfo($command, $options, $params)
        !          66184:     {
        !          66185:         if (sizeof($params) != 1) {
        !          66186:             return $this->raiseError("$command expects one param: the remote package name");
        !          66187:         }
        !          66188:         $savechannel = $channel = $this->config->get('default_channel');
        !          66189:         $reg = &$this->config->getRegistry();
        !          66190:         $package = $params[0];
        !          66191:         $parsed = $reg->parsePackageName($package, $channel);
        !          66192:         if (PEAR::isError($parsed)) {
        !          66193:             return $this->raiseError('Invalid package name "' . $package . '"');
        !          66194:         }
        !          66195: 
        !          66196:         $channel = $parsed['channel'];
        !          66197:         $this->config->set('default_channel', $channel);
        !          66198:         $chan = $reg->getChannel($channel);
        !          66199:         if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
        !          66200:             return $e;
        !          66201:         }
        !          66202: 
        !          66203:         $mirror = $this->config->get('preferred_mirror');
        !          66204:         if ($chan->supportsREST($mirror) && $base = $chan->getBaseURL('REST1.0', $mirror)) {
        !          66205:             $rest = &$this->config->getREST('1.0', array());
        !          66206:             $info = $rest->packageInfo($base, $parsed['package'], $channel);
        !          66207:         }
        !          66208: 
        !          66209:         if (!isset($info)) {
        !          66210:             return $this->raiseError('No supported protocol was found');
        !          66211:         }
        !          66212: 
        !          66213:         if (PEAR::isError($info)) {
        !          66214:             $this->config->set('default_channel', $savechannel);
        !          66215:             return $this->raiseError($info);
        !          66216:         }
        !          66217: 
        !          66218:         if (!isset($info['name'])) {
        !          66219:             return $this->raiseError('No remote package "' . $package . '" was found');
        !          66220:         }
        !          66221: 
        !          66222:         $installed = $reg->packageInfo($info['name'], null, $channel);
        !          66223:         $info['installed'] = $installed['version'] ? $installed['version'] : '- no -';
        !          66224:         if (is_array($info['installed'])) {
        !          66225:             $info['installed'] = $info['installed']['release'];
        !          66226:         }
        !          66227: 
        !          66228:         $this->ui->outputData($info, $command);
        !          66229:         $this->config->set('default_channel', $savechannel);
        !          66230: 
        !          66231:         return true;
        !          66232:     }
        !          66233: 
        !          66234:     function doRemoteList($command, $options, $params)
        !          66235:     {
        !          66236:         $savechannel = $channel = $this->config->get('default_channel');
        !          66237:         $reg = &$this->config->getRegistry();
        !          66238:         if (isset($options['channel'])) {
        !          66239:             $channel = $options['channel'];
        !          66240:             if (!$reg->channelExists($channel)) {
        !          66241:                 return $this->raiseError('Channel "' . $channel . '" does not exist');
        !          66242:             }
        !          66243: 
        !          66244:             $this->config->set('default_channel', $channel);
        !          66245:         }
        !          66246: 
        !          66247:         $chan = $reg->getChannel($channel);
        !          66248:         if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
        !          66249:             return $e;
        !          66250:         }
        !          66251: 
        !          66252:         $list_options = false;
        !          66253:         if ($this->config->get('preferred_state') == 'stable') {
        !          66254:             $list_options = true;
        !          66255:         }
        !          66256: 
        !          66257:         $available = array();
        !          66258:         if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
        !          66259:               $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))
        !          66260:         ) {
        !          66261:             // use faster list-all if available
        !          66262:             $rest = &$this->config->getREST('1.1', array());
        !          66263:             $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName());
        !          66264:         } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) &&
        !          66265:               $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
        !          66266:             $rest = &$this->config->getREST('1.0', array());
        !          66267:             $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName());
        !          66268:         }
        !          66269: 
        !          66270:         if (PEAR::isError($available)) {
        !          66271:             $this->config->set('default_channel', $savechannel);
        !          66272:             return $this->raiseError($available);
        !          66273:         }
        !          66274: 
        !          66275:         $i = $j = 0;
        !          66276:         $data = array(
        !          66277:             'caption' => 'Channel ' . $channel . ' Available packages:',
        !          66278:             'border' => true,
        !          66279:             'headline' => array('Package', 'Version'),
        !          66280:             'channel' => $channel
        !          66281:             );
        !          66282: 
        !          66283:         if (count($available) == 0) {
        !          66284:             $data = '(no packages available yet)';
        !          66285:         } else {
        !          66286:             foreach ($available as $name => $info) {
        !          66287:                 $version = (isset($info['stable']) && $info['stable']) ? $info['stable'] : '-n/a-';
        !          66288:                 $data['data'][] = array($name, $version);
        !          66289:             }
        !          66290:         }
        !          66291:         $this->ui->outputData($data, $command);
        !          66292:         $this->config->set('default_channel', $savechannel);
        !          66293:         return true;
        !          66294:     }
        !          66295: 
        !          66296:     function doListAll($command, $options, $params)
        !          66297:     {
        !          66298:         $savechannel = $channel = $this->config->get('default_channel');
        !          66299:         $reg = &$this->config->getRegistry();
        !          66300:         if (isset($options['channel'])) {
        !          66301:             $channel = $options['channel'];
        !          66302:             if (!$reg->channelExists($channel)) {
        !          66303:                 return $this->raiseError("Channel \"$channel\" does not exist");
        !          66304:             }
        !          66305: 
        !          66306:             $this->config->set('default_channel', $channel);
        !          66307:         }
        !          66308: 
        !          66309:         $list_options = false;
        !          66310:         if ($this->config->get('preferred_state') == 'stable') {
        !          66311:             $list_options = true;
        !          66312:         }
        !          66313: 
        !          66314:         $chan = $reg->getChannel($channel);
        !          66315:         if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
        !          66316:             return $e;
        !          66317:         }
        !          66318: 
        !          66319:         if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
        !          66320:               $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) {
        !          66321:             // use faster list-all if available
        !          66322:             $rest = &$this->config->getREST('1.1', array());
        !          66323:             $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName());
        !          66324:         } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) &&
        !          66325:               $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
        !          66326:             $rest = &$this->config->getREST('1.0', array());
        !          66327:             $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName());
        !          66328:         }
        !          66329: 
        !          66330:         if (PEAR::isError($available)) {
        !          66331:             $this->config->set('default_channel', $savechannel);
        !          66332:             return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "' . $available->getMessage() . '")');
        !          66333:         }
        !          66334: 
        !          66335:         $data = array(
        !          66336:             'caption' => 'All packages [Channel ' . $channel . ']:',
        !          66337:             'border' => true,
        !          66338:             'headline' => array('Package', 'Latest', 'Local'),
        !          66339:             'channel' => $channel,
        !          66340:             );
        !          66341: 
        !          66342:         if (isset($options['channelinfo'])) {
        !          66343:             // add full channelinfo
        !          66344:             $data['caption'] = 'Channel ' . $channel . ' All packages:';
        !          66345:             $data['headline'] = array('Channel', 'Package', 'Latest', 'Local',
        !          66346:                 'Description', 'Dependencies');
        !          66347:         }
        !          66348:         $local_pkgs = $reg->listPackages($channel);
        !          66349: 
        !          66350:         foreach ($available as $name => $info) {
        !          66351:             $installed = $reg->packageInfo($name, null, $channel);
        !          66352:             if (is_array($installed['version'])) {
        !          66353:                 $installed['version'] = $installed['version']['release'];
        !          66354:             }
        !          66355:             $desc = $info['summary'];
        !          66356:             if (isset($params[$name])) {
        !          66357:                 $desc .= "\n\n".$info['description'];
        !          66358:             }
        !          66359:             if (isset($options['mode']))
        !          66360:             {
        !          66361:                 if ($options['mode'] == 'installed' && !isset($installed['version'])) {
        !          66362:                     continue;
        !          66363:                 }
        !          66364:                 if ($options['mode'] == 'notinstalled' && isset($installed['version'])) {
        !          66365:                     continue;
        !          66366:                 }
        !          66367:                 if ($options['mode'] == 'upgrades'
        !          66368:                       && (!isset($installed['version']) || version_compare($installed['version'],
        !          66369:                       $info['stable'], '>='))) {
        !          66370:                     continue;
        !          66371:                 }
        !          66372:             }
        !          66373:             $pos = array_search(strtolower($name), $local_pkgs);
        !          66374:             if ($pos !== false) {
        !          66375:                 unset($local_pkgs[$pos]);
        !          66376:             }
        !          66377: 
        !          66378:             if (isset($info['stable']) && !$info['stable']) {
        !          66379:                 $info['stable'] = null;
        !          66380:             }
        !          66381: 
        !          66382:             if (isset($options['channelinfo'])) {
        !          66383:                 // add full channelinfo
        !          66384:                 if ($info['stable'] === $info['unstable']) {
        !          66385:                     $state = $info['state'];
        !          66386:                 } else {
        !          66387:                     $state = 'stable';
        !          66388:                 }
        !          66389:                 $latest = $info['stable'].' ('.$state.')';
        !          66390:                 $local = '';
        !          66391:                 if (isset($installed['version'])) {
        !          66392:                     $inst_state = $reg->packageInfo($name, 'release_state', $channel);
        !          66393:                     $local = $installed['version'].' ('.$inst_state.')';
        !          66394:                 }
        !          66395: 
        !          66396:                 $packageinfo = array(
        !          66397:                     $channel,
        !          66398:                     $name,
        !          66399:                     $latest,
        !          66400:                     $local,
        !          66401:                     isset($desc) ? $desc : null,
        !          66402:                     isset($info['deps']) ? $info['deps'] : null,
        !          66403:                 );
        !          66404:             } else {
        !          66405:                 $packageinfo = array(
        !          66406:                     $reg->channelAlias($channel) . '/' . $name,
        !          66407:                     isset($info['stable']) ? $info['stable'] : null,
        !          66408:                     isset($installed['version']) ? $installed['version'] : null,
        !          66409:                     isset($desc) ? $desc : null,
        !          66410:                     isset($info['deps']) ? $info['deps'] : null,
        !          66411:                 );
        !          66412:             }
        !          66413:             $data['data'][$info['category']][] = $packageinfo;
        !          66414:         }
        !          66415: 
        !          66416:         if (isset($options['mode']) && in_array($options['mode'], array('notinstalled', 'upgrades'))) {
        !          66417:             $this->config->set('default_channel', $savechannel);
        !          66418:             $this->ui->outputData($data, $command);
        !          66419:             return true;
        !          66420:         }
        !          66421: 
        !          66422:         foreach ($local_pkgs as $name) {
        !          66423:             $info = &$reg->getPackage($name, $channel);
        !          66424:             $data['data']['Local'][] = array(
        !          66425:                 $reg->channelAlias($channel) . '/' . $info->getPackage(),
        !          66426:                 '',
        !          66427:                 $info->getVersion(),
        !          66428:                 $info->getSummary(),
        !          66429:                 $info->getDeps()
        !          66430:                 );
        !          66431:         }
        !          66432: 
        !          66433:         $this->config->set('default_channel', $savechannel);
        !          66434:         $this->ui->outputData($data, $command);
        !          66435:         return true;
        !          66436:     }
        !          66437: 
        !          66438:     function doSearch($command, $options, $params)
        !          66439:     {
        !          66440:         if ((!isset($params[0]) || empty($params[0]))
        !          66441:             && (!isset($params[1]) || empty($params[1])))
        !          66442:         {
        !          66443:             return $this->raiseError('no valid search string supplied');
        !          66444:         }
        !          66445: 
        !          66446:         $channelinfo = isset($options['channelinfo']);
        !          66447:         $reg = &$this->config->getRegistry();
        !          66448:         if (isset($options['allchannels'])) {
        !          66449:             // search all channels
        !          66450:             unset($options['allchannels']);
        !          66451:             $channels = $reg->getChannels();
        !          66452:             $errors = array();
        !          66453:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          66454:             foreach ($channels as $channel) {
        !          66455:                 if ($channel->getName() != '__uri') {
        !          66456:                     $options['channel'] = $channel->getName();
        !          66457:                     $ret = $this->doSearch($command, $options, $params);
        !          66458:                     if (PEAR::isError($ret)) {
        !          66459:                         $errors[] = $ret;
        !          66460:                     }
        !          66461:                 }
        !          66462:             }
        !          66463: 
        !          66464:             PEAR::staticPopErrorHandling();
        !          66465:             if (count($errors) !== 0) {
        !          66466:                 // for now, only give first error
        !          66467:                 return PEAR::raiseError($errors[0]);
        !          66468:             }
        !          66469: 
        !          66470:             return true;
        !          66471:         }
        !          66472: 
        !          66473:         $savechannel = $channel = $this->config->get('default_channel');
        !          66474:         $package = strtolower($params[0]);
        !          66475:         $summary = isset($params[1]) ? $params[1] : false;
        !          66476:         if (isset($options['channel'])) {
        !          66477:             $reg = &$this->config->getRegistry();
        !          66478:             $channel = $options['channel'];
        !          66479:             if (!$reg->channelExists($channel)) {
        !          66480:                 return $this->raiseError('Channel "' . $channel . '" does not exist');
        !          66481:             }
        !          66482: 
        !          66483:             $this->config->set('default_channel', $channel);
        !          66484:         }
        !          66485: 
        !          66486:         $chan = $reg->getChannel($channel);
        !          66487:         if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
        !          66488:             return $e;
        !          66489:         }
        !          66490: 
        !          66491:         if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
        !          66492:               $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
        !          66493:             $rest = &$this->config->getREST('1.0', array());
        !          66494:             $available = $rest->listAll($base, false, false, $package, $summary, $chan->getName());
        !          66495:         }
        !          66496: 
        !          66497:         if (PEAR::isError($available)) {
        !          66498:             $this->config->set('default_channel', $savechannel);
        !          66499:             return $this->raiseError($available);
        !          66500:         }
        !          66501: 
        !          66502:         if (!$available && !$channelinfo) {
        !          66503:             // clean exit when not found, no error !
        !          66504:             $data = 'no packages found that match pattern "' . $package . '", for channel '.$channel.'.';
        !          66505:             $this->ui->outputData($data);
        !          66506:             $this->config->set('default_channel', $channel);
        !          66507:             return true;
        !          66508:         }
        !          66509: 
        !          66510:         if ($channelinfo) {
        !          66511:             $data = array(
        !          66512:                 'caption' => 'Matched packages, channel ' . $channel . ':',
        !          66513:                 'border' => true,
        !          66514:                 'headline' => array('Channel', 'Package', 'Stable/(Latest)', 'Local'),
        !          66515:                 'channel' => $channel
        !          66516:                 );
        !          66517:         } else {
        !          66518:             $data = array(
        !          66519:                 'caption' => 'Matched packages, channel ' . $channel . ':',
        !          66520:                 'border' => true,
        !          66521:                 'headline' => array('Package', 'Stable/(Latest)', 'Local'),
        !          66522:                 'channel' => $channel
        !          66523:                 );
        !          66524:         }
        !          66525: 
        !          66526:         if (!$available && $channelinfo) {
        !          66527:             unset($data['headline']);
        !          66528:             $data['data'] = 'No packages found that match pattern "' . $package . '".';
        !          66529:             $available = array();
        !          66530:         }
        !          66531: 
        !          66532:         foreach ($available as $name => $info) {
        !          66533:             $installed = $reg->packageInfo($name, null, $channel);
        !          66534:             $desc = $info['summary'];
        !          66535:             if (isset($params[$name]))
        !          66536:                 $desc .= "\n\n".$info['description'];
        !          66537: 
        !          66538:             if (!isset($info['stable']) || !$info['stable']) {
        !          66539:                 $version_remote = 'none';
        !          66540:             } else {
        !          66541:                 if ($info['unstable']) {
        !          66542:                     $version_remote = $info['unstable'];
        !          66543:                 } else {
        !          66544:                     $version_remote = $info['stable'];
        !          66545:                 }
        !          66546:                 $version_remote .= ' ('.$info['state'].')';
        !          66547:             }
        !          66548:             $version = is_array($installed['version']) ? $installed['version']['release'] :
        !          66549:                 $installed['version'];
        !          66550:             if ($channelinfo) {
        !          66551:                 $packageinfo = array(
        !          66552:                     $channel,
        !          66553:                     $name,
        !          66554:                     $version_remote,
        !          66555:                     $version,
        !          66556:                     $desc,
        !          66557:                 );
        !          66558:             } else {
        !          66559:                 $packageinfo = array(
        !          66560:                     $name,
        !          66561:                     $version_remote,
        !          66562:                     $version,
        !          66563:                     $desc,
        !          66564:                 );
        !          66565:             }
        !          66566:             $data['data'][$info['category']][] = $packageinfo;
        !          66567:         }
        !          66568: 
        !          66569:         $this->ui->outputData($data, $command);
        !          66570:         $this->config->set('default_channel', $channel);
        !          66571:         return true;
        !          66572:     }
        !          66573: 
        !          66574:     function &getDownloader($options)
        !          66575:     {
        !          66576:         if (!class_exists('PEAR_Downloader')) {
        !          66577:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Downloader.php';
        !          66578:         }
        !          66579:         $a = &new PEAR_Downloader($this->ui, $options, $this->config);
        !          66580:         return $a;
        !          66581:     }
        !          66582: 
        !          66583:     function doDownload($command, $options, $params)
        !          66584:     {
        !          66585:         // make certain that dependencies are ignored
        !          66586:         $options['downloadonly'] = 1;
        !          66587: 
        !          66588:         // eliminate error messages for preferred_state-related errors
        !          66589:         /* TODO: Should be an option, but until now download does respect
        !          66590:            prefered state */
        !          66591:         /* $options['ignorepreferred_state'] = 1; */
        !          66592:         // eliminate error messages for preferred_state-related errors
        !          66593: 
        !          66594:         $downloader = &$this->getDownloader($options);
        !          66595:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          66596:         $e = $downloader->setDownloadDir(getcwd());
        !          66597:         PEAR::staticPopErrorHandling();
        !          66598:         if (PEAR::isError($e)) {
        !          66599:             return $this->raiseError('Current directory is not writeable, cannot download');
        !          66600:         }
        !          66601: 
        !          66602:         $errors = array();
        !          66603:         $downloaded = array();
        !          66604:         $err = $downloader->download($params);
        !          66605:         if (PEAR::isError($err)) {
        !          66606:             return $err;
        !          66607:         }
        !          66608: 
        !          66609:         $errors = $downloader->getErrorMsgs();
        !          66610:         if (count($errors)) {
        !          66611:             foreach ($errors as $error) {
        !          66612:                 if ($error !== null) {
        !          66613:                     $this->ui->outputData($error);
        !          66614:                 }
        !          66615:             }
        !          66616: 
        !          66617:             return $this->raiseError("$command failed");
        !          66618:         }
        !          66619: 
        !          66620:         $downloaded = $downloader->getDownloadedPackages();
        !          66621:         foreach ($downloaded as $pkg) {
        !          66622:             $this->ui->outputData("File $pkg[file] downloaded", $command);
        !          66623:         }
        !          66624: 
        !          66625:         return true;
        !          66626:     }
        !          66627: 
        !          66628:     function downloadCallback($msg, $params = null)
        !          66629:     {
        !          66630:         if ($msg == 'done') {
        !          66631:             $this->bytes_downloaded = $params;
        !          66632:         }
        !          66633:     }
        !          66634: 
        !          66635:     function doListUpgrades($command, $options, $params)
        !          66636:     {
        !          66637:         require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
        !          66638:         if (isset($params[0]) && !is_array(PEAR_Common::betterStates($params[0]))) {
        !          66639:             return $this->raiseError($params[0] . ' is not a valid state (stable/beta/alpha/devel/etc.) try "pear help list-upgrades"');
        !          66640:         }
        !          66641: 
        !          66642:         $savechannel = $channel = $this->config->get('default_channel');
        !          66643:         $reg = &$this->config->getRegistry();
        !          66644:         foreach ($reg->listChannels() as $channel) {
        !          66645:             $inst = array_flip($reg->listPackages($channel));
        !          66646:             if (!count($inst)) {
        !          66647:                 continue;
        !          66648:             }
        !          66649: 
        !          66650:             if ($channel == '__uri') {
        !          66651:                 continue;
        !          66652:             }
        !          66653: 
        !          66654:             $this->config->set('default_channel', $channel);
        !          66655:             $state = empty($params[0]) ? $this->config->get('preferred_state') : $params[0];
        !          66656: 
        !          66657:             $caption = $channel . ' Available Upgrades';
        !          66658:             $chan = $reg->getChannel($channel);
        !          66659:             if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
        !          66660:                 return $e;
        !          66661:             }
        !          66662: 
        !          66663:             $latest = array();
        !          66664:             $base2  = false;
        !          66665:             $preferred_mirror = $this->config->get('preferred_mirror');
        !          66666:             if ($chan->supportsREST($preferred_mirror) &&
        !          66667:                 (
        !          66668:                    //($base2 = $chan->getBaseURL('REST1.4', $preferred_mirror)) ||
        !          66669:                    ($base  = $chan->getBaseURL('REST1.0', $preferred_mirror))
        !          66670:                 )
        !          66671: 
        !          66672:             ) {
        !          66673:                 if ($base2) {
        !          66674:                     $rest = &$this->config->getREST('1.4', array());
        !          66675:                     $base = $base2;
        !          66676:                 } else {
        !          66677:                     $rest = &$this->config->getREST('1.0', array());
        !          66678:                 }
        !          66679: 
        !          66680:                 if (empty($state) || $state == 'any') {
        !          66681:                     $state = false;
        !          66682:                 } else {
        !          66683:                     $caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')';
        !          66684:                 }
        !          66685: 
        !          66686:                 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          66687:                 $latest = $rest->listLatestUpgrades($base, $state, $inst, $channel, $reg);
        !          66688:                 PEAR::staticPopErrorHandling();
        !          66689:             }
        !          66690: 
        !          66691:             if (PEAR::isError($latest)) {
        !          66692:                 $this->ui->outputData($latest->getMessage());
        !          66693:                 continue;
        !          66694:             }
        !          66695: 
        !          66696:             $caption .= ':';
        !          66697:             if (PEAR::isError($latest)) {
        !          66698:                 $this->config->set('default_channel', $savechannel);
        !          66699:                 return $latest;
        !          66700:             }
        !          66701: 
        !          66702:             $data = array(
        !          66703:                 'caption' => $caption,
        !          66704:                 'border' => 1,
        !          66705:                 'headline' => array('Channel', 'Package', 'Local', 'Remote', 'Size'),
        !          66706:                 'channel' => $channel
        !          66707:                 );
        !          66708: 
        !          66709:             foreach ((array)$latest as $pkg => $info) {
        !          66710:                 $package = strtolower($pkg);
        !          66711:                 if (!isset($inst[$package])) {
        !          66712:                     // skip packages we don't have installed
        !          66713:                     continue;
        !          66714:                 }
        !          66715: 
        !          66716:                 extract($info);
        !          66717:                 $inst_version = $reg->packageInfo($package, 'version', $channel);
        !          66718:                 $inst_state   = $reg->packageInfo($package, 'release_state', $channel);
        !          66719:                 if (version_compare("$version", "$inst_version", "le")) {
        !          66720:                     // installed version is up-to-date
        !          66721:                     continue;
        !          66722:                 }
        !          66723: 
        !          66724:                 if ($filesize >= 20480) {
        !          66725:                     $filesize += 1024 - ($filesize % 1024);
        !          66726:                     $fs = sprintf("%dkB", $filesize / 1024);
        !          66727:                 } elseif ($filesize > 0) {
        !          66728:                     $filesize += 103 - ($filesize % 103);
        !          66729:                     $fs = sprintf("%.1fkB", $filesize / 1024.0);
        !          66730:                 } else {
        !          66731:                     $fs = "  -"; // XXX center instead
        !          66732:                 }
        !          66733: 
        !          66734:                 $data['data'][] = array($channel, $pkg, "$inst_version ($inst_state)", "$version ($state)", $fs);
        !          66735:             }
        !          66736: 
        !          66737:             if (isset($options['channelinfo'])) {
        !          66738:                 if (empty($data['data'])) {
        !          66739:                     unset($data['headline']);
        !          66740:                     if (count($inst) == 0) {
        !          66741:                         $data['data'] = '(no packages installed)';
        !          66742:                     } else {
        !          66743:                         $data['data'] = '(no upgrades available)';
        !          66744:                     }
        !          66745:                 }
        !          66746:                 $this->ui->outputData($data, $command);
        !          66747:             } else {
        !          66748:                 if (empty($data['data'])) {
        !          66749:                     $this->ui->outputData('Channel ' . $channel . ': No upgrades available');
        !          66750:                 } else {
        !          66751:                     $this->ui->outputData($data, $command);
        !          66752:                 }
        !          66753:             }
        !          66754:         }
        !          66755: 
        !          66756:         $this->config->set('default_channel', $savechannel);
        !          66757:         return true;
        !          66758:     }
        !          66759: 
        !          66760:     function doClearCache($command, $options, $params)
        !          66761:     {
        !          66762:         $cache_dir = $this->config->get('cache_dir');
        !          66763:         $verbose   = $this->config->get('verbose');
        !          66764:         $output = '';
        !          66765:         if (!file_exists($cache_dir) || !is_dir($cache_dir)) {
        !          66766:             return $this->raiseError("$cache_dir does not exist or is not a directory");
        !          66767:         }
        !          66768: 
        !          66769:         if (!($dp = @opendir($cache_dir))) {
        !          66770:             return $this->raiseError("opendir($cache_dir) failed: $php_errormsg");
        !          66771:         }
        !          66772: 
        !          66773:         if ($verbose >= 1) {
        !          66774:             $output .= "reading directory $cache_dir\n";
        !          66775:         }
        !          66776: 
        !          66777:         $num = 0;
        !          66778:         while ($ent = readdir($dp)) {
        !          66779:             if (preg_match('/rest.cache(file|id)\\z/', $ent)) {
        !          66780:                 $path = $cache_dir . DIRECTORY_SEPARATOR . $ent;
        !          66781:                 if (file_exists($path)) {
        !          66782:                     $ok = @unlink($path);
        !          66783:                 } else {
        !          66784:                     $ok = false;
        !          66785:                     $php_errormsg = '';
        !          66786:                 }
        !          66787: 
        !          66788:                 if ($ok) {
        !          66789:                     if ($verbose >= 2) {
        !          66790:                         $output .= "deleted $path\n";
        !          66791:                     }
        !          66792:                     $num++;
        !          66793:                 } elseif ($verbose >= 1) {
        !          66794:                     $output .= "failed to delete $path $php_errormsg\n";
        !          66795:                 }
        !          66796:             }
        !          66797:         }
        !          66798: 
        !          66799:         closedir($dp);
        !          66800:         if ($verbose >= 1) {
        !          66801:             $output .= "$num cache entries cleared\n";
        !          66802:         }
        !          66803: 
        !          66804:         $this->ui->outputData(rtrim($output), $command);
        !          66805:         return $num;
        !          66806:     }
        !          66807: }<commands version="1.0">
        !          66808:  <remote-info>
        !          66809:   <summary>Information About Remote Packages</summary>
        !          66810:   <function>doRemoteInfo</function>
        !          66811:   <shortcut>ri</shortcut>
        !          66812:   <options />
        !          66813:   <doc>&lt;package&gt;
        !          66814: Get details on a package from the server.</doc>
        !          66815:  </remote-info>
        !          66816:  <list-upgrades>
        !          66817:   <summary>List Available Upgrades</summary>
        !          66818:   <function>doListUpgrades</function>
        !          66819:   <shortcut>lu</shortcut>
        !          66820:   <options>
        !          66821:    <channelinfo>
        !          66822:     <shortopt>i</shortopt>
        !          66823:     <doc>output fully channel-aware data, even on failure</doc>
        !          66824:    </channelinfo>
        !          66825:   </options>
        !          66826:   <doc>[preferred_state]
        !          66827: List releases on the server of packages you have installed where
        !          66828: a newer version is available with the same release state (stable etc.)
        !          66829: or the state passed as the second parameter.</doc>
        !          66830:  </list-upgrades>
        !          66831:  <remote-list>
        !          66832:   <summary>List Remote Packages</summary>
        !          66833:   <function>doRemoteList</function>
        !          66834:   <shortcut>rl</shortcut>
        !          66835:   <options>
        !          66836:    <channel>
        !          66837:     <shortopt>c</shortopt>
        !          66838:     <doc>specify a channel other than the default channel</doc>
        !          66839:     <arg>CHAN</arg>
        !          66840:    </channel>
        !          66841:   </options>
        !          66842:   <doc>
        !          66843: Lists the packages available on the configured server along with the
        !          66844: latest stable release of each package.</doc>
        !          66845:  </remote-list>
        !          66846:  <search>
        !          66847:   <summary>Search remote package database</summary>
        !          66848:   <function>doSearch</function>
        !          66849:   <shortcut>sp</shortcut>
        !          66850:   <options>
        !          66851:    <channel>
        !          66852:     <shortopt>c</shortopt>
        !          66853:     <doc>specify a channel other than the default channel</doc>
        !          66854:     <arg>CHAN</arg>
        !          66855:    </channel>
        !          66856:    <allchannels>
        !          66857:     <shortopt>a</shortopt>
        !          66858:     <doc>search packages from all known channels</doc>
        !          66859:    </allchannels>
        !          66860:    <channelinfo>
        !          66861:     <shortopt>i</shortopt>
        !          66862:     <doc>output fully channel-aware data, even on failure</doc>
        !          66863:    </channelinfo>
        !          66864:   </options>
        !          66865:   <doc>[packagename] [packageinfo]
        !          66866: Lists all packages which match the search parameters.  The first
        !          66867: parameter is a fragment of a packagename.  The default channel
        !          66868: will be used unless explicitly overridden.  The second parameter
        !          66869: will be used to match any portion of the summary/description</doc>
        !          66870:  </search>
        !          66871:  <list-all>
        !          66872:   <summary>List All Packages</summary>
        !          66873:   <function>doListAll</function>
        !          66874:   <shortcut>la</shortcut>
        !          66875:   <options>
        !          66876:    <channel>
        !          66877:     <shortopt>c</shortopt>
        !          66878:     <doc>specify a channel other than the default channel</doc>
        !          66879:     <arg>CHAN</arg>
        !          66880:    </channel>
        !          66881:    <channelinfo>
        !          66882:     <shortopt>i</shortopt>
        !          66883:     <doc>output fully channel-aware data, even on failure</doc>
        !          66884:    </channelinfo>
        !          66885:   </options>
        !          66886:   <doc>
        !          66887: Lists the packages available on the configured server along with the
        !          66888: latest stable release of each package.</doc>
        !          66889:  </list-all>
        !          66890:  <download>
        !          66891:   <summary>Download Package</summary>
        !          66892:   <function>doDownload</function>
        !          66893:   <shortcut>d</shortcut>
        !          66894:   <options>
        !          66895:    <nocompress>
        !          66896:     <shortopt>Z</shortopt>
        !          66897:     <doc>download an uncompressed (.tar) file</doc>
        !          66898:    </nocompress>
        !          66899:   </options>
        !          66900:   <doc>&lt;package&gt;...
        !          66901: Download package tarballs.  The files will be named as suggested by the
        !          66902: server, for example if you download the DB package and the latest stable
        !          66903: version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.</doc>
        !          66904:  </download>
        !          66905:  <clear-cache>
        !          66906:   <summary>Clear Web Services Cache</summary>
        !          66907:   <function>doClearCache</function>
        !          66908:   <shortcut>cc</shortcut>
        !          66909:   <options />
        !          66910:   <doc>
        !          66911: Clear the XML-RPC/REST cache.  See also the cache_ttl configuration
        !          66912: parameter.
        !          66913: </doc>
        !          66914:  </clear-cache>
        !          66915: </commands><?php
        !          66916: /**
        !          66917:  * PEAR_Command_Test (run-tests)
        !          66918:  *
        !          66919:  * PHP versions 4 and 5
        !          66920:  *
        !          66921:  * @category   pear
        !          66922:  * @package    PEAR
        !          66923:  * @author     Stig Bakken <ssb@php.net>
        !          66924:  * @author     Martin Jansen <mj@php.net>
        !          66925:  * @author     Greg Beaver <cellog@php.net>
        !          66926:  * @copyright  1997-2009 The Authors
        !          66927:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          66928:  * @version    CVS: $Id: Test.php 313023 2011-07-06 19:17:11Z dufuz $
        !          66929:  * @link       http://pear.php.net/package/PEAR
        !          66930:  * @since      File available since Release 0.1
        !          66931:  */
        !          66932: 
        !          66933: /**
        !          66934:  * base class
        !          66935:  */
        !          66936: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command/Common.php';
        !          66937: 
        !          66938: /**
        !          66939:  * PEAR commands for login/logout
        !          66940:  *
        !          66941:  * @category   pear
        !          66942:  * @package    PEAR
        !          66943:  * @author     Stig Bakken <ssb@php.net>
        !          66944:  * @author     Martin Jansen <mj@php.net>
        !          66945:  * @author     Greg Beaver <cellog@php.net>
        !          66946:  * @copyright  1997-2009 The Authors
        !          66947:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          66948:  * @version    Release: 1.9.4
        !          66949:  * @link       http://pear.php.net/package/PEAR
        !          66950:  * @since      Class available since Release 0.1
        !          66951:  */
        !          66952: 
        !          66953: class PEAR_Command_Test extends PEAR_Command_Common
        !          66954: {
        !          66955:     var $commands = array(
        !          66956:         'run-tests' => array(
        !          66957:             'summary' => 'Run Regression Tests',
        !          66958:             'function' => 'doRunTests',
        !          66959:             'shortcut' => 'rt',
        !          66960:             'options' => array(
        !          66961:                 'recur' => array(
        !          66962:                     'shortopt' => 'r',
        !          66963:                     'doc' => 'Run tests in child directories, recursively.  4 dirs deep maximum',
        !          66964:                 ),
        !          66965:                 'ini' => array(
        !          66966:                     'shortopt' => 'i',
        !          66967:                     'doc' => 'actual string of settings to pass to php in format " -d setting=blah"',
        !          66968:                     'arg' => 'SETTINGS'
        !          66969:                 ),
        !          66970:                 'realtimelog' => array(
        !          66971:                     'shortopt' => 'l',
        !          66972:                     'doc' => 'Log test runs/results as they are run',
        !          66973:                 ),
        !          66974:                 'quiet' => array(
        !          66975:                     'shortopt' => 'q',
        !          66976:                     'doc' => 'Only display detail for failed tests',
        !          66977:                 ),
        !          66978:                 'simple' => array(
        !          66979:                     'shortopt' => 's',
        !          66980:                     'doc' => 'Display simple output for all tests',
        !          66981:                 ),
        !          66982:                 'package' => array(
        !          66983:                     'shortopt' => 'p',
        !          66984:                     'doc' => 'Treat parameters as installed packages from which to run tests',
        !          66985:                 ),
        !          66986:                 'phpunit' => array(
        !          66987:                     'shortopt' => 'u',
        !          66988:                     'doc' => 'Search parameters for AllTests.php, and use that to run phpunit-based tests
        !          66989: If none is found, all .phpt tests will be tried instead.',
        !          66990:                 ),
        !          66991:                 'tapoutput' => array(
        !          66992:                     'shortopt' => 't',
        !          66993:                     'doc' => 'Output run-tests.log in TAP-compliant format',
        !          66994:                 ),
        !          66995:                 'cgi' => array(
        !          66996:                     'shortopt' => 'c',
        !          66997:                     'doc' => 'CGI php executable (needed for tests with POST/GET section)',
        !          66998:                     'arg' => 'PHPCGI',
        !          66999:                 ),
        !          67000:                 'coverage' => array(
        !          67001:                     'shortopt' => 'x',
        !          67002:                     'doc'      => 'Generate a code coverage report (requires Xdebug 2.0.0+)',
        !          67003:                 ),
        !          67004:             ),
        !          67005:             'doc' => '[testfile|dir ...]
        !          67006: Run regression tests with PHP\'s regression testing script (run-tests.php).',
        !          67007:             ),
        !          67008:         );
        !          67009: 
        !          67010:     var $output;
        !          67011: 
        !          67012:     /**
        !          67013:      * PEAR_Command_Test constructor.
        !          67014:      *
        !          67015:      * @access public
        !          67016:      */
        !          67017:     function PEAR_Command_Test(&$ui, &$config)
        !          67018:     {
        !          67019:         parent::PEAR_Command_Common($ui, $config);
        !          67020:     }
        !          67021: 
        !          67022:     function doRunTests($command, $options, $params)
        !          67023:     {
        !          67024:         if (isset($options['phpunit']) && isset($options['tapoutput'])) {
        !          67025:             return $this->raiseError('ERROR: cannot use both --phpunit and --tapoutput at the same time');
        !          67026:         }
        !          67027: 
        !          67028:         require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
        !          67029:         require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
        !          67030:         $log = new PEAR_Common;
        !          67031:         $log->ui = &$this->ui; // slightly hacky, but it will work
        !          67032:         $tests = array();
        !          67033:         $depth = isset($options['recur']) ? 14 : 1;
        !          67034: 
        !          67035:         if (!count($params)) {
        !          67036:             $params[] = '.';
        !          67037:         }
        !          67038: 
        !          67039:         if (isset($options['package'])) {
        !          67040:             $oldparams = $params;
        !          67041:             $params = array();
        !          67042:             $reg = &$this->config->getRegistry();
        !          67043:             foreach ($oldparams as $param) {
        !          67044:                 $pname = $reg->parsePackageName($param, $this->config->get('default_channel'));
        !          67045:                 if (PEAR::isError($pname)) {
        !          67046:                     return $this->raiseError($pname);
        !          67047:                 }
        !          67048: 
        !          67049:                 $package = &$reg->getPackage($pname['package'], $pname['channel']);
        !          67050:                 if (!$package) {
        !          67051:                     return PEAR::raiseError('Unknown package "' .
        !          67052:                         $reg->parsedPackageNameToString($pname) . '"');
        !          67053:                 }
        !          67054: 
        !          67055:                 $filelist = $package->getFilelist();
        !          67056:                 foreach ($filelist as $name => $atts) {
        !          67057:                     if (isset($atts['role']) && $atts['role'] != 'test') {
        !          67058:                         continue;
        !          67059:                     }
        !          67060: 
        !          67061:                     if (isset($options['phpunit']) && preg_match('/AllTests\.php\\z/i', $name)) {
        !          67062:                         $params[] = $atts['installed_as'];
        !          67063:                         continue;
        !          67064:                     } elseif (!preg_match('/\.phpt\\z/', $name)) {
        !          67065:                         continue;
        !          67066:                     }
        !          67067:                     $params[] = $atts['installed_as'];
        !          67068:                 }
        !          67069:             }
        !          67070:         }
        !          67071: 
        !          67072:         foreach ($params as $p) {
        !          67073:             if (is_dir($p)) {
        !          67074:                 if (isset($options['phpunit'])) {
        !          67075:                     $dir = System::find(array($p, '-type', 'f',
        !          67076:                                                 '-maxdepth', $depth,
        !          67077:                                                 '-name', 'AllTests.php'));
        !          67078:                     if (count($dir)) {
        !          67079:                         foreach ($dir as $p) {
        !          67080:                             $p = realpath($p);
        !          67081:                             if (!count($tests) ||
        !          67082:                                   (count($tests) && strlen($p) < strlen($tests[0]))) {
        !          67083:                                 // this is in a higher-level directory, use this one instead.
        !          67084:                                 $tests = array($p);
        !          67085:                             }
        !          67086:                         }
        !          67087:                     }
        !          67088:                     continue;
        !          67089:                 }
        !          67090: 
        !          67091:                 $args  = array($p, '-type', 'f', '-name', '*.phpt');
        !          67092:             } else {
        !          67093:                 if (isset($options['phpunit'])) {
        !          67094:                     if (preg_match('/AllTests\.php\\z/i', $p)) {
        !          67095:                         $p = realpath($p);
        !          67096:                         if (!count($tests) ||
        !          67097:                               (count($tests) && strlen($p) < strlen($tests[0]))) {
        !          67098:                             // this is in a higher-level directory, use this one instead.
        !          67099:                             $tests = array($p);
        !          67100:                         }
        !          67101:                     }
        !          67102:                     continue;
        !          67103:                 }
        !          67104: 
        !          67105:                 if (file_exists($p) && preg_match('/\.phpt$/', $p)) {
        !          67106:                     $tests[] = $p;
        !          67107:                     continue;
        !          67108:                 }
        !          67109: 
        !          67110:                 if (!preg_match('/\.phpt\\z/', $p)) {
        !          67111:                     $p .= '.phpt';
        !          67112:                 }
        !          67113: 
        !          67114:                 $args  = array(dirname($p), '-type', 'f', '-name', $p);
        !          67115:             }
        !          67116: 
        !          67117:             if (!isset($options['recur'])) {
        !          67118:                 $args[] = '-maxdepth';
        !          67119:                 $args[] = 1;
        !          67120:             }
        !          67121: 
        !          67122:             $dir   = System::find($args);
        !          67123:             $tests = array_merge($tests, $dir);
        !          67124:         }
        !          67125: 
        !          67126:         $ini_settings = '';
        !          67127:         if (isset($options['ini'])) {
        !          67128:             $ini_settings .= $options['ini'];
        !          67129:         }
        !          67130: 
        !          67131:         if (isset($_ENV['TEST_PHP_INCLUDE_PATH'])) {
        !          67132:             $ini_settings .= " -d include_path={$_ENV['TEST_PHP_INCLUDE_PATH']}";
        !          67133:         }
        !          67134: 
        !          67135:         if ($ini_settings) {
        !          67136:             $this->ui->outputData('Using INI settings: "' . $ini_settings . '"');
        !          67137:         }
        !          67138: 
        !          67139:         $skipped = $passed = $failed = array();
        !          67140:         $tests_count = count($tests);
        !          67141:         $this->ui->outputData('Running ' . $tests_count . ' tests', $command);
        !          67142:         $start = time();
        !          67143:         if (isset($options['realtimelog']) && file_exists('run-tests.log')) {
        !          67144:             unlink('run-tests.log');
        !          67145:         }
        !          67146: 
        !          67147:         if (isset($options['tapoutput'])) {
        !          67148:             $tap = '1..' . $tests_count . "\n";
        !          67149:         }
        !          67150: 
        !          67151:         require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/RunTest.php';
        !          67152:         $run = new PEAR_RunTest($log, $options);
        !          67153:         $run->tests_count = $tests_count;
        !          67154: 
        !          67155:         if (isset($options['coverage']) && extension_loaded('xdebug')){
        !          67156:             $run->xdebug_loaded = true;
        !          67157:         } else {
        !          67158:             $run->xdebug_loaded = false;
        !          67159:         }
        !          67160: 
        !          67161:         $j = $i = 1;
        !          67162:         foreach ($tests as $t) {
        !          67163:             if (isset($options['realtimelog'])) {
        !          67164:                 $fp = @fopen('run-tests.log', 'a');
        !          67165:                 if ($fp) {
        !          67166:                     fwrite($fp, "Running test [$i / $tests_count] $t...");
        !          67167:                     fclose($fp);
        !          67168:                 }
        !          67169:             }
        !          67170:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          67171:             if (isset($options['phpunit'])) {
        !          67172:                 $result = $run->runPHPUnit($t, $ini_settings);
        !          67173:             } else {
        !          67174:                 $result = $run->run($t, $ini_settings, $j);
        !          67175:             }
        !          67176:             PEAR::staticPopErrorHandling();
        !          67177:             if (PEAR::isError($result)) {
        !          67178:                 $this->ui->log($result->getMessage());
        !          67179:                 continue;
        !          67180:             }
        !          67181: 
        !          67182:             if (isset($options['tapoutput'])) {
        !          67183:                 $tap .= $result[0] . ' ' . $i . $result[1] . "\n";
        !          67184:                 continue;
        !          67185:             }
        !          67186: 
        !          67187:             if (isset($options['realtimelog'])) {
        !          67188:                 $fp = @fopen('run-tests.log', 'a');
        !          67189:                 if ($fp) {
        !          67190:                     fwrite($fp, "$result\n");
        !          67191:                     fclose($fp);
        !          67192:                 }
        !          67193:             }
        !          67194: 
        !          67195:             if ($result == 'FAILED') {
        !          67196:                 $failed[] = $t;
        !          67197:             }
        !          67198:             if ($result == 'PASSED') {
        !          67199:                 $passed[] = $t;
        !          67200:             }
        !          67201:             if ($result == 'SKIPPED') {
        !          67202:                 $skipped[] = $t;
        !          67203:             }
        !          67204: 
        !          67205:             $j++;
        !          67206:         }
        !          67207: 
        !          67208:         $total = date('i:s', time() - $start);
        !          67209:         if (isset($options['tapoutput'])) {
        !          67210:             $fp = @fopen('run-tests.log', 'w');
        !          67211:             if ($fp) {
        !          67212:                 fwrite($fp, $tap, strlen($tap));
        !          67213:                 fclose($fp);
        !          67214:                 $this->ui->outputData('wrote TAP-format log to "' .realpath('run-tests.log') .
        !          67215:                     '"', $command);
        !          67216:             }
        !          67217:         } else {
        !          67218:             if (count($failed)) {
        !          67219:                 $output = "TOTAL TIME: $total\n";
        !          67220:                 $output .= count($passed) . " PASSED TESTS\n";
        !          67221:                 $output .= count($skipped) . " SKIPPED TESTS\n";
        !          67222:                 $output .= count($failed) . " FAILED TESTS:\n";
        !          67223:                 foreach ($failed as $failure) {
        !          67224:                     $output .= $failure . "\n";
        !          67225:                 }
        !          67226: 
        !          67227:                 $mode = isset($options['realtimelog']) ? 'a' : 'w';
        !          67228:                 $fp   = @fopen('run-tests.log', $mode);
        !          67229: 
        !          67230:                 if ($fp) {
        !          67231:                     fwrite($fp, $output, strlen($output));
        !          67232:                     fclose($fp);
        !          67233:                     $this->ui->outputData('wrote log to "' . realpath('run-tests.log') . '"', $command);
        !          67234:                 }
        !          67235:             } elseif (file_exists('run-tests.log') && !is_dir('run-tests.log')) {
        !          67236:                 @unlink('run-tests.log');
        !          67237:             }
        !          67238:         }
        !          67239:         $this->ui->outputData('TOTAL TIME: ' . $total);
        !          67240:         $this->ui->outputData(count($passed) . ' PASSED TESTS', $command);
        !          67241:         $this->ui->outputData(count($skipped) . ' SKIPPED TESTS', $command);
        !          67242:         if (count($failed)) {
        !          67243:             $this->ui->outputData(count($failed) . ' FAILED TESTS:', $command);
        !          67244:             foreach ($failed as $failure) {
        !          67245:                 $this->ui->outputData($failure, $command);
        !          67246:             }
        !          67247:         }
        !          67248: 
        !          67249:         return true;
        !          67250:     }
        !          67251: }<commands version="1.0">
        !          67252:  <run-tests>
        !          67253:   <summary>Run Regression Tests</summary>
        !          67254:   <function>doRunTests</function>
        !          67255:   <shortcut>rt</shortcut>
        !          67256:   <options>
        !          67257:    <recur>
        !          67258:     <shortopt>r</shortopt>
        !          67259:     <doc>Run tests in child directories, recursively.  4 dirs deep maximum</doc>
        !          67260:    </recur>
        !          67261:    <ini>
        !          67262:     <shortopt>i</shortopt>
        !          67263:     <doc>actual string of settings to pass to php in format &quot; -d setting=blah&quot;</doc>
        !          67264:     <arg>SETTINGS</arg>
        !          67265:    </ini>
        !          67266:    <realtimelog>
        !          67267:     <shortopt>l</shortopt>
        !          67268:     <doc>Log test runs/results as they are run</doc>
        !          67269:    </realtimelog>
        !          67270:    <quiet>
        !          67271:     <shortopt>q</shortopt>
        !          67272:     <doc>Only display detail for failed tests</doc>
        !          67273:    </quiet>
        !          67274:    <simple>
        !          67275:     <shortopt>s</shortopt>
        !          67276:     <doc>Display simple output for all tests</doc>
        !          67277:    </simple>
        !          67278:    <package>
        !          67279:     <shortopt>p</shortopt>
        !          67280:     <doc>Treat parameters as installed packages from which to run tests</doc>
        !          67281:    </package>
        !          67282:    <phpunit>
        !          67283:     <shortopt>u</shortopt>
        !          67284:     <doc>Search parameters for AllTests.php, and use that to run phpunit-based tests
        !          67285: If none is found, all .phpt tests will be tried instead.</doc>
        !          67286:    </phpunit>
        !          67287:    <tapoutput>
        !          67288:     <shortopt>t</shortopt>
        !          67289:     <doc>Output run-tests.log in TAP-compliant format</doc>
        !          67290:    </tapoutput>
        !          67291:    <cgi>
        !          67292:     <shortopt>c</shortopt>
        !          67293:     <doc>CGI php executable (needed for tests with POST/GET section)</doc>
        !          67294:     <arg>PHPCGI</arg>
        !          67295:    </cgi>
        !          67296:    <coverage>
        !          67297:     <shortopt>x</shortopt>
        !          67298:     <doc>Generate a code coverage report (requires Xdebug 2.0.0+)</doc>
        !          67299:    </coverage>
        !          67300:   </options>
        !          67301:   <doc>[testfile|dir ...]
        !          67302: Run regression tests with PHP&#039;s regression testing script (run-tests.php).</doc>
        !          67303:  </run-tests>
        !          67304: </commands><?php
        !          67305: /**
        !          67306:  * PEAR_Common, the base class for the PEAR Installer
        !          67307:  *
        !          67308:  * PHP versions 4 and 5
        !          67309:  *
        !          67310:  * @category   pear
        !          67311:  * @package    PEAR
        !          67312:  * @author     Stig Bakken <ssb@php.net>
        !          67313:  * @author     Tomas V. V. Cox <cox@idecnet.com>
        !          67314:  * @author     Greg Beaver <cellog@php.net>
        !          67315:  * @copyright  1997-2009 The Authors
        !          67316:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          67317:  * @version    CVS: $Id: Common.php 313023 2011-07-06 19:17:11Z dufuz $
        !          67318:  * @link       http://pear.php.net/package/PEAR
        !          67319:  * @since      File available since Release 0.1.0
        !          67320:  * @deprecated File deprecated since Release 1.4.0a1
        !          67321:  */
        !          67322: 
        !          67323: /**
        !          67324:  * Include error handling
        !          67325:  */
        !          67326: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
        !          67327: 
        !          67328: /**
        !          67329:  * PEAR_Common error when an invalid PHP file is passed to PEAR_Common::analyzeSourceCode()
        !          67330:  */
        !          67331: define('PEAR_COMMON_ERROR_INVALIDPHP', 1);
        !          67332: define('_PEAR_COMMON_PACKAGE_NAME_PREG', '[A-Za-z][a-zA-Z0-9_]+');
        !          67333: define('PEAR_COMMON_PACKAGE_NAME_PREG', '/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/');
        !          67334: 
        !          67335: // this should allow: 1, 1.0, 1.0RC1, 1.0dev, 1.0dev123234234234, 1.0a1, 1.0b1, 1.0pl1
        !          67336: define('_PEAR_COMMON_PACKAGE_VERSION_PREG', '\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?');
        !          67337: define('PEAR_COMMON_PACKAGE_VERSION_PREG', '/^' . _PEAR_COMMON_PACKAGE_VERSION_PREG . '\\z/i');
        !          67338: 
        !          67339: // XXX far from perfect :-)
        !          67340: define('_PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '(' . _PEAR_COMMON_PACKAGE_NAME_PREG .
        !          67341:     ')(-([.0-9a-zA-Z]+))?');
        !          67342: define('PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_PACKAGE_DOWNLOAD_PREG .
        !          67343:     '\\z/');
        !          67344: 
        !          67345: define('_PEAR_CHANNELS_NAME_PREG', '[A-Za-z][a-zA-Z0-9\.]+');
        !          67346: define('PEAR_CHANNELS_NAME_PREG', '/^' . _PEAR_CHANNELS_NAME_PREG . '\\z/');
        !          67347: 
        !          67348: // this should allow any dns or IP address, plus a path - NO UNDERSCORES ALLOWED
        !          67349: define('_PEAR_CHANNELS_SERVER_PREG', '[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*(\/[a-zA-Z0-9\-]+)*');
        !          67350: define('PEAR_CHANNELS_SERVER_PREG', '/^' . _PEAR_CHANNELS_SERVER_PREG . '\\z/i');
        !          67351: 
        !          67352: define('_PEAR_CHANNELS_PACKAGE_PREG',  '(' ._PEAR_CHANNELS_SERVER_PREG . ')\/('
        !          67353:          . _PEAR_COMMON_PACKAGE_NAME_PREG . ')');
        !          67354: define('PEAR_CHANNELS_PACKAGE_PREG', '/^' . _PEAR_CHANNELS_PACKAGE_PREG . '\\z/i');
        !          67355: 
        !          67356: define('_PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '(' . _PEAR_CHANNELS_NAME_PREG . ')::('
        !          67357:     . _PEAR_COMMON_PACKAGE_NAME_PREG . ')(-([.0-9a-zA-Z]+))?');
        !          67358: define('PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_CHANNEL_DOWNLOAD_PREG . '\\z/');
        !          67359: 
        !          67360: /**
        !          67361:  * List of temporary files and directories registered by
        !          67362:  * PEAR_Common::addTempFile().
        !          67363:  * @var array
        !          67364:  */
        !          67365: $GLOBALS['_PEAR_Common_tempfiles'] = array();
        !          67366: 
        !          67367: /**
        !          67368:  * Valid maintainer roles
        !          67369:  * @var array
        !          67370:  */
        !          67371: $GLOBALS['_PEAR_Common_maintainer_roles'] = array('lead','developer','contributor','helper');
        !          67372: 
        !          67373: /**
        !          67374:  * Valid release states
        !          67375:  * @var array
        !          67376:  */
        !          67377: $GLOBALS['_PEAR_Common_release_states'] = array('alpha','beta','stable','snapshot','devel');
        !          67378: 
        !          67379: /**
        !          67380:  * Valid dependency types
        !          67381:  * @var array
        !          67382:  */
        !          67383: $GLOBALS['_PEAR_Common_dependency_types'] = array('pkg','ext','php','prog','ldlib','rtlib','os','websrv','sapi');
        !          67384: 
        !          67385: /**
        !          67386:  * Valid dependency relations
        !          67387:  * @var array
        !          67388:  */
        !          67389: $GLOBALS['_PEAR_Common_dependency_relations'] = array('has','eq','lt','le','gt','ge','not', 'ne');
        !          67390: 
        !          67391: /**
        !          67392:  * Valid file roles
        !          67393:  * @var array
        !          67394:  */
        !          67395: $GLOBALS['_PEAR_Common_file_roles'] = array('php','ext','test','doc','data','src','script');
        !          67396: 
        !          67397: /**
        !          67398:  * Valid replacement types
        !          67399:  * @var array
        !          67400:  */
        !          67401: $GLOBALS['_PEAR_Common_replacement_types'] = array('php-const', 'pear-config', 'package-info');
        !          67402: 
        !          67403: /**
        !          67404:  * Valid "provide" types
        !          67405:  * @var array
        !          67406:  */
        !          67407: $GLOBALS['_PEAR_Common_provide_types'] = array('ext', 'prog', 'class', 'function', 'feature', 'api');
        !          67408: 
        !          67409: /**
        !          67410:  * Valid "provide" types
        !          67411:  * @var array
        !          67412:  */
        !          67413: $GLOBALS['_PEAR_Common_script_phases'] = array('pre-install', 'post-install', 'pre-uninstall', 'post-uninstall', 'pre-build', 'post-build', 'pre-configure', 'post-configure', 'pre-setup', 'post-setup');
        !          67414: 
        !          67415: /**
        !          67416:  * Class providing common functionality for PEAR administration classes.
        !          67417:  * @category   pear
        !          67418:  * @package    PEAR
        !          67419:  * @author     Stig Bakken <ssb@php.net>
        !          67420:  * @author     Tomas V. V. Cox <cox@idecnet.com>
        !          67421:  * @author     Greg Beaver <cellog@php.net>
        !          67422:  * @copyright  1997-2009 The Authors
        !          67423:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          67424:  * @version    Release: 1.9.4
        !          67425:  * @link       http://pear.php.net/package/PEAR
        !          67426:  * @since      Class available since Release 1.4.0a1
        !          67427:  * @deprecated This class will disappear, and its components will be spread
        !          67428:  *             into smaller classes, like the AT&T breakup, as of Release 1.4.0a1
        !          67429:  */
        !          67430: class PEAR_Common extends PEAR
        !          67431: {
        !          67432:     /**
        !          67433:      * User Interface object (PEAR_Frontend_* class).  If null,
        !          67434:      * the log() method uses print.
        !          67435:      * @var object
        !          67436:      */
        !          67437:     var $ui = null;
        !          67438: 
        !          67439:     /**
        !          67440:      * Configuration object (PEAR_Config).
        !          67441:      * @var PEAR_Config
        !          67442:      */
        !          67443:     var $config = null;
        !          67444: 
        !          67445:     /** stack of elements, gives some sort of XML context */
        !          67446:     var $element_stack = array();
        !          67447: 
        !          67448:     /** name of currently parsed XML element */
        !          67449:     var $current_element;
        !          67450: 
        !          67451:     /** array of attributes of the currently parsed XML element */
        !          67452:     var $current_attributes = array();
        !          67453: 
        !          67454:     /** assoc with information about a package */
        !          67455:     var $pkginfo = array();
        !          67456: 
        !          67457:     var $current_path = null;
        !          67458: 
        !          67459:     /**
        !          67460:      * Flag variable used to mark a valid package file
        !          67461:      * @var boolean
        !          67462:      * @access private
        !          67463:      */
        !          67464:     var $_validPackageFile;
        !          67465: 
        !          67466:     /**
        !          67467:      * PEAR_Common constructor
        !          67468:      *
        !          67469:      * @access public
        !          67470:      */
        !          67471:     function PEAR_Common()
        !          67472:     {
        !          67473:         parent::PEAR();
        !          67474:         $this->config = &PEAR_Config::singleton();
        !          67475:         $this->debug = $this->config->get('verbose');
        !          67476:     }
        !          67477: 
        !          67478:     /**
        !          67479:      * PEAR_Common destructor
        !          67480:      *
        !          67481:      * @access private
        !          67482:      */
        !          67483:     function _PEAR_Common()
        !          67484:     {
        !          67485:         // doesn't work due to bug #14744
        !          67486:         //$tempfiles = $this->_tempfiles;
        !          67487:         $tempfiles =& $GLOBALS['_PEAR_Common_tempfiles'];
        !          67488:         while ($file = array_shift($tempfiles)) {
        !          67489:             if (@is_dir($file)) {
        !          67490:                 if (!class_exists('System')) {
        !          67491:                     require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
        !          67492:                 }
        !          67493: 
        !          67494:                 System::rm(array('-rf', $file));
        !          67495:             } elseif (file_exists($file)) {
        !          67496:                 unlink($file);
        !          67497:             }
        !          67498:         }
        !          67499:     }
        !          67500: 
        !          67501:     /**
        !          67502:      * Register a temporary file or directory.  When the destructor is
        !          67503:      * executed, all registered temporary files and directories are
        !          67504:      * removed.
        !          67505:      *
        !          67506:      * @param string  $file  name of file or directory
        !          67507:      *
        !          67508:      * @return void
        !          67509:      *
        !          67510:      * @access public
        !          67511:      */
        !          67512:     function addTempFile($file)
        !          67513:     {
        !          67514:         if (!class_exists('PEAR_Frontend')) {
        !          67515:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Frontend.php';
        !          67516:         }
        !          67517:         PEAR_Frontend::addTempFile($file);
        !          67518:     }
        !          67519: 
        !          67520:     /**
        !          67521:      * Wrapper to System::mkDir(), creates a directory as well as
        !          67522:      * any necessary parent directories.
        !          67523:      *
        !          67524:      * @param string  $dir  directory name
        !          67525:      *
        !          67526:      * @return bool TRUE on success, or a PEAR error
        !          67527:      *
        !          67528:      * @access public
        !          67529:      */
        !          67530:     function mkDirHier($dir)
        !          67531:     {
        !          67532:         // Only used in Installer - move it there ?
        !          67533:         $this->log(2, "+ create dir $dir");
        !          67534:         if (!class_exists('System')) {
        !          67535:             require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
        !          67536:         }
        !          67537:         return System::mkDir(array('-p', $dir));
        !          67538:     }
        !          67539: 
        !          67540:     /**
        !          67541:      * Logging method.
        !          67542:      *
        !          67543:      * @param int    $level  log level (0 is quiet, higher is noisier)
        !          67544:      * @param string $msg    message to write to the log
        !          67545:      *
        !          67546:      * @return void
        !          67547:      *
        !          67548:      * @access public
        !          67549:      * @static
        !          67550:      */
        !          67551:     function log($level, $msg, $append_crlf = true)
        !          67552:     {
        !          67553:         if ($this->debug >= $level) {
        !          67554:             if (!class_exists('PEAR_Frontend')) {
        !          67555:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Frontend.php';
        !          67556:             }
        !          67557: 
        !          67558:             $ui = &PEAR_Frontend::singleton();
        !          67559:             if (is_a($ui, 'PEAR_Frontend')) {
        !          67560:                 $ui->log($msg, $append_crlf);
        !          67561:             } else {
        !          67562:                 print "$msg\n";
        !          67563:             }
        !          67564:         }
        !          67565:     }
        !          67566: 
        !          67567:     /**
        !          67568:      * Create and register a temporary directory.
        !          67569:      *
        !          67570:      * @param string $tmpdir (optional) Directory to use as tmpdir.
        !          67571:      *                       Will use system defaults (for example
        !          67572:      *                       /tmp or c:\windows\temp) if not specified
        !          67573:      *
        !          67574:      * @return string name of created directory
        !          67575:      *
        !          67576:      * @access public
        !          67577:      */
        !          67578:     function mkTempDir($tmpdir = '')
        !          67579:     {
        !          67580:         $topt = $tmpdir ? array('-t', $tmpdir) : array();
        !          67581:         $topt = array_merge($topt, array('-d', 'pear'));
        !          67582:         if (!class_exists('System')) {
        !          67583:             require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
        !          67584:         }
        !          67585: 
        !          67586:         if (!$tmpdir = System::mktemp($topt)) {
        !          67587:             return false;
        !          67588:         }
        !          67589: 
        !          67590:         $this->addTempFile($tmpdir);
        !          67591:         return $tmpdir;
        !          67592:     }
        !          67593: 
        !          67594:     /**
        !          67595:      * Set object that represents the frontend to be used.
        !          67596:      *
        !          67597:      * @param  object Reference of the frontend object
        !          67598:      * @return void
        !          67599:      * @access public
        !          67600:      */
        !          67601:     function setFrontendObject(&$ui)
        !          67602:     {
        !          67603:         $this->ui = &$ui;
        !          67604:     }
        !          67605: 
        !          67606:     /**
        !          67607:      * Return an array containing all of the states that are more stable than
        !          67608:      * or equal to the passed in state
        !          67609:      *
        !          67610:      * @param string Release state
        !          67611:      * @param boolean Determines whether to include $state in the list
        !          67612:      * @return false|array False if $state is not a valid release state
        !          67613:      */
        !          67614:     function betterStates($state, $include = false)
        !          67615:     {
        !          67616:         static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
        !          67617:         $i = array_search($state, $states);
        !          67618:         if ($i === false) {
        !          67619:             return false;
        !          67620:         }
        !          67621:         if ($include) {
        !          67622:             $i--;
        !          67623:         }
        !          67624:         return array_slice($states, $i + 1);
        !          67625:     }
        !          67626: 
        !          67627:     /**
        !          67628:      * Get the valid roles for a PEAR package maintainer
        !          67629:      *
        !          67630:      * @return array
        !          67631:      * @static
        !          67632:      */
        !          67633:     function getUserRoles()
        !          67634:     {
        !          67635:         return $GLOBALS['_PEAR_Common_maintainer_roles'];
        !          67636:     }
        !          67637: 
        !          67638:     /**
        !          67639:      * Get the valid package release states of packages
        !          67640:      *
        !          67641:      * @return array
        !          67642:      * @static
        !          67643:      */
        !          67644:     function getReleaseStates()
        !          67645:     {
        !          67646:         return $GLOBALS['_PEAR_Common_release_states'];
        !          67647:     }
        !          67648: 
        !          67649:     /**
        !          67650:      * Get the implemented dependency types (php, ext, pkg etc.)
        !          67651:      *
        !          67652:      * @return array
        !          67653:      * @static
        !          67654:      */
        !          67655:     function getDependencyTypes()
        !          67656:     {
        !          67657:         return $GLOBALS['_PEAR_Common_dependency_types'];
        !          67658:     }
        !          67659: 
        !          67660:     /**
        !          67661:      * Get the implemented dependency relations (has, lt, ge etc.)
        !          67662:      *
        !          67663:      * @return array
        !          67664:      * @static
        !          67665:      */
        !          67666:     function getDependencyRelations()
        !          67667:     {
        !          67668:         return $GLOBALS['_PEAR_Common_dependency_relations'];
        !          67669:     }
        !          67670: 
        !          67671:     /**
        !          67672:      * Get the implemented file roles
        !          67673:      *
        !          67674:      * @return array
        !          67675:      * @static
        !          67676:      */
        !          67677:     function getFileRoles()
        !          67678:     {
        !          67679:         return $GLOBALS['_PEAR_Common_file_roles'];
        !          67680:     }
        !          67681: 
        !          67682:     /**
        !          67683:      * Get the implemented file replacement types in
        !          67684:      *
        !          67685:      * @return array
        !          67686:      * @static
        !          67687:      */
        !          67688:     function getReplacementTypes()
        !          67689:     {
        !          67690:         return $GLOBALS['_PEAR_Common_replacement_types'];
        !          67691:     }
        !          67692: 
        !          67693:     /**
        !          67694:      * Get the implemented file replacement types in
        !          67695:      *
        !          67696:      * @return array
        !          67697:      * @static
        !          67698:      */
        !          67699:     function getProvideTypes()
        !          67700:     {
        !          67701:         return $GLOBALS['_PEAR_Common_provide_types'];
        !          67702:     }
        !          67703: 
        !          67704:     /**
        !          67705:      * Get the implemented file replacement types in
        !          67706:      *
        !          67707:      * @return array
        !          67708:      * @static
        !          67709:      */
        !          67710:     function getScriptPhases()
        !          67711:     {
        !          67712:         return $GLOBALS['_PEAR_Common_script_phases'];
        !          67713:     }
        !          67714: 
        !          67715:     /**
        !          67716:      * Test whether a string contains a valid package name.
        !          67717:      *
        !          67718:      * @param string $name the package name to test
        !          67719:      *
        !          67720:      * @return bool
        !          67721:      *
        !          67722:      * @access public
        !          67723:      */
        !          67724:     function validPackageName($name)
        !          67725:     {
        !          67726:         return (bool)preg_match(PEAR_COMMON_PACKAGE_NAME_PREG, $name);
        !          67727:     }
        !          67728: 
        !          67729:     /**
        !          67730:      * Test whether a string contains a valid package version.
        !          67731:      *
        !          67732:      * @param string $ver the package version to test
        !          67733:      *
        !          67734:      * @return bool
        !          67735:      *
        !          67736:      * @access public
        !          67737:      */
        !          67738:     function validPackageVersion($ver)
        !          67739:     {
        !          67740:         return (bool)preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver);
        !          67741:     }
        !          67742: 
        !          67743:     /**
        !          67744:      * @param string $path relative or absolute include path
        !          67745:      * @return boolean
        !          67746:      * @static
        !          67747:      */
        !          67748:     function isIncludeable($path)
        !          67749:     {
        !          67750:         if (file_exists($path) && is_readable($path)) {
        !          67751:             return true;
        !          67752:         }
        !          67753: 
        !          67754:         $ipath = explode(PATH_SEPARATOR, ini_get('include_path'));
        !          67755:         foreach ($ipath as $include) {
        !          67756:             $test = realpath($include . DIRECTORY_SEPARATOR . $path);
        !          67757:             if (file_exists($test) && is_readable($test)) {
        !          67758:                 return true;
        !          67759:             }
        !          67760:         }
        !          67761: 
        !          67762:         return false;
        !          67763:     }
        !          67764: 
        !          67765:     function _postProcessChecks($pf)
        !          67766:     {
        !          67767:         if (!PEAR::isError($pf)) {
        !          67768:             return $this->_postProcessValidPackagexml($pf);
        !          67769:         }
        !          67770: 
        !          67771:         $errs = $pf->getUserinfo();
        !          67772:         if (is_array($errs)) {
        !          67773:             foreach ($errs as $error) {
        !          67774:                 $e = $this->raiseError($error['message'], $error['code'], null, null, $error);
        !          67775:             }
        !          67776:         }
        !          67777: 
        !          67778:         return $pf;
        !          67779:     }
        !          67780: 
        !          67781:     /**
        !          67782:      * Returns information about a package file.  Expects the name of
        !          67783:      * a gzipped tar file as input.
        !          67784:      *
        !          67785:      * @param string  $file  name of .tgz file
        !          67786:      *
        !          67787:      * @return array  array with package information
        !          67788:      *
        !          67789:      * @access public
        !          67790:      * @deprecated use PEAR_PackageFile->fromTgzFile() instead
        !          67791:      *
        !          67792:      */
        !          67793:     function infoFromTgzFile($file)
        !          67794:     {
        !          67795:         $packagefile = &new PEAR_PackageFile($this->config);
        !          67796:         $pf = &$packagefile->fromTgzFile($file, PEAR_VALIDATE_NORMAL);
        !          67797:         return $this->_postProcessChecks($pf);
        !          67798:     }
        !          67799: 
        !          67800:     /**
        !          67801:      * Returns information about a package file.  Expects the name of
        !          67802:      * a package xml file as input.
        !          67803:      *
        !          67804:      * @param string  $descfile  name of package xml file
        !          67805:      *
        !          67806:      * @return array  array with package information
        !          67807:      *
        !          67808:      * @access public
        !          67809:      * @deprecated use PEAR_PackageFile->fromPackageFile() instead
        !          67810:      *
        !          67811:      */
        !          67812:     function infoFromDescriptionFile($descfile)
        !          67813:     {
        !          67814:         $packagefile = &new PEAR_PackageFile($this->config);
        !          67815:         $pf = &$packagefile->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
        !          67816:         return $this->_postProcessChecks($pf);
        !          67817:     }
        !          67818: 
        !          67819:     /**
        !          67820:      * Returns information about a package file.  Expects the contents
        !          67821:      * of a package xml file as input.
        !          67822:      *
        !          67823:      * @param string  $data  contents of package.xml file
        !          67824:      *
        !          67825:      * @return array   array with package information
        !          67826:      *
        !          67827:      * @access public
        !          67828:      * @deprecated use PEAR_PackageFile->fromXmlstring() instead
        !          67829:      *
        !          67830:      */
        !          67831:     function infoFromString($data)
        !          67832:     {
        !          67833:         $packagefile = &new PEAR_PackageFile($this->config);
        !          67834:         $pf = &$packagefile->fromXmlString($data, PEAR_VALIDATE_NORMAL, false);
        !          67835:         return $this->_postProcessChecks($pf);
        !          67836:     }
        !          67837: 
        !          67838:     /**
        !          67839:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
        !          67840:      * @return array
        !          67841:      */
        !          67842:     function _postProcessValidPackagexml(&$pf)
        !          67843:     {
        !          67844:         if (!is_a($pf, 'PEAR_PackageFile_v2')) {
        !          67845:             $this->pkginfo = $pf->toArray();
        !          67846:             return $this->pkginfo;
        !          67847:         }
        !          67848: 
        !          67849:         // sort of make this into a package.xml 1.0-style array
        !          67850:         // changelog is not converted to old format.
        !          67851:         $arr = $pf->toArray(true);
        !          67852:         $arr = array_merge($arr, $arr['old']);
        !          67853:         unset($arr['old'], $arr['xsdversion'], $arr['contents'], $arr['compatible'],
        !          67854:               $arr['channel'], $arr['uri'], $arr['dependencies'], $arr['phprelease'],
        !          67855:               $arr['extsrcrelease'], $arr['zendextsrcrelease'], $arr['extbinrelease'],
        !          67856:               $arr['zendextbinrelease'], $arr['bundle'], $arr['lead'], $arr['developer'],
        !          67857:               $arr['helper'], $arr['contributor']);
        !          67858:         $arr['filelist'] = $pf->getFilelist();
        !          67859:         $this->pkginfo = $arr;
        !          67860:         return $arr;
        !          67861:     }
        !          67862: 
        !          67863:     /**
        !          67864:      * Returns package information from different sources
        !          67865:      *
        !          67866:      * This method is able to extract information about a package
        !          67867:      * from a .tgz archive or from a XML package definition file.
        !          67868:      *
        !          67869:      * @access public
        !          67870:      * @param  string Filename of the source ('package.xml', '<package>.tgz')
        !          67871:      * @return string
        !          67872:      * @deprecated use PEAR_PackageFile->fromAnyFile() instead
        !          67873:      */
        !          67874:     function infoFromAny($info)
        !          67875:     {
        !          67876:         if (is_string($info) && file_exists($info)) {
        !          67877:             $packagefile = &new PEAR_PackageFile($this->config);
        !          67878:             $pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL);
        !          67879:             if (PEAR::isError($pf)) {
        !          67880:                 $errs = $pf->getUserinfo();
        !          67881:                 if (is_array($errs)) {
        !          67882:                     foreach ($errs as $error) {
        !          67883:                         $e = $this->raiseError($error['message'], $error['code'], null, null, $error);
        !          67884:                     }
        !          67885:                 }
        !          67886: 
        !          67887:                 return $pf;
        !          67888:             }
        !          67889: 
        !          67890:             return $this->_postProcessValidPackagexml($pf);
        !          67891:         }
        !          67892: 
        !          67893:         return $info;
        !          67894:     }
        !          67895: 
        !          67896:     /**
        !          67897:      * Return an XML document based on the package info (as returned
        !          67898:      * by the PEAR_Common::infoFrom* methods).
        !          67899:      *
        !          67900:      * @param array  $pkginfo  package info
        !          67901:      *
        !          67902:      * @return string XML data
        !          67903:      *
        !          67904:      * @access public
        !          67905:      * @deprecated use a PEAR_PackageFile_v* object's generator instead
        !          67906:      */
        !          67907:     function xmlFromInfo($pkginfo)
        !          67908:     {
        !          67909:         $config      = &PEAR_Config::singleton();
        !          67910:         $packagefile = &new PEAR_PackageFile($config);
        !          67911:         $pf = &$packagefile->fromArray($pkginfo);
        !          67912:         $gen = &$pf->getDefaultGenerator();
        !          67913:         return $gen->toXml(PEAR_VALIDATE_PACKAGING);
        !          67914:     }
        !          67915: 
        !          67916:     /**
        !          67917:      * Validate XML package definition file.
        !          67918:      *
        !          67919:      * @param  string $info Filename of the package archive or of the
        !          67920:      *                package definition file
        !          67921:      * @param  array $errors Array that will contain the errors
        !          67922:      * @param  array $warnings Array that will contain the warnings
        !          67923:      * @param  string $dir_prefix (optional) directory where source files
        !          67924:      *                may be found, or empty if they are not available
        !          67925:      * @access public
        !          67926:      * @return boolean
        !          67927:      * @deprecated use the validation of PEAR_PackageFile objects
        !          67928:      */
        !          67929:     function validatePackageInfo($info, &$errors, &$warnings, $dir_prefix = '')
        !          67930:     {
        !          67931:         $config      = &PEAR_Config::singleton();
        !          67932:         $packagefile = &new PEAR_PackageFile($config);
        !          67933:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          67934:         if (strpos($info, '<?xml') !== false) {
        !          67935:             $pf = &$packagefile->fromXmlString($info, PEAR_VALIDATE_NORMAL, '');
        !          67936:         } else {
        !          67937:             $pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL);
        !          67938:         }
        !          67939: 
        !          67940:         PEAR::staticPopErrorHandling();
        !          67941:         if (PEAR::isError($pf)) {
        !          67942:             $errs = $pf->getUserinfo();
        !          67943:             if (is_array($errs)) {
        !          67944:                 foreach ($errs as $error) {
        !          67945:                     if ($error['level'] == 'error') {
        !          67946:                         $errors[] = $error['message'];
        !          67947:                     } else {
        !          67948:                         $warnings[] = $error['message'];
        !          67949:                     }
        !          67950:                 }
        !          67951:             }
        !          67952: 
        !          67953:             return false;
        !          67954:         }
        !          67955: 
        !          67956:         return true;
        !          67957:     }
        !          67958: 
        !          67959:     /**
        !          67960:      * Build a "provides" array from data returned by
        !          67961:      * analyzeSourceCode().  The format of the built array is like
        !          67962:      * this:
        !          67963:      *
        !          67964:      *  array(
        !          67965:      *    'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
        !          67966:      *    ...
        !          67967:      *  )
        !          67968:      *
        !          67969:      *
        !          67970:      * @param array $srcinfo array with information about a source file
        !          67971:      * as returned by the analyzeSourceCode() method.
        !          67972:      *
        !          67973:      * @return void
        !          67974:      *
        !          67975:      * @access public
        !          67976:      *
        !          67977:      */
        !          67978:     function buildProvidesArray($srcinfo)
        !          67979:     {
        !          67980:         $file = basename($srcinfo['source_file']);
        !          67981:         $pn = '';
        !          67982:         if (isset($this->_packageName)) {
        !          67983:             $pn = $this->_packageName;
        !          67984:         }
        !          67985: 
        !          67986:         $pnl = strlen($pn);
        !          67987:         foreach ($srcinfo['declared_classes'] as $class) {
        !          67988:             $key = "class;$class";
        !          67989:             if (isset($this->pkginfo['provides'][$key])) {
        !          67990:                 continue;
        !          67991:             }
        !          67992: 
        !          67993:             $this->pkginfo['provides'][$key] =
        !          67994:                 array('file'=> $file, 'type' => 'class', 'name' => $class);
        !          67995:             if (isset($srcinfo['inheritance'][$class])) {
        !          67996:                 $this->pkginfo['provides'][$key]['extends'] =
        !          67997:                     $srcinfo['inheritance'][$class];
        !          67998:             }
        !          67999:         }
        !          68000: 
        !          68001:         foreach ($srcinfo['declared_methods'] as $class => $methods) {
        !          68002:             foreach ($methods as $method) {
        !          68003:                 $function = "$class::$method";
        !          68004:                 $key = "function;$function";
        !          68005:                 if ($method{0} == '_' || !strcasecmp($method, $class) ||
        !          68006:                     isset($this->pkginfo['provides'][$key])) {
        !          68007:                     continue;
        !          68008:                 }
        !          68009: 
        !          68010:                 $this->pkginfo['provides'][$key] =
        !          68011:                     array('file'=> $file, 'type' => 'function', 'name' => $function);
        !          68012:             }
        !          68013:         }
        !          68014: 
        !          68015:         foreach ($srcinfo['declared_functions'] as $function) {
        !          68016:             $key = "function;$function";
        !          68017:             if ($function{0} == '_' || isset($this->pkginfo['provides'][$key])) {
        !          68018:                 continue;
        !          68019:             }
        !          68020: 
        !          68021:             if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
        !          68022:                 $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
        !          68023:             }
        !          68024: 
        !          68025:             $this->pkginfo['provides'][$key] =
        !          68026:                 array('file'=> $file, 'type' => 'function', 'name' => $function);
        !          68027:         }
        !          68028:     }
        !          68029: 
        !          68030:     /**
        !          68031:      * Analyze the source code of the given PHP file
        !          68032:      *
        !          68033:      * @param  string Filename of the PHP file
        !          68034:      * @return mixed
        !          68035:      * @access public
        !          68036:      */
        !          68037:     function analyzeSourceCode($file)
        !          68038:     {
        !          68039:         if (!class_exists('PEAR_PackageFile_v2_Validator')) {
        !          68040:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2/Validator.php';
        !          68041:         }
        !          68042: 
        !          68043:         $a = new PEAR_PackageFile_v2_Validator;
        !          68044:         return $a->analyzeSourceCode($file);
        !          68045:     }
        !          68046: 
        !          68047:     function detectDependencies($any, $status_callback = null)
        !          68048:     {
        !          68049:         if (!function_exists("token_get_all")) {
        !          68050:             return false;
        !          68051:         }
        !          68052: 
        !          68053:         if (PEAR::isError($info = $this->infoFromAny($any))) {
        !          68054:             return $this->raiseError($info);
        !          68055:         }
        !          68056: 
        !          68057:         if (!is_array($info)) {
        !          68058:             return false;
        !          68059:         }
        !          68060: 
        !          68061:         $deps = array();
        !          68062:         $used_c = $decl_c = $decl_f = $decl_m = array();
        !          68063:         foreach ($info['filelist'] as $file => $fa) {
        !          68064:             $tmp = $this->analyzeSourceCode($file);
        !          68065:             $used_c = @array_merge($used_c, $tmp['used_classes']);
        !          68066:             $decl_c = @array_merge($decl_c, $tmp['declared_classes']);
        !          68067:             $decl_f = @array_merge($decl_f, $tmp['declared_functions']);
        !          68068:             $decl_m = @array_merge($decl_m, $tmp['declared_methods']);
        !          68069:             $inheri = @array_merge($inheri, $tmp['inheritance']);
        !          68070:         }
        !          68071: 
        !          68072:         $used_c = array_unique($used_c);
        !          68073:         $decl_c = array_unique($decl_c);
        !          68074:         $undecl_c = array_diff($used_c, $decl_c);
        !          68075: 
        !          68076:         return array('used_classes' => $used_c,
        !          68077:                      'declared_classes' => $decl_c,
        !          68078:                      'declared_methods' => $decl_m,
        !          68079:                      'declared_functions' => $decl_f,
        !          68080:                      'undeclared_classes' => $undecl_c,
        !          68081:                      'inheritance' => $inheri,
        !          68082:                      );
        !          68083:     }
        !          68084: 
        !          68085:     /**
        !          68086:      * Download a file through HTTP.  Considers suggested file name in
        !          68087:      * Content-disposition: header and can run a callback function for
        !          68088:      * different events.  The callback will be called with two
        !          68089:      * parameters: the callback type, and parameters.  The implemented
        !          68090:      * callback types are:
        !          68091:      *
        !          68092:      *  'setup'       called at the very beginning, parameter is a UI object
        !          68093:      *                that should be used for all output
        !          68094:      *  'message'     the parameter is a string with an informational message
        !          68095:      *  'saveas'      may be used to save with a different file name, the
        !          68096:      *                parameter is the filename that is about to be used.
        !          68097:      *                If a 'saveas' callback returns a non-empty string,
        !          68098:      *                that file name will be used as the filename instead.
        !          68099:      *                Note that $save_dir will not be affected by this, only
        !          68100:      *                the basename of the file.
        !          68101:      *  'start'       download is starting, parameter is number of bytes
        !          68102:      *                that are expected, or -1 if unknown
        !          68103:      *  'bytesread'   parameter is the number of bytes read so far
        !          68104:      *  'done'        download is complete, parameter is the total number
        !          68105:      *                of bytes read
        !          68106:      *  'connfailed'  if the TCP connection fails, this callback is called
        !          68107:      *                with array(host,port,errno,errmsg)
        !          68108:      *  'writefailed' if writing to disk fails, this callback is called
        !          68109:      *                with array(destfile,errmsg)
        !          68110:      *
        !          68111:      * If an HTTP proxy has been configured (http_proxy PEAR_Config
        !          68112:      * setting), the proxy will be used.
        !          68113:      *
        !          68114:      * @param string  $url       the URL to download
        !          68115:      * @param object  $ui        PEAR_Frontend_* instance
        !          68116:      * @param object  $config    PEAR_Config instance
        !          68117:      * @param string  $save_dir  (optional) directory to save file in
        !          68118:      * @param mixed   $callback  (optional) function/method to call for status
        !          68119:      *                           updates
        !          68120:      *
        !          68121:      * @return string  Returns the full path of the downloaded file or a PEAR
        !          68122:      *                 error on failure.  If the error is caused by
        !          68123:      *                 socket-related errors, the error object will
        !          68124:      *                 have the fsockopen error code available through
        !          68125:      *                 getCode().
        !          68126:      *
        !          68127:      * @access public
        !          68128:      * @deprecated in favor of PEAR_Downloader::downloadHttp()
        !          68129:      */
        !          68130:     function downloadHttp($url, &$ui, $save_dir = '.', $callback = null)
        !          68131:     {
        !          68132:         if (!class_exists('PEAR_Downloader')) {
        !          68133:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Downloader.php';
        !          68134:         }
        !          68135:         return PEAR_Downloader::downloadHttp($url, $ui, $save_dir, $callback);
        !          68136:     }
        !          68137: }
        !          68138: 
        !          68139: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Config.php';
        !          68140: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile.php';<?php
        !          68141: /**
        !          68142:  * PEAR_Config, customized configuration handling for the PEAR Installer
        !          68143:  *
        !          68144:  * PHP versions 4 and 5
        !          68145:  *
        !          68146:  * @category   pear
        !          68147:  * @package    PEAR
        !          68148:  * @author     Stig Bakken <ssb@php.net>
        !          68149:  * @author     Greg Beaver <cellog@php.net>
        !          68150:  * @copyright  1997-2009 The Authors
        !          68151:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          68152:  * @version    CVS: $Id: Config.php 313023 2011-07-06 19:17:11Z dufuz $
        !          68153:  * @link       http://pear.php.net/package/PEAR
        !          68154:  * @since      File available since Release 0.1
        !          68155:  */
        !          68156: 
        !          68157: /**
        !          68158:  * Required for error handling
        !          68159:  */
        !          68160: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
        !          68161: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Registry.php';
        !          68162: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Installer/Role.php';
        !          68163: require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
        !          68164: 
        !          68165: /**
        !          68166:  * Last created PEAR_Config instance.
        !          68167:  * @var object
        !          68168:  */
        !          68169: $GLOBALS['_PEAR_Config_instance'] = null;
        !          68170: if (!defined('PEAR_INSTALL_DIR') || !PEAR_INSTALL_DIR) {
        !          68171:     $PEAR_INSTALL_DIR = PHP_LIBDIR . DIRECTORY_SEPARATOR . 'pear';
        !          68172: } else {
        !          68173:     $PEAR_INSTALL_DIR = PEAR_INSTALL_DIR;
        !          68174: }
        !          68175: 
        !          68176: // Below we define constants with default values for all configuration
        !          68177: // parameters except username/password.  All of them can have their
        !          68178: // defaults set through environment variables.  The reason we use the
        !          68179: // PHP_ prefix is for some security, PHP protects environment
        !          68180: // variables starting with PHP_*.
        !          68181: 
        !          68182: // default channel and preferred mirror is based on whether we are invoked through
        !          68183: // the "pear" or the "pecl" command
        !          68184: if (!defined('PEAR_RUNTYPE')) {
        !          68185:     define('PEAR_RUNTYPE', 'pear');
        !          68186: }
        !          68187: 
        !          68188: if (PEAR_RUNTYPE == 'pear') {
        !          68189:     define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pear.php.net');
        !          68190: } else {
        !          68191:     define('PEAR_CONFIG_DEFAULT_CHANNEL', 'pecl.php.net');
        !          68192: }
        !          68193: 
        !          68194: if (getenv('PHP_PEAR_SYSCONF_DIR')) {
        !          68195:     define('PEAR_CONFIG_SYSCONFDIR', getenv('PHP_PEAR_SYSCONF_DIR'));
        !          68196: } elseif (getenv('SystemRoot')) {
        !          68197:     define('PEAR_CONFIG_SYSCONFDIR', getenv('SystemRoot'));
        !          68198: } else {
        !          68199:     define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR);
        !          68200: }
        !          68201: 
        !          68202: // Default for master_server
        !          68203: if (getenv('PHP_PEAR_MASTER_SERVER')) {
        !          68204:     define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', getenv('PHP_PEAR_MASTER_SERVER'));
        !          68205: } else {
        !          68206:     define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', 'pear.php.net');
        !          68207: }
        !          68208: 
        !          68209: // Default for http_proxy
        !          68210: if (getenv('PHP_PEAR_HTTP_PROXY')) {
        !          68211:     define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('PHP_PEAR_HTTP_PROXY'));
        !          68212: } elseif (getenv('http_proxy')) {
        !          68213:     define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('http_proxy'));
        !          68214: } else {
        !          68215:     define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', '');
        !          68216: }
        !          68217: 
        !          68218: // Default for php_dir
        !          68219: if (getenv('PHP_PEAR_INSTALL_DIR')) {
        !          68220:     define('PEAR_CONFIG_DEFAULT_PHP_DIR', getenv('PHP_PEAR_INSTALL_DIR'));
        !          68221: } else {
        !          68222:     if (@file_exists($PEAR_INSTALL_DIR) && is_dir($PEAR_INSTALL_DIR)) {
        !          68223:         define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR);
        !          68224:     } else {
        !          68225:         define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR);
        !          68226:     }
        !          68227: }
        !          68228: 
        !          68229: // Default for ext_dir
        !          68230: if (getenv('PHP_PEAR_EXTENSION_DIR')) {
        !          68231:     define('PEAR_CONFIG_DEFAULT_EXT_DIR', getenv('PHP_PEAR_EXTENSION_DIR'));
        !          68232: } else {
        !          68233:     if (ini_get('extension_dir')) {
        !          68234:         define('PEAR_CONFIG_DEFAULT_EXT_DIR', ini_get('extension_dir'));
        !          68235:     } elseif (defined('PEAR_EXTENSION_DIR') &&
        !          68236:               file_exists(PEAR_EXTENSION_DIR) && is_dir(PEAR_EXTENSION_DIR)) {
        !          68237:         define('PEAR_CONFIG_DEFAULT_EXT_DIR', PEAR_EXTENSION_DIR);
        !          68238:     } elseif (defined('PHP_EXTENSION_DIR')) {
        !          68239:         define('PEAR_CONFIG_DEFAULT_EXT_DIR', PHP_EXTENSION_DIR);
        !          68240:     } else {
        !          68241:         define('PEAR_CONFIG_DEFAULT_EXT_DIR', '.');
        !          68242:     }
        !          68243: }
        !          68244: 
        !          68245: // Default for doc_dir
        !          68246: if (getenv('PHP_PEAR_DOC_DIR')) {
        !          68247:     define('PEAR_CONFIG_DEFAULT_DOC_DIR', getenv('PHP_PEAR_DOC_DIR'));
        !          68248: } else {
        !          68249:     define('PEAR_CONFIG_DEFAULT_DOC_DIR',
        !          68250:            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'docs');
        !          68251: }
        !          68252: 
        !          68253: // Default for bin_dir
        !          68254: if (getenv('PHP_PEAR_BIN_DIR')) {
        !          68255:     define('PEAR_CONFIG_DEFAULT_BIN_DIR', getenv('PHP_PEAR_BIN_DIR'));
        !          68256: } else {
        !          68257:     define('PEAR_CONFIG_DEFAULT_BIN_DIR', PHP_BINDIR);
        !          68258: }
        !          68259: 
        !          68260: // Default for data_dir
        !          68261: if (getenv('PHP_PEAR_DATA_DIR')) {
        !          68262:     define('PEAR_CONFIG_DEFAULT_DATA_DIR', getenv('PHP_PEAR_DATA_DIR'));
        !          68263: } else {
        !          68264:     define('PEAR_CONFIG_DEFAULT_DATA_DIR',
        !          68265:            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'data');
        !          68266: }
        !          68267: 
        !          68268: // Default for cfg_dir
        !          68269: if (getenv('PHP_PEAR_CFG_DIR')) {
        !          68270:     define('PEAR_CONFIG_DEFAULT_CFG_DIR', getenv('PHP_PEAR_CFG_DIR'));
        !          68271: } else {
        !          68272:     define('PEAR_CONFIG_DEFAULT_CFG_DIR',
        !          68273:            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'cfg');
        !          68274: }
        !          68275: 
        !          68276: // Default for www_dir
        !          68277: if (getenv('PHP_PEAR_WWW_DIR')) {
        !          68278:     define('PEAR_CONFIG_DEFAULT_WWW_DIR', getenv('PHP_PEAR_WWW_DIR'));
        !          68279: } else {
        !          68280:     define('PEAR_CONFIG_DEFAULT_WWW_DIR',
        !          68281:            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'www');
        !          68282: }
        !          68283: 
        !          68284: // Default for test_dir
        !          68285: if (getenv('PHP_PEAR_TEST_DIR')) {
        !          68286:     define('PEAR_CONFIG_DEFAULT_TEST_DIR', getenv('PHP_PEAR_TEST_DIR'));
        !          68287: } else {
        !          68288:     define('PEAR_CONFIG_DEFAULT_TEST_DIR',
        !          68289:            $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'tests');
        !          68290: }
        !          68291: 
        !          68292: // Default for temp_dir
1.1       misho    68293: if (getenv('PHP_PEAR_TEMP_DIR')) {
                   68294:     define('PEAR_CONFIG_DEFAULT_TEMP_DIR', getenv('PHP_PEAR_TEMP_DIR'));
                   68295: } else {
                   68296:     define('PEAR_CONFIG_DEFAULT_TEMP_DIR',
                   68297:            System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
                   68298:            DIRECTORY_SEPARATOR . 'temp');
                   68299: }
                   68300: 
1.1.1.2 ! misho    68301: // Default for cache_dir
        !          68302: if (getenv('PHP_PEAR_CACHE_DIR')) {
        !          68303:     define('PEAR_CONFIG_DEFAULT_CACHE_DIR', getenv('PHP_PEAR_CACHE_DIR'));
        !          68304: } else {
        !          68305:     define('PEAR_CONFIG_DEFAULT_CACHE_DIR',
        !          68306:            System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
        !          68307:            DIRECTORY_SEPARATOR . 'cache');
        !          68308: }
        !          68309: 
        !          68310: // Default for download_dir
        !          68311: if (getenv('PHP_PEAR_DOWNLOAD_DIR')) {
        !          68312:     define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR', getenv('PHP_PEAR_DOWNLOAD_DIR'));
        !          68313: } else {
        !          68314:     define('PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR',
        !          68315:            System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' .
        !          68316:            DIRECTORY_SEPARATOR . 'download');
        !          68317: }
        !          68318: 
        !          68319: // Default for php_bin
        !          68320: if (getenv('PHP_PEAR_PHP_BIN')) {
        !          68321:     define('PEAR_CONFIG_DEFAULT_PHP_BIN', getenv('PHP_PEAR_PHP_BIN'));
        !          68322: } else {
        !          68323:     define('PEAR_CONFIG_DEFAULT_PHP_BIN', PEAR_CONFIG_DEFAULT_BIN_DIR.
        !          68324:            DIRECTORY_SEPARATOR.'php'.(OS_WINDOWS ? '.exe' : ''));
        !          68325: }
        !          68326: 
        !          68327: // Default for verbose
        !          68328: if (getenv('PHP_PEAR_VERBOSE')) {
        !          68329:     define('PEAR_CONFIG_DEFAULT_VERBOSE', getenv('PHP_PEAR_VERBOSE'));
        !          68330: } else {
        !          68331:     define('PEAR_CONFIG_DEFAULT_VERBOSE', 1);
        !          68332: }
        !          68333: 
        !          68334: // Default for preferred_state
        !          68335: if (getenv('PHP_PEAR_PREFERRED_STATE')) {
        !          68336:     define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', getenv('PHP_PEAR_PREFERRED_STATE'));
        !          68337: } else {
        !          68338:     define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', 'stable');
        !          68339: }
        !          68340: 
        !          68341: // Default for umask
        !          68342: if (getenv('PHP_PEAR_UMASK')) {
        !          68343:     define('PEAR_CONFIG_DEFAULT_UMASK', getenv('PHP_PEAR_UMASK'));
        !          68344: } else {
        !          68345:     define('PEAR_CONFIG_DEFAULT_UMASK', decoct(umask()));
        !          68346: }
        !          68347: 
        !          68348: // Default for cache_ttl
        !          68349: if (getenv('PHP_PEAR_CACHE_TTL')) {
        !          68350:     define('PEAR_CONFIG_DEFAULT_CACHE_TTL', getenv('PHP_PEAR_CACHE_TTL'));
        !          68351: } else {
        !          68352:     define('PEAR_CONFIG_DEFAULT_CACHE_TTL', 3600);
        !          68353: }
        !          68354: 
        !          68355: // Default for sig_type
        !          68356: if (getenv('PHP_PEAR_SIG_TYPE')) {
        !          68357:     define('PEAR_CONFIG_DEFAULT_SIG_TYPE', getenv('PHP_PEAR_SIG_TYPE'));
        !          68358: } else {
        !          68359:     define('PEAR_CONFIG_DEFAULT_SIG_TYPE', 'gpg');
        !          68360: }
        !          68361: 
        !          68362: // Default for sig_bin
        !          68363: if (getenv('PHP_PEAR_SIG_BIN')) {
        !          68364:     define('PEAR_CONFIG_DEFAULT_SIG_BIN', getenv('PHP_PEAR_SIG_BIN'));
        !          68365: } else {
        !          68366:     define('PEAR_CONFIG_DEFAULT_SIG_BIN',
        !          68367:            System::which(
        !          68368:                'gpg', OS_WINDOWS ? 'c:\gnupg\gpg.exe' : '/usr/local/bin/gpg'));
        !          68369: }
        !          68370: 
        !          68371: // Default for sig_keydir
        !          68372: if (getenv('PHP_PEAR_SIG_KEYDIR')) {
        !          68373:     define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', getenv('PHP_PEAR_SIG_KEYDIR'));
        !          68374: } else {
        !          68375:     define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR',
        !          68376:            PEAR_CONFIG_SYSCONFDIR . DIRECTORY_SEPARATOR . 'pearkeys');
        !          68377: }
        !          68378: 
        !          68379: /**
        !          68380:  * This is a class for storing configuration data, keeping track of
        !          68381:  * which are system-defined, user-defined or defaulted.
        !          68382:  * @category   pear
        !          68383:  * @package    PEAR
        !          68384:  * @author     Stig Bakken <ssb@php.net>
        !          68385:  * @author     Greg Beaver <cellog@php.net>
        !          68386:  * @copyright  1997-2009 The Authors
        !          68387:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          68388:  * @version    Release: 1.9.4
        !          68389:  * @link       http://pear.php.net/package/PEAR
        !          68390:  * @since      Class available since Release 0.1
        !          68391:  */
        !          68392: class PEAR_Config extends PEAR
        !          68393: {
        !          68394:     /**
        !          68395:      * Array of config files used.
        !          68396:      *
        !          68397:      * @var array layer => config file
        !          68398:      */
        !          68399:     var $files = array(
        !          68400:         'system' => '',
        !          68401:         'user' => '',
        !          68402:         );
        !          68403: 
        !          68404:     var $layers = array();
        !          68405: 
        !          68406:     /**
        !          68407:      * Configuration data, two-dimensional array where the first
        !          68408:      * dimension is the config layer ('user', 'system' and 'default'),
        !          68409:      * and the second dimension is keyname => value.
        !          68410:      *
        !          68411:      * The order in the first dimension is important!  Earlier
        !          68412:      * layers will shadow later ones when a config value is
        !          68413:      * requested (if a 'user' value exists, it will be returned first,
        !          68414:      * then 'system' and finally 'default').
        !          68415:      *
        !          68416:      * @var array layer => array(keyname => value, ...)
        !          68417:      */
        !          68418:     var $configuration = array(
        !          68419:         'user' => array(),
        !          68420:         'system' => array(),
        !          68421:         'default' => array(),
        !          68422:         );
        !          68423: 
        !          68424:     /**
        !          68425:      * Configuration values that can be set for a channel
        !          68426:      *
        !          68427:      * All other configuration values can only have a global value
        !          68428:      * @var array
        !          68429:      * @access private
        !          68430:      */
        !          68431:     var $_channelConfigInfo = array(
        !          68432:         'php_dir', 'ext_dir', 'doc_dir', 'bin_dir', 'data_dir', 'cfg_dir',
        !          68433:         'test_dir', 'www_dir', 'php_bin', 'php_prefix', 'php_suffix', 'username',
        !          68434:         'password', 'verbose', 'preferred_state', 'umask', 'preferred_mirror', 'php_ini'
        !          68435:         );
        !          68436: 
        !          68437:     /**
        !          68438:      * Channels that can be accessed
        !          68439:      * @see setChannels()
        !          68440:      * @var array
        !          68441:      * @access private
        !          68442:      */
        !          68443:     var $_channels = array('pear.php.net', 'pecl.php.net', '__uri');
        !          68444: 
        !          68445:     /**
        !          68446:      * This variable is used to control the directory values returned
        !          68447:      * @see setInstallRoot();
        !          68448:      * @var string|false
        !          68449:      * @access private
        !          68450:      */
        !          68451:     var $_installRoot = false;
        !          68452: 
        !          68453:     /**
        !          68454:      * If requested, this will always refer to the registry
        !          68455:      * contained in php_dir
        !          68456:      * @var PEAR_Registry
        !          68457:      */
        !          68458:     var $_registry = array();
        !          68459: 
        !          68460:     /**
        !          68461:      * @var array
        !          68462:      * @access private
        !          68463:      */
        !          68464:     var $_regInitialized = array();
        !          68465: 
        !          68466:     /**
        !          68467:      * @var bool
        !          68468:      * @access private
        !          68469:      */
        !          68470:     var $_noRegistry = false;
        !          68471: 
        !          68472:     /**
        !          68473:      * amount of errors found while parsing config
        !          68474:      * @var integer
        !          68475:      * @access private
        !          68476:      */
        !          68477:     var $_errorsFound = 0;
        !          68478:     var $_lastError = null;
        !          68479: 
        !          68480:     /**
        !          68481:      * Information about the configuration data.  Stores the type,
        !          68482:      * default value and a documentation string for each configuration
        !          68483:      * value.
        !          68484:      *
        !          68485:      * @var array layer => array(infotype => value, ...)
        !          68486:      */
        !          68487:     var $configuration_info = array(
        !          68488:         // Channels/Internet Access
        !          68489:         'default_channel' => array(
        !          68490:             'type' => 'string',
        !          68491:             'default' => PEAR_CONFIG_DEFAULT_CHANNEL,
        !          68492:             'doc' => 'the default channel to use for all non explicit commands',
        !          68493:             'prompt' => 'Default Channel',
        !          68494:             'group' => 'Internet Access',
        !          68495:             ),
        !          68496:         'preferred_mirror' => array(
        !          68497:             'type' => 'string',
        !          68498:             'default' => PEAR_CONFIG_DEFAULT_CHANNEL,
        !          68499:             'doc' => 'the default server or mirror to use for channel actions',
        !          68500:             'prompt' => 'Default Channel Mirror',
        !          68501:             'group' => 'Internet Access',
        !          68502:             ),
        !          68503:         'remote_config' => array(
        !          68504:             'type' => 'password',
        !          68505:             'default' => '',
        !          68506:             'doc' => 'ftp url of remote configuration file to use for synchronized install',
        !          68507:             'prompt' => 'Remote Configuration File',
        !          68508:             'group' => 'Internet Access',
        !          68509:             ),
        !          68510:         'auto_discover' => array(
        !          68511:             'type' => 'integer',
        !          68512:             'default' => 0,
        !          68513:             'doc' => 'whether to automatically discover new channels',
        !          68514:             'prompt' => 'Auto-discover new Channels',
        !          68515:             'group' => 'Internet Access',
        !          68516:             ),
        !          68517:         // Internet Access
        !          68518:         'master_server' => array(
        !          68519:             'type' => 'string',
        !          68520:             'default' => 'pear.php.net',
        !          68521:             'doc' => 'name of the main PEAR server [NOT USED IN THIS VERSION]',
        !          68522:             'prompt' => 'PEAR server [DEPRECATED]',
        !          68523:             'group' => 'Internet Access',
        !          68524:             ),
        !          68525:         'http_proxy' => array(
        !          68526:             'type' => 'string',
        !          68527:             'default' => PEAR_CONFIG_DEFAULT_HTTP_PROXY,
        !          68528:             'doc' => 'HTTP proxy (host:port) to use when downloading packages',
        !          68529:             'prompt' => 'HTTP Proxy Server Address',
        !          68530:             'group' => 'Internet Access',
        !          68531:             ),
        !          68532:         // File Locations
        !          68533:         'php_dir' => array(
        !          68534:             'type' => 'directory',
        !          68535:             'default' => PEAR_CONFIG_DEFAULT_PHP_DIR,
        !          68536:             'doc' => 'directory where .php files are installed',
        !          68537:             'prompt' => 'PEAR directory',
        !          68538:             'group' => 'File Locations',
        !          68539:             ),
        !          68540:         'ext_dir' => array(
        !          68541:             'type' => 'directory',
        !          68542:             'default' => PEAR_CONFIG_DEFAULT_EXT_DIR,
        !          68543:             'doc' => 'directory where loadable extensions are installed',
        !          68544:             'prompt' => 'PHP extension directory',
        !          68545:             'group' => 'File Locations',
        !          68546:             ),
        !          68547:         'doc_dir' => array(
        !          68548:             'type' => 'directory',
        !          68549:             'default' => PEAR_CONFIG_DEFAULT_DOC_DIR,
        !          68550:             'doc' => 'directory where documentation is installed',
        !          68551:             'prompt' => 'PEAR documentation directory',
        !          68552:             'group' => 'File Locations',
        !          68553:             ),
        !          68554:         'bin_dir' => array(
        !          68555:             'type' => 'directory',
        !          68556:             'default' => PEAR_CONFIG_DEFAULT_BIN_DIR,
        !          68557:             'doc' => 'directory where executables are installed',
        !          68558:             'prompt' => 'PEAR executables directory',
        !          68559:             'group' => 'File Locations',
        !          68560:             ),
        !          68561:         'data_dir' => array(
        !          68562:             'type' => 'directory',
        !          68563:             'default' => PEAR_CONFIG_DEFAULT_DATA_DIR,
        !          68564:             'doc' => 'directory where data files are installed',
        !          68565:             'prompt' => 'PEAR data directory',
        !          68566:             'group' => 'File Locations (Advanced)',
        !          68567:             ),
        !          68568:         'cfg_dir' => array(
        !          68569:             'type' => 'directory',
        !          68570:             'default' => PEAR_CONFIG_DEFAULT_CFG_DIR,
        !          68571:             'doc' => 'directory where modifiable configuration files are installed',
        !          68572:             'prompt' => 'PEAR configuration file directory',
        !          68573:             'group' => 'File Locations (Advanced)',
        !          68574:             ),
        !          68575:         'www_dir' => array(
        !          68576:             'type' => 'directory',
        !          68577:             'default' => PEAR_CONFIG_DEFAULT_WWW_DIR,
        !          68578:             'doc' => 'directory where www frontend files (html/js) are installed',
        !          68579:             'prompt' => 'PEAR www files directory',
        !          68580:             'group' => 'File Locations (Advanced)',
        !          68581:             ),
        !          68582:         'test_dir' => array(
        !          68583:             'type' => 'directory',
        !          68584:             'default' => PEAR_CONFIG_DEFAULT_TEST_DIR,
        !          68585:             'doc' => 'directory where regression tests are installed',
        !          68586:             'prompt' => 'PEAR test directory',
        !          68587:             'group' => 'File Locations (Advanced)',
        !          68588:             ),
        !          68589:         'cache_dir' => array(
        !          68590:             'type' => 'directory',
        !          68591:             'default' => PEAR_CONFIG_DEFAULT_CACHE_DIR,
        !          68592:             'doc' => 'directory which is used for web service cache',
        !          68593:             'prompt' => 'PEAR Installer cache directory',
        !          68594:             'group' => 'File Locations (Advanced)',
        !          68595:             ),
        !          68596:         'temp_dir' => array(
        !          68597:             'type' => 'directory',
        !          68598:             'default' => PEAR_CONFIG_DEFAULT_TEMP_DIR,
        !          68599:             'doc' => 'directory which is used for all temp files',
        !          68600:             'prompt' => 'PEAR Installer temp directory',
        !          68601:             'group' => 'File Locations (Advanced)',
        !          68602:             ),
        !          68603:         'download_dir' => array(
        !          68604:             'type' => 'directory',
        !          68605:             'default' => PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR,
        !          68606:             'doc' => 'directory which is used for all downloaded files',
        !          68607:             'prompt' => 'PEAR Installer download directory',
        !          68608:             'group' => 'File Locations (Advanced)',
        !          68609:             ),
        !          68610:         'php_bin' => array(
        !          68611:             'type' => 'file',
        !          68612:             'default' => PEAR_CONFIG_DEFAULT_PHP_BIN,
        !          68613:             'doc' => 'PHP CLI/CGI binary for executing scripts',
        !          68614:             'prompt' => 'PHP CLI/CGI binary',
        !          68615:             'group' => 'File Locations (Advanced)',
        !          68616:             ),
        !          68617:         'php_prefix' => array(
        !          68618:             'type' => 'string',
        !          68619:             'default' => '',
        !          68620:             'doc' => '--program-prefix for php_bin\'s ./configure, used for pecl installs',
        !          68621:             'prompt' => '--program-prefix passed to PHP\'s ./configure',
        !          68622:             'group' => 'File Locations (Advanced)',
        !          68623:             ),
        !          68624:         'php_suffix' => array(
        !          68625:             'type' => 'string',
        !          68626:             'default' => '',
        !          68627:             'doc' => '--program-suffix for php_bin\'s ./configure, used for pecl installs',
        !          68628:             'prompt' => '--program-suffix passed to PHP\'s ./configure',
        !          68629:             'group' => 'File Locations (Advanced)',
        !          68630:             ),
        !          68631:         'php_ini' => array(
        !          68632:             'type' => 'file',
        !          68633:             'default' => '',
        !          68634:             'doc' => 'location of php.ini in which to enable PECL extensions on install',
        !          68635:             'prompt' => 'php.ini location',
        !          68636:             'group' => 'File Locations (Advanced)',
        !          68637:             ),
        !          68638:         // Maintainers
        !          68639:         'username' => array(
        !          68640:             'type' => 'string',
        !          68641:             'default' => '',
        !          68642:             'doc' => '(maintainers) your PEAR account name',
        !          68643:             'prompt' => 'PEAR username (for maintainers)',
        !          68644:             'group' => 'Maintainers',
        !          68645:             ),
        !          68646:         'password' => array(
        !          68647:             'type' => 'password',
        !          68648:             'default' => '',
        !          68649:             'doc' => '(maintainers) your PEAR account password',
        !          68650:             'prompt' => 'PEAR password (for maintainers)',
        !          68651:             'group' => 'Maintainers',
        !          68652:             ),
        !          68653:         // Advanced
        !          68654:         'verbose' => array(
        !          68655:             'type' => 'integer',
        !          68656:             'default' => PEAR_CONFIG_DEFAULT_VERBOSE,
        !          68657:             'doc' => 'verbosity level
        !          68658: 0: really quiet
        !          68659: 1: somewhat quiet
        !          68660: 2: verbose
        !          68661: 3: debug',
        !          68662:             'prompt' => 'Debug Log Level',
        !          68663:             'group' => 'Advanced',
        !          68664:             ),
        !          68665:         'preferred_state' => array(
        !          68666:             'type' => 'set',
        !          68667:             'default' => PEAR_CONFIG_DEFAULT_PREFERRED_STATE,
        !          68668:             'doc' => 'the installer will prefer releases with this state when installing packages without a version or state specified',
        !          68669:             'valid_set' => array(
        !          68670:                 'stable', 'beta', 'alpha', 'devel', 'snapshot'),
        !          68671:             'prompt' => 'Preferred Package State',
        !          68672:             'group' => 'Advanced',
        !          68673:             ),
        !          68674:         'umask' => array(
        !          68675:             'type' => 'mask',
        !          68676:             'default' => PEAR_CONFIG_DEFAULT_UMASK,
        !          68677:             'doc' => 'umask used when creating files (Unix-like systems only)',
        !          68678:             'prompt' => 'Unix file mask',
        !          68679:             'group' => 'Advanced',
        !          68680:             ),
        !          68681:         'cache_ttl' => array(
        !          68682:             'type' => 'integer',
        !          68683:             'default' => PEAR_CONFIG_DEFAULT_CACHE_TTL,
        !          68684:             'doc' => 'amount of secs where the local cache is used and not updated',
        !          68685:             'prompt' => 'Cache TimeToLive',
        !          68686:             'group' => 'Advanced',
        !          68687:             ),
        !          68688:         'sig_type' => array(
        !          68689:             'type' => 'set',
        !          68690:             'default' => PEAR_CONFIG_DEFAULT_SIG_TYPE,
        !          68691:             'doc' => 'which package signature mechanism to use',
        !          68692:             'valid_set' => array('gpg'),
        !          68693:             'prompt' => 'Package Signature Type',
        !          68694:             'group' => 'Maintainers',
        !          68695:             ),
        !          68696:         'sig_bin' => array(
        !          68697:             'type' => 'string',
        !          68698:             'default' => PEAR_CONFIG_DEFAULT_SIG_BIN,
        !          68699:             'doc' => 'which package signature mechanism to use',
        !          68700:             'prompt' => 'Signature Handling Program',
        !          68701:             'group' => 'Maintainers',
        !          68702:             ),
        !          68703:         'sig_keyid' => array(
        !          68704:             'type' => 'string',
        !          68705:             'default' => '',
        !          68706:             'doc' => 'which key to use for signing with',
        !          68707:             'prompt' => 'Signature Key Id',
        !          68708:             'group' => 'Maintainers',
        !          68709:             ),
        !          68710:         'sig_keydir' => array(
        !          68711:             'type' => 'directory',
        !          68712:             'default' => PEAR_CONFIG_DEFAULT_SIG_KEYDIR,
        !          68713:             'doc' => 'directory where signature keys are located',
        !          68714:             'prompt' => 'Signature Key Directory',
        !          68715:             'group' => 'Maintainers',
        !          68716:             ),
        !          68717:         // __channels is reserved - used for channel-specific configuration
        !          68718:         );
        !          68719: 
        !          68720:     /**
        !          68721:      * Constructor.
        !          68722:      *
        !          68723:      * @param string file to read user-defined options from
        !          68724:      * @param string file to read system-wide defaults from
        !          68725:      * @param bool   determines whether a registry object "follows"
        !          68726:      *               the value of php_dir (is automatically created
        !          68727:      *               and moved when php_dir is changed)
        !          68728:      * @param bool   if true, fails if configuration files cannot be loaded
        !          68729:      *
        !          68730:      * @access public
        !          68731:      *
        !          68732:      * @see PEAR_Config::singleton
        !          68733:      */
        !          68734:     function PEAR_Config($user_file = '', $system_file = '', $ftp_file = false,
        !          68735:                          $strict = true)
        !          68736:     {
        !          68737:         $this->PEAR();
        !          68738:         PEAR_Installer_Role::initializeConfig($this);
        !          68739:         $sl = DIRECTORY_SEPARATOR;
        !          68740:         if (empty($user_file)) {
        !          68741:             if (OS_WINDOWS) {
        !          68742:                 $user_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini';
        !          68743:             } else {
        !          68744:                 $user_file = getenv('HOME') . $sl . '.pearrc';
        !          68745:             }
        !          68746:         }
        !          68747: 
        !          68748:         if (empty($system_file)) {
        !          68749:             $system_file = PEAR_CONFIG_SYSCONFDIR . $sl;
        !          68750:             if (OS_WINDOWS) {
        !          68751:                 $system_file .= 'pearsys.ini';
        !          68752:             } else {
        !          68753:                 $system_file .= 'pear.conf';
        !          68754:             }
        !          68755:         }
        !          68756: 
        !          68757:         $this->layers = array_keys($this->configuration);
        !          68758:         $this->files['user']   = $user_file;
        !          68759:         $this->files['system'] = $system_file;
        !          68760:         if ($user_file && file_exists($user_file)) {
        !          68761:             $this->pushErrorHandling(PEAR_ERROR_RETURN);
        !          68762:             $this->readConfigFile($user_file, 'user', $strict);
        !          68763:             $this->popErrorHandling();
        !          68764:             if ($this->_errorsFound > 0) {
        !          68765:                 return;
        !          68766:             }
        !          68767:         }
        !          68768: 
        !          68769:         if ($system_file && @file_exists($system_file)) {
        !          68770:             $this->mergeConfigFile($system_file, false, 'system', $strict);
        !          68771:             if ($this->_errorsFound > 0) {
        !          68772:                 return;
        !          68773:             }
        !          68774: 
        !          68775:         }
        !          68776: 
        !          68777:         if (!$ftp_file) {
        !          68778:             $ftp_file = $this->get('remote_config');
        !          68779:         }
        !          68780: 
        !          68781:         if ($ftp_file && defined('PEAR_REMOTEINSTALL_OK')) {
        !          68782:             $this->readFTPConfigFile($ftp_file);
        !          68783:         }
        !          68784: 
        !          68785:         foreach ($this->configuration_info as $key => $info) {
        !          68786:             $this->configuration['default'][$key] = $info['default'];
        !          68787:         }
        !          68788: 
        !          68789:         $this->_registry['default'] = &new PEAR_Registry($this->configuration['default']['php_dir']);
        !          68790:         $this->_registry['default']->setConfig($this, false);
        !          68791:         $this->_regInitialized['default'] = false;
        !          68792:         //$GLOBALS['_PEAR_Config_instance'] = &$this;
        !          68793:     }
        !          68794: 
        !          68795:     /**
        !          68796:      * Return the default locations of user and system configuration files
        !          68797:      * @static
        !          68798:      */
        !          68799:     function getDefaultConfigFiles()
        !          68800:     {
        !          68801:         $sl = DIRECTORY_SEPARATOR;
        !          68802:         if (OS_WINDOWS) {
        !          68803:             return array(
        !          68804:                 'user'   => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini',
        !          68805:                 'system' =>  PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini'
        !          68806:             );
        !          68807:         }
        !          68808: 
        !          68809:         return array(
        !          68810:             'user'   => getenv('HOME') . $sl . '.pearrc',
        !          68811:             'system' => PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf'
        !          68812:         );
        !          68813:     }
        !          68814: 
        !          68815:     /**
        !          68816:      * Static singleton method.  If you want to keep only one instance
        !          68817:      * of this class in use, this method will give you a reference to
        !          68818:      * the last created PEAR_Config object if one exists, or create a
        !          68819:      * new object.
        !          68820:      *
        !          68821:      * @param string (optional) file to read user-defined options from
        !          68822:      * @param string (optional) file to read system-wide defaults from
        !          68823:      *
        !          68824:      * @return object an existing or new PEAR_Config instance
        !          68825:      *
        !          68826:      * @access public
        !          68827:      *
        !          68828:      * @see PEAR_Config::PEAR_Config
        !          68829:      */
        !          68830:     function &singleton($user_file = '', $system_file = '', $strict = true)
        !          68831:     {
        !          68832:         if (is_object($GLOBALS['_PEAR_Config_instance'])) {
        !          68833:             return $GLOBALS['_PEAR_Config_instance'];
        !          68834:         }
        !          68835: 
        !          68836:         $t_conf = &new PEAR_Config($user_file, $system_file, false, $strict);
        !          68837:         if ($t_conf->_errorsFound > 0) {
        !          68838:              return $t_conf->lastError;
        !          68839:         }
        !          68840: 
        !          68841:         $GLOBALS['_PEAR_Config_instance'] = &$t_conf;
        !          68842:         return $GLOBALS['_PEAR_Config_instance'];
        !          68843:     }
        !          68844: 
        !          68845:     /**
        !          68846:      * Determine whether any configuration files have been detected, and whether a
        !          68847:      * registry object can be retrieved from this configuration.
        !          68848:      * @return bool
        !          68849:      * @since PEAR 1.4.0a1
        !          68850:      */
        !          68851:     function validConfiguration()
        !          68852:     {
        !          68853:         if ($this->isDefinedLayer('user') || $this->isDefinedLayer('system')) {
        !          68854:             return true;
        !          68855:         }
        !          68856: 
        !          68857:         return false;
        !          68858:     }
        !          68859: 
        !          68860:     /**
        !          68861:      * Reads configuration data from a file.  All existing values in
        !          68862:      * the config layer are discarded and replaced with data from the
        !          68863:      * file.
        !          68864:      * @param string file to read from, if NULL or not specified, the
        !          68865:      *               last-used file for the same layer (second param) is used
        !          68866:      * @param string config layer to insert data into ('user' or 'system')
        !          68867:      * @return bool TRUE on success or a PEAR error on failure
        !          68868:      */
        !          68869:     function readConfigFile($file = null, $layer = 'user', $strict = true)
        !          68870:     {
        !          68871:         if (empty($this->files[$layer])) {
        !          68872:             return $this->raiseError("unknown config layer `$layer'");
        !          68873:         }
        !          68874: 
        !          68875:         if ($file === null) {
        !          68876:             $file = $this->files[$layer];
        !          68877:         }
        !          68878: 
        !          68879:         $data = $this->_readConfigDataFrom($file);
        !          68880:         if (PEAR::isError($data)) {
        !          68881:             if (!$strict) {
        !          68882:                 return true;
        !          68883:             }
        !          68884: 
        !          68885:             $this->_errorsFound++;
        !          68886:             $this->lastError = $data;
        !          68887: 
        !          68888:             return $data;
        !          68889:         }
        !          68890: 
        !          68891:         $this->files[$layer] = $file;
        !          68892:         $this->_decodeInput($data);
        !          68893:         $this->configuration[$layer] = $data;
        !          68894:         $this->_setupChannels();
        !          68895:         if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {
        !          68896:             $this->_registry[$layer] = &new PEAR_Registry($phpdir);
        !          68897:             $this->_registry[$layer]->setConfig($this, false);
        !          68898:             $this->_regInitialized[$layer] = false;
        !          68899:         } else {
        !          68900:             unset($this->_registry[$layer]);
        !          68901:         }
        !          68902:         return true;
        !          68903:     }
        !          68904: 
        !          68905:     /**
        !          68906:      * @param string url to the remote config file, like ftp://www.example.com/pear/config.ini
        !          68907:      * @return true|PEAR_Error
        !          68908:      */
        !          68909:     function readFTPConfigFile($path)
        !          68910:     {
        !          68911:         do { // poor man's try
        !          68912:             if (!class_exists('PEAR_FTP')) {
        !          68913:                 if (!class_exists('PEAR_Common')) {
        !          68914:                     require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
        !          68915:                 }
        !          68916:                 if (PEAR_Common::isIncludeable('PEAR/FTP.php')) {
        !          68917:                     require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/FTP.php';
        !          68918:                 }
        !          68919:             }
        !          68920: 
        !          68921:             if (!class_exists('PEAR_FTP')) {
        !          68922:                 return PEAR::raiseError('PEAR_RemoteInstaller must be installed to use remote config');
        !          68923:             }
        !          68924: 
        !          68925:             $this->_ftp = &new PEAR_FTP;
        !          68926:             $this->_ftp->pushErrorHandling(PEAR_ERROR_RETURN);
        !          68927:             $e = $this->_ftp->init($path);
        !          68928:             if (PEAR::isError($e)) {
        !          68929:                 $this->_ftp->popErrorHandling();
        !          68930:                 return $e;
        !          68931:             }
        !          68932: 
        !          68933:             $tmp = System::mktemp('-d');
        !          68934:             PEAR_Common::addTempFile($tmp);
        !          68935:             $e = $this->_ftp->get(basename($path), $tmp . DIRECTORY_SEPARATOR .
        !          68936:                 'pear.ini', false, FTP_BINARY);
        !          68937:             if (PEAR::isError($e)) {
        !          68938:                 $this->_ftp->popErrorHandling();
        !          68939:                 return $e;
        !          68940:             }
        !          68941: 
        !          68942:             PEAR_Common::addTempFile($tmp . DIRECTORY_SEPARATOR . 'pear.ini');
        !          68943:             $this->_ftp->disconnect();
        !          68944:             $this->_ftp->popErrorHandling();
        !          68945:             $this->files['ftp'] = $tmp . DIRECTORY_SEPARATOR . 'pear.ini';
        !          68946:             $e = $this->readConfigFile(null, 'ftp');
        !          68947:             if (PEAR::isError($e)) {
        !          68948:                 return $e;
        !          68949:             }
        !          68950: 
        !          68951:             $fail = array();
        !          68952:             foreach ($this->configuration_info as $key => $val) {
        !          68953:                 if (in_array($this->getGroup($key),
        !          68954:                       array('File Locations', 'File Locations (Advanced)')) &&
        !          68955:                       $this->getType($key) == 'directory') {
        !          68956:                     // any directory configs must be set for this to work
        !          68957:                     if (!isset($this->configuration['ftp'][$key])) {
        !          68958:                         $fail[] = $key;
        !          68959:                     }
        !          68960:                 }
        !          68961:             }
        !          68962: 
        !          68963:             if (!count($fail)) {
        !          68964:                 return true;
        !          68965:             }
        !          68966: 
        !          68967:             $fail = '"' . implode('", "', $fail) . '"';
        !          68968:             unset($this->files['ftp']);
        !          68969:             unset($this->configuration['ftp']);
        !          68970:             return PEAR::raiseError('ERROR: Ftp configuration file must set all ' .
        !          68971:                 'directory configuration variables.  These variables were not set: ' .
        !          68972:                 $fail);
        !          68973:         } while (false); // poor man's catch
        !          68974:         unset($this->files['ftp']);
        !          68975:         return PEAR::raiseError('no remote host specified');
        !          68976:     }
        !          68977: 
        !          68978:     /**
        !          68979:      * Reads the existing configurations and creates the _channels array from it
        !          68980:      */
        !          68981:     function _setupChannels()
        !          68982:     {
        !          68983:         $set = array_flip(array_values($this->_channels));
        !          68984:         foreach ($this->configuration as $layer => $data) {
        !          68985:             $i = 1000;
        !          68986:             if (isset($data['__channels']) && is_array($data['__channels'])) {
        !          68987:                 foreach ($data['__channels'] as $channel => $info) {
        !          68988:                     $set[$channel] = $i++;
        !          68989:                 }
        !          68990:             }
        !          68991:         }
        !          68992:         $this->_channels = array_values(array_flip($set));
        !          68993:         $this->setChannels($this->_channels);
        !          68994:     }
        !          68995: 
        !          68996:     function deleteChannel($channel)
        !          68997:     {
        !          68998:         $ch = strtolower($channel);
        !          68999:         foreach ($this->configuration as $layer => $data) {
        !          69000:             if (isset($data['__channels']) && isset($data['__channels'][$ch])) {
        !          69001:                 unset($this->configuration[$layer]['__channels'][$ch]);
        !          69002:             }
        !          69003:         }
        !          69004: 
        !          69005:         $this->_channels = array_flip($this->_channels);
        !          69006:         unset($this->_channels[$ch]);
        !          69007:         $this->_channels = array_flip($this->_channels);
        !          69008:     }
        !          69009: 
        !          69010:     /**
        !          69011:      * Merges data into a config layer from a file.  Does the same
        !          69012:      * thing as readConfigFile, except it does not replace all
        !          69013:      * existing values in the config layer.
        !          69014:      * @param string file to read from
        !          69015:      * @param bool whether to overwrite existing data (default TRUE)
        !          69016:      * @param string config layer to insert data into ('user' or 'system')
        !          69017:      * @param string if true, errors are returned if file opening fails
        !          69018:      * @return bool TRUE on success or a PEAR error on failure
        !          69019:      */
        !          69020:     function mergeConfigFile($file, $override = true, $layer = 'user', $strict = true)
        !          69021:     {
        !          69022:         if (empty($this->files[$layer])) {
        !          69023:             return $this->raiseError("unknown config layer `$layer'");
        !          69024:         }
        !          69025: 
        !          69026:         if ($file === null) {
        !          69027:             $file = $this->files[$layer];
        !          69028:         }
        !          69029: 
        !          69030:         $data = $this->_readConfigDataFrom($file);
        !          69031:         if (PEAR::isError($data)) {
        !          69032:             if (!$strict) {
        !          69033:                 return true;
        !          69034:             }
        !          69035: 
        !          69036:             $this->_errorsFound++;
        !          69037:             $this->lastError = $data;
        !          69038: 
        !          69039:             return $data;
        !          69040:         }
        !          69041: 
        !          69042:         $this->_decodeInput($data);
        !          69043:         if ($override) {
        !          69044:             $this->configuration[$layer] =
        !          69045:                 PEAR_Config::arrayMergeRecursive($this->configuration[$layer], $data);
        !          69046:         } else {
        !          69047:             $this->configuration[$layer] =
        !          69048:                 PEAR_Config::arrayMergeRecursive($data, $this->configuration[$layer]);
        !          69049:         }
        !          69050: 
        !          69051:         $this->_setupChannels();
        !          69052:         if (!$this->_noRegistry && ($phpdir = $this->get('php_dir', $layer, 'pear.php.net'))) {
        !          69053:             $this->_registry[$layer] = &new PEAR_Registry($phpdir);
        !          69054:             $this->_registry[$layer]->setConfig($this, false);
        !          69055:             $this->_regInitialized[$layer] = false;
        !          69056:         } else {
        !          69057:             unset($this->_registry[$layer]);
        !          69058:         }
        !          69059:         return true;
        !          69060:     }
        !          69061: 
        !          69062:     /**
        !          69063:      * @param array
        !          69064:      * @param array
        !          69065:      * @return array
        !          69066:      * @static
        !          69067:      */
        !          69068:     function arrayMergeRecursive($arr2, $arr1)
        !          69069:     {
        !          69070:         $ret = array();
        !          69071:         foreach ($arr2 as $key => $data) {
        !          69072:             if (!isset($arr1[$key])) {
        !          69073:                 $ret[$key] = $data;
        !          69074:                 unset($arr1[$key]);
        !          69075:                 continue;
        !          69076:             }
        !          69077:             if (is_array($data)) {
        !          69078:                 if (!is_array($arr1[$key])) {
        !          69079:                     $ret[$key] = $arr1[$key];
        !          69080:                     unset($arr1[$key]);
        !          69081:                     continue;
        !          69082:                 }
        !          69083:                 $ret[$key] = PEAR_Config::arrayMergeRecursive($arr1[$key], $arr2[$key]);
        !          69084:                 unset($arr1[$key]);
        !          69085:             }
        !          69086:         }
        !          69087: 
        !          69088:         return array_merge($ret, $arr1);
        !          69089:     }
        !          69090: 
        !          69091:     /**
        !          69092:      * Writes data into a config layer from a file.
        !          69093:      *
        !          69094:      * @param string|null file to read from, or null for default
        !          69095:      * @param string config layer to insert data into ('user' or
        !          69096:      *               'system')
        !          69097:      * @param string|null data to write to config file or null for internal data [DEPRECATED]
        !          69098:      * @return bool TRUE on success or a PEAR error on failure
        !          69099:      */
        !          69100:     function writeConfigFile($file = null, $layer = 'user', $data = null)
        !          69101:     {
        !          69102:         $this->_lazyChannelSetup($layer);
        !          69103:         if ($layer == 'both' || $layer == 'all') {
        !          69104:             foreach ($this->files as $type => $file) {
        !          69105:                 $err = $this->writeConfigFile($file, $type, $data);
        !          69106:                 if (PEAR::isError($err)) {
        !          69107:                     return $err;
        !          69108:                 }
        !          69109:             }
        !          69110:             return true;
        !          69111:         }
        !          69112: 
        !          69113:         if (empty($this->files[$layer])) {
        !          69114:             return $this->raiseError("unknown config file type `$layer'");
        !          69115:         }
        !          69116: 
        !          69117:         if ($file === null) {
        !          69118:             $file = $this->files[$layer];
        !          69119:         }
        !          69120: 
        !          69121:         $data = ($data === null) ? $this->configuration[$layer] : $data;
        !          69122:         $this->_encodeOutput($data);
        !          69123:         $opt = array('-p', dirname($file));
        !          69124:         if (!@System::mkDir($opt)) {
        !          69125:             return $this->raiseError("could not create directory: " . dirname($file));
        !          69126:         }
        !          69127: 
        !          69128:         if (file_exists($file) && is_file($file) && !is_writeable($file)) {
        !          69129:             return $this->raiseError("no write access to $file!");
        !          69130:         }
        !          69131: 
        !          69132:         $fp = @fopen($file, "w");
        !          69133:         if (!$fp) {
        !          69134:             return $this->raiseError("PEAR_Config::writeConfigFile fopen('$file','w') failed ($php_errormsg)");
        !          69135:         }
        !          69136: 
        !          69137:         $contents = "#PEAR_Config 0.9\n" . serialize($data);
        !          69138:         if (!@fwrite($fp, $contents)) {
        !          69139:             return $this->raiseError("PEAR_Config::writeConfigFile: fwrite failed ($php_errormsg)");
        !          69140:         }
        !          69141:         return true;
        !          69142:     }
        !          69143: 
        !          69144:     /**
        !          69145:      * Reads configuration data from a file and returns the parsed data
        !          69146:      * in an array.
        !          69147:      *
        !          69148:      * @param string file to read from
        !          69149:      * @return array configuration data or a PEAR error on failure
        !          69150:      * @access private
        !          69151:      */
        !          69152:     function _readConfigDataFrom($file)
        !          69153:     {
        !          69154:         $fp = false;
        !          69155:         if (file_exists($file)) {
        !          69156:             $fp = @fopen($file, "r");
        !          69157:         }
        !          69158: 
        !          69159:         if (!$fp) {
        !          69160:             return $this->raiseError("PEAR_Config::readConfigFile fopen('$file','r') failed");
        !          69161:         }
        !          69162: 
        !          69163:         $size = filesize($file);
        !          69164:         $rt = get_magic_quotes_runtime();
        !          69165:         set_magic_quotes_runtime(0);
        !          69166:         fclose($fp);
        !          69167:         $contents = file_get_contents($file);
        !          69168:         if (empty($contents)) {
        !          69169:             return $this->raiseError('Configuration file "' . $file . '" is empty');
        !          69170:         }
        !          69171: 
        !          69172:         set_magic_quotes_runtime($rt);
        !          69173: 
        !          69174:         $version = false;
        !          69175:         if (preg_match('/^#PEAR_Config\s+(\S+)\s+/si', $contents, $matches)) {
        !          69176:             $version = $matches[1];
        !          69177:             $contents = substr($contents, strlen($matches[0]));
        !          69178:         } else {
        !          69179:             // Museum config file
        !          69180:             if (substr($contents,0,2) == 'a:') {
        !          69181:                 $version = '0.1';
        !          69182:             }
        !          69183:         }
        !          69184: 
        !          69185:         if ($version && version_compare("$version", '1', '<')) {
        !          69186:             // no '@', it is possible that unserialize
        !          69187:             // raises a notice but it seems to block IO to
        !          69188:             // STDOUT if a '@' is used and a notice is raise
        !          69189:             $data = unserialize($contents);
        !          69190: 
        !          69191:             if (!is_array($data) && !$data) {
        !          69192:                 if ($contents == serialize(false)) {
        !          69193:                     $data = array();
        !          69194:                 } else {
        !          69195:                     $err = $this->raiseError("PEAR_Config: bad data in $file");
        !          69196:                     return $err;
        !          69197:                 }
        !          69198:             }
        !          69199:             if (!is_array($data)) {
        !          69200:                 if (strlen(trim($contents)) > 0) {
        !          69201:                     $error = "PEAR_Config: bad data in $file";
        !          69202:                     $err = $this->raiseError($error);
        !          69203:                     return $err;
        !          69204:                 }
        !          69205: 
        !          69206:                 $data = array();
        !          69207:             }
        !          69208:         // add parsing of newer formats here...
        !          69209:         } else {
        !          69210:             $err = $this->raiseError("$file: unknown version `$version'");
        !          69211:             return $err;
        !          69212:         }
        !          69213: 
        !          69214:         return $data;
        !          69215:     }
        !          69216: 
        !          69217:     /**
        !          69218:     * Gets the file used for storing the config for a layer
        !          69219:     *
        !          69220:     * @param string $layer 'user' or 'system'
        !          69221:     */
        !          69222:     function getConfFile($layer)
        !          69223:     {
        !          69224:         return $this->files[$layer];
        !          69225:     }
        !          69226: 
        !          69227:     /**
        !          69228:      * @param string Configuration class name, used for detecting duplicate calls
        !          69229:      * @param array information on a role as parsed from its xml file
        !          69230:      * @return true|PEAR_Error
        !          69231:      * @access private
        !          69232:      */
        !          69233:     function _addConfigVars($class, $vars)
        !          69234:     {
        !          69235:         static $called = array();
        !          69236:         if (isset($called[$class])) {
        !          69237:             return;
        !          69238:         }
        !          69239: 
        !          69240:         $called[$class] = 1;
        !          69241:         if (count($vars) > 3) {
        !          69242:             return $this->raiseError('Roles can only define 3 new config variables or less');
        !          69243:         }
        !          69244: 
        !          69245:         foreach ($vars as $name => $var) {
        !          69246:             if (!is_array($var)) {
        !          69247:                 return $this->raiseError('Configuration information must be an array');
        !          69248:             }
        !          69249: 
        !          69250:             if (!isset($var['type'])) {
        !          69251:                 return $this->raiseError('Configuration information must contain a type');
        !          69252:             } elseif (!in_array($var['type'],
        !          69253:                     array('string', 'mask', 'password', 'directory', 'file', 'set'))) {
        !          69254:                   return $this->raiseError(
        !          69255:                       'Configuration type must be one of directory, file, string, ' .
        !          69256:                       'mask, set, or password');
        !          69257:             }
        !          69258:             if (!isset($var['default'])) {
        !          69259:                 return $this->raiseError(
        !          69260:                     'Configuration information must contain a default value ("default" index)');
        !          69261:             }
        !          69262: 
        !          69263:             if (is_array($var['default'])) {
        !          69264:                 $real_default = '';
        !          69265:                 foreach ($var['default'] as $config_var => $val) {
        !          69266:                     if (strpos($config_var, 'text') === 0) {
        !          69267:                         $real_default .= $val;
        !          69268:                     } elseif (strpos($config_var, 'constant') === 0) {
        !          69269:                         if (!defined($val)) {
        !          69270:                             return $this->raiseError(
        !          69271:                                 'Unknown constant "' . $val . '" requested in ' .
        !          69272:                                 'default value for configuration variable "' .
        !          69273:                                 $name . '"');
        !          69274:                         }
        !          69275: 
        !          69276:                         $real_default .= constant($val);
        !          69277:                     } elseif (isset($this->configuration_info[$config_var])) {
        !          69278:                         $real_default .=
        !          69279:                             $this->configuration_info[$config_var]['default'];
        !          69280:                     } else {
        !          69281:                         return $this->raiseError(
        !          69282:                             'Unknown request for "' . $config_var . '" value in ' .
        !          69283:                             'default value for configuration variable "' .
        !          69284:                             $name . '"');
        !          69285:                     }
        !          69286:                 }
        !          69287:                 $var['default'] = $real_default;
        !          69288:             }
        !          69289: 
        !          69290:             if ($var['type'] == 'integer') {
        !          69291:                 $var['default'] = (integer) $var['default'];
        !          69292:             }
        !          69293: 
        !          69294:             if (!isset($var['doc'])) {
        !          69295:                 return $this->raiseError(
        !          69296:                     'Configuration information must contain a summary ("doc" index)');
        !          69297:             }
        !          69298: 
        !          69299:             if (!isset($var['prompt'])) {
        !          69300:                 return $this->raiseError(
        !          69301:                     'Configuration information must contain a simple prompt ("prompt" index)');
        !          69302:             }
        !          69303: 
        !          69304:             if (!isset($var['group'])) {
        !          69305:                 return $this->raiseError(
        !          69306:                     'Configuration information must contain a simple group ("group" index)');
        !          69307:             }
        !          69308: 
        !          69309:             if (isset($this->configuration_info[$name])) {
        !          69310:                 return $this->raiseError('Configuration variable "' . $name .
        !          69311:                     '" already exists');
        !          69312:             }
        !          69313: 
        !          69314:             $this->configuration_info[$name] = $var;
        !          69315:             // fix bug #7351: setting custom config variable in a channel fails
        !          69316:             $this->_channelConfigInfo[] = $name;
        !          69317:         }
        !          69318: 
        !          69319:         return true;
        !          69320:     }
        !          69321: 
        !          69322:     /**
        !          69323:      * Encodes/scrambles configuration data before writing to files.
        !          69324:      * Currently, 'password' values will be base64-encoded as to avoid
        !          69325:      * that people spot cleartext passwords by accident.
        !          69326:      *
        !          69327:      * @param array (reference) array to encode values in
        !          69328:      * @return bool TRUE on success
        !          69329:      * @access private
        !          69330:      */
        !          69331:     function _encodeOutput(&$data)
        !          69332:     {
        !          69333:         foreach ($data as $key => $value) {
        !          69334:             if ($key == '__channels') {
        !          69335:                 foreach ($data['__channels'] as $channel => $blah) {
        !          69336:                     $this->_encodeOutput($data['__channels'][$channel]);
        !          69337:                 }
        !          69338:             }
        !          69339: 
        !          69340:             if (!isset($this->configuration_info[$key])) {
        !          69341:                 continue;
        !          69342:             }
        !          69343: 
        !          69344:             $type = $this->configuration_info[$key]['type'];
        !          69345:             switch ($type) {
        !          69346:                 // we base64-encode passwords so they are at least
        !          69347:                 // not shown in plain by accident
        !          69348:                 case 'password': {
        !          69349:                     $data[$key] = base64_encode($data[$key]);
        !          69350:                     break;
        !          69351:                 }
        !          69352:                 case 'mask': {
        !          69353:                     $data[$key] = octdec($data[$key]);
        !          69354:                     break;
        !          69355:                 }
        !          69356:             }
        !          69357:         }
        !          69358: 
        !          69359:         return true;
        !          69360:     }
        !          69361: 
        !          69362:     /**
        !          69363:      * Decodes/unscrambles configuration data after reading from files.
        !          69364:      *
        !          69365:      * @param array (reference) array to encode values in
        !          69366:      * @return bool TRUE on success
        !          69367:      * @access private
        !          69368:      *
        !          69369:      * @see PEAR_Config::_encodeOutput
        !          69370:      */
        !          69371:     function _decodeInput(&$data)
        !          69372:     {
        !          69373:         if (!is_array($data)) {
        !          69374:             return true;
        !          69375:         }
        !          69376: 
        !          69377:         foreach ($data as $key => $value) {
        !          69378:             if ($key == '__channels') {
        !          69379:                 foreach ($data['__channels'] as $channel => $blah) {
        !          69380:                     $this->_decodeInput($data['__channels'][$channel]);
        !          69381:                 }
        !          69382:             }
        !          69383: 
        !          69384:             if (!isset($this->configuration_info[$key])) {
        !          69385:                 continue;
        !          69386:             }
        !          69387: 
        !          69388:             $type = $this->configuration_info[$key]['type'];
        !          69389:             switch ($type) {
        !          69390:                 case 'password': {
        !          69391:                     $data[$key] = base64_decode($data[$key]);
        !          69392:                     break;
        !          69393:                 }
        !          69394:                 case 'mask': {
        !          69395:                     $data[$key] = decoct($data[$key]);
        !          69396:                     break;
        !          69397:                 }
        !          69398:             }
        !          69399:         }
        !          69400: 
        !          69401:         return true;
        !          69402:     }
        !          69403: 
        !          69404:     /**
        !          69405:      * Retrieve the default channel.
        !          69406:      *
        !          69407:      * On startup, channels are not initialized, so if the default channel is not
        !          69408:      * pear.php.net, then initialize the config.
        !          69409:      * @param string registry layer
        !          69410:      * @return string|false
        !          69411:      */
        !          69412:     function getDefaultChannel($layer = null)
        !          69413:     {
        !          69414:         $ret = false;
        !          69415:         if ($layer === null) {
        !          69416:             foreach ($this->layers as $layer) {
        !          69417:                 if (isset($this->configuration[$layer]['default_channel'])) {
        !          69418:                     $ret = $this->configuration[$layer]['default_channel'];
        !          69419:                     break;
        !          69420:                 }
        !          69421:             }
        !          69422:         } elseif (isset($this->configuration[$layer]['default_channel'])) {
        !          69423:             $ret = $this->configuration[$layer]['default_channel'];
        !          69424:         }
        !          69425: 
        !          69426:         if ($ret == 'pear.php.net' && defined('PEAR_RUNTYPE') && PEAR_RUNTYPE == 'pecl') {
        !          69427:             $ret = 'pecl.php.net';
        !          69428:         }
        !          69429: 
        !          69430:         if ($ret) {
        !          69431:             if ($ret != 'pear.php.net') {
        !          69432:                 $this->_lazyChannelSetup();
        !          69433:             }
        !          69434: 
        !          69435:             return $ret;
        !          69436:         }
        !          69437: 
        !          69438:         return PEAR_CONFIG_DEFAULT_CHANNEL;
        !          69439:     }
        !          69440: 
        !          69441:     /**
        !          69442:      * Returns a configuration value, prioritizing layers as per the
        !          69443:      * layers property.
        !          69444:      *
        !          69445:      * @param string config key
        !          69446:      * @return mixed the config value, or NULL if not found
        !          69447:      * @access public
        !          69448:      */
        !          69449:     function get($key, $layer = null, $channel = false)
        !          69450:     {
        !          69451:         if (!isset($this->configuration_info[$key])) {
        !          69452:             return null;
        !          69453:         }
        !          69454: 
        !          69455:         if ($key == '__channels') {
        !          69456:             return null;
        !          69457:         }
1.1       misho    69458: 
1.1.1.2 ! misho    69459:         if ($key == 'default_channel') {
        !          69460:             return $this->getDefaultChannel($layer);
        !          69461:         }
1.1       misho    69462: 
1.1.1.2 ! misho    69463:         if (!$channel) {
        !          69464:             $channel = $this->getDefaultChannel();
        !          69465:         } elseif ($channel != 'pear.php.net') {
        !          69466:             $this->_lazyChannelSetup();
        !          69467:         }
        !          69468:         $channel = strtolower($channel);
1.1       misho    69469: 
1.1.1.2 ! misho    69470:         $test = (in_array($key, $this->_channelConfigInfo)) ?
        !          69471:             $this->_getChannelValue($key, $layer, $channel) :
        !          69472:             null;
        !          69473:         if ($test !== null) {
        !          69474:             if ($this->_installRoot) {
        !          69475:                 if (in_array($this->getGroup($key),
        !          69476:                       array('File Locations', 'File Locations (Advanced)')) &&
        !          69477:                       $this->getType($key) == 'directory') {
        !          69478:                     return $this->_prependPath($test, $this->_installRoot);
        !          69479:                 }
        !          69480:             }
        !          69481:             return $test;
        !          69482:         }
1.1       misho    69483: 
1.1.1.2 ! misho    69484:         if ($layer === null) {
        !          69485:             foreach ($this->layers as $layer) {
        !          69486:                 if (isset($this->configuration[$layer][$key])) {
        !          69487:                     $test = $this->configuration[$layer][$key];
        !          69488:                     if ($this->_installRoot) {
        !          69489:                         if (in_array($this->getGroup($key),
        !          69490:                               array('File Locations', 'File Locations (Advanced)')) &&
        !          69491:                               $this->getType($key) == 'directory') {
        !          69492:                             return $this->_prependPath($test, $this->_installRoot);
        !          69493:                         }
        !          69494:                     }
1.1       misho    69495: 
1.1.1.2 ! misho    69496:                     if ($key == 'preferred_mirror') {
        !          69497:                         $reg = &$this->getRegistry();
        !          69498:                         if (is_object($reg)) {
        !          69499:                             $chan = &$reg->getChannel($channel);
        !          69500:                             if (PEAR::isError($chan)) {
        !          69501:                                 return $channel;
        !          69502:                             }
1.1       misho    69503: 
1.1.1.2 ! misho    69504:                             if (!$chan->getMirror($test) && $chan->getName() != $test) {
        !          69505:                                 return $channel; // mirror does not exist
        !          69506:                             }
        !          69507:                         }
        !          69508:                     }
        !          69509:                     return $test;
        !          69510:                 }
        !          69511:             }
        !          69512:         } elseif (isset($this->configuration[$layer][$key])) {
        !          69513:             $test = $this->configuration[$layer][$key];
        !          69514:             if ($this->_installRoot) {
        !          69515:                 if (in_array($this->getGroup($key),
        !          69516:                       array('File Locations', 'File Locations (Advanced)')) &&
        !          69517:                       $this->getType($key) == 'directory') {
        !          69518:                     return $this->_prependPath($test, $this->_installRoot);
        !          69519:                 }
        !          69520:             }
1.1       misho    69521: 
1.1.1.2 ! misho    69522:             if ($key == 'preferred_mirror') {
        !          69523:                 $reg = &$this->getRegistry();
        !          69524:                 if (is_object($reg)) {
        !          69525:                     $chan = &$reg->getChannel($channel);
        !          69526:                     if (PEAR::isError($chan)) {
        !          69527:                         return $channel;
        !          69528:                     }
        !          69529: 
        !          69530:                     if (!$chan->getMirror($test) && $chan->getName() != $test) {
        !          69531:                         return $channel; // mirror does not exist
        !          69532:                     }
        !          69533:                 }
        !          69534:             }
        !          69535: 
        !          69536:             return $test;
        !          69537:         }
        !          69538: 
        !          69539:         return null;
        !          69540:     }
        !          69541: 
        !          69542:     /**
        !          69543:      * Returns a channel-specific configuration value, prioritizing layers as per the
        !          69544:      * layers property.
        !          69545:      *
        !          69546:      * @param string config key
        !          69547:      * @return mixed the config value, or NULL if not found
        !          69548:      * @access private
        !          69549:      */
        !          69550:     function _getChannelValue($key, $layer, $channel)
        !          69551:     {
        !          69552:         if ($key == '__channels' || $channel == 'pear.php.net') {
        !          69553:             return null;
        !          69554:         }
        !          69555: 
        !          69556:         $ret = null;
        !          69557:         if ($layer === null) {
        !          69558:             foreach ($this->layers as $ilayer) {
        !          69559:                 if (isset($this->configuration[$ilayer]['__channels'][$channel][$key])) {
        !          69560:                     $ret = $this->configuration[$ilayer]['__channels'][$channel][$key];
        !          69561:                     break;
        !          69562:                 }
        !          69563:             }
        !          69564:         } elseif (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
        !          69565:             $ret = $this->configuration[$layer]['__channels'][$channel][$key];
        !          69566:         }
        !          69567: 
        !          69568:         if ($key != 'preferred_mirror') {
        !          69569:             return $ret;
        !          69570:         }
        !          69571: 
        !          69572: 
        !          69573:         if ($ret !== null) {
        !          69574:             $reg = &$this->getRegistry($layer);
        !          69575:             if (is_object($reg)) {
        !          69576:                 $chan = &$reg->getChannel($channel);
        !          69577:                 if (PEAR::isError($chan)) {
        !          69578:                     return $channel;
        !          69579:                 }
        !          69580: 
        !          69581:                 if (!$chan->getMirror($ret) && $chan->getName() != $ret) {
        !          69582:                     return $channel; // mirror does not exist
        !          69583:                 }
        !          69584:             }
        !          69585: 
        !          69586:             return $ret;
        !          69587:         }
        !          69588: 
        !          69589:         if ($channel != $this->getDefaultChannel($layer)) {
        !          69590:             return $channel; // we must use the channel name as the preferred mirror
        !          69591:                              // if the user has not chosen an alternate
        !          69592:         }
        !          69593: 
        !          69594:         return $this->getDefaultChannel($layer);
        !          69595:     }
        !          69596: 
        !          69597:     /**
        !          69598:      * Set a config value in a specific layer (defaults to 'user').
        !          69599:      * Enforces the types defined in the configuration_info array.  An
        !          69600:      * integer config variable will be cast to int, and a set config
        !          69601:      * variable will be validated against its legal values.
        !          69602:      *
        !          69603:      * @param string config key
        !          69604:      * @param string config value
        !          69605:      * @param string (optional) config layer
        !          69606:      * @param string channel to set this value for, or null for global value
        !          69607:      * @return bool TRUE on success, FALSE on failure
        !          69608:      */
        !          69609:     function set($key, $value, $layer = 'user', $channel = false)
        !          69610:     {
        !          69611:         if ($key == '__channels') {
        !          69612:             return false;
        !          69613:         }
        !          69614: 
        !          69615:         if (!isset($this->configuration[$layer])) {
        !          69616:             return false;
        !          69617:         }
        !          69618: 
        !          69619:         if ($key == 'default_channel') {
        !          69620:             // can only set this value globally
        !          69621:             $channel = 'pear.php.net';
        !          69622:             if ($value != 'pear.php.net') {
        !          69623:                 $this->_lazyChannelSetup($layer);
        !          69624:             }
        !          69625:         }
        !          69626: 
        !          69627:         if ($key == 'preferred_mirror') {
        !          69628:             if ($channel == '__uri') {
        !          69629:                 return false; // can't set the __uri pseudo-channel's mirror
        !          69630:             }
        !          69631: 
        !          69632:             $reg = &$this->getRegistry($layer);
        !          69633:             if (is_object($reg)) {
        !          69634:                 $chan = &$reg->getChannel($channel ? $channel : 'pear.php.net');
        !          69635:                 if (PEAR::isError($chan)) {
        !          69636:                     return false;
        !          69637:                 }
        !          69638: 
        !          69639:                 if (!$chan->getMirror($value) && $chan->getName() != $value) {
        !          69640:                     return false; // mirror does not exist
        !          69641:                 }
        !          69642:             }
        !          69643:         }
        !          69644: 
        !          69645:         if (!isset($this->configuration_info[$key])) {
        !          69646:             return false;
        !          69647:         }
        !          69648: 
        !          69649:         extract($this->configuration_info[$key]);
        !          69650:         switch ($type) {
        !          69651:             case 'integer':
        !          69652:                 $value = (int)$value;
        !          69653:                 break;
        !          69654:             case 'set': {
        !          69655:                 // If a valid_set is specified, require the value to
        !          69656:                 // be in the set.  If there is no valid_set, accept
        !          69657:                 // any value.
        !          69658:                 if ($valid_set) {
        !          69659:                     reset($valid_set);
        !          69660:                     if ((key($valid_set) === 0 && !in_array($value, $valid_set)) ||
        !          69661:                         (key($valid_set) !== 0 && empty($valid_set[$value])))
        !          69662:                     {
        !          69663:                         return false;
        !          69664:                     }
        !          69665:                 }
        !          69666:                 break;
        !          69667:             }
        !          69668:         }
        !          69669: 
        !          69670:         if (!$channel) {
        !          69671:             $channel = $this->get('default_channel', null, 'pear.php.net');
        !          69672:         }
        !          69673: 
        !          69674:         if (!in_array($channel, $this->_channels)) {
        !          69675:             $this->_lazyChannelSetup($layer);
        !          69676:             $reg = &$this->getRegistry($layer);
        !          69677:             if ($reg) {
        !          69678:                 $channel = $reg->channelName($channel);
        !          69679:             }
        !          69680: 
        !          69681:             if (!in_array($channel, $this->_channels)) {
        !          69682:                 return false;
        !          69683:             }
        !          69684:         }
        !          69685: 
        !          69686:         if ($channel != 'pear.php.net') {
        !          69687:             if (in_array($key, $this->_channelConfigInfo)) {
        !          69688:                 $this->configuration[$layer]['__channels'][$channel][$key] = $value;
        !          69689:                 return true;
        !          69690:             }
        !          69691: 
        !          69692:             return false;
        !          69693:         }
        !          69694: 
        !          69695:         if ($key == 'default_channel') {
        !          69696:             if (!isset($reg)) {
        !          69697:                 $reg = &$this->getRegistry($layer);
        !          69698:                 if (!$reg) {
        !          69699:                     $reg = &$this->getRegistry();
        !          69700:                 }
        !          69701:             }
        !          69702: 
        !          69703:             if ($reg) {
        !          69704:                 $value = $reg->channelName($value);
        !          69705:             }
        !          69706: 
        !          69707:             if (!$value) {
        !          69708:                 return false;
        !          69709:             }
        !          69710:         }
        !          69711: 
        !          69712:         $this->configuration[$layer][$key] = $value;
        !          69713:         if ($key == 'php_dir' && !$this->_noRegistry) {
        !          69714:             if (!isset($this->_registry[$layer]) ||
        !          69715:                   $value != $this->_registry[$layer]->install_dir) {
        !          69716:                 $this->_registry[$layer] = &new PEAR_Registry($value);
        !          69717:                 $this->_regInitialized[$layer] = false;
        !          69718:                 $this->_registry[$layer]->setConfig($this, false);
        !          69719:             }
        !          69720:         }
        !          69721: 
        !          69722:         return true;
        !          69723:     }
        !          69724: 
        !          69725:     function _lazyChannelSetup($uselayer = false)
        !          69726:     {
        !          69727:         if ($this->_noRegistry) {
        !          69728:             return;
        !          69729:         }
        !          69730: 
        !          69731:         $merge = false;
        !          69732:         foreach ($this->_registry as $layer => $p) {
        !          69733:             if ($uselayer && $uselayer != $layer) {
        !          69734:                 continue;
        !          69735:             }
        !          69736: 
        !          69737:             if (!$this->_regInitialized[$layer]) {
        !          69738:                 if ($layer == 'default' && isset($this->_registry['user']) ||
        !          69739:                       isset($this->_registry['system'])) {
        !          69740:                     // only use the default registry if there are no alternatives
        !          69741:                     continue;
        !          69742:                 }
        !          69743: 
        !          69744:                 if (!is_object($this->_registry[$layer])) {
        !          69745:                     if ($phpdir = $this->get('php_dir', $layer, 'pear.php.net')) {
        !          69746:                         $this->_registry[$layer] = &new PEAR_Registry($phpdir);
        !          69747:                         $this->_registry[$layer]->setConfig($this, false);
        !          69748:                         $this->_regInitialized[$layer] = false;
        !          69749:                     } else {
        !          69750:                         unset($this->_registry[$layer]);
        !          69751:                         return;
        !          69752:                     }
        !          69753:                 }
        !          69754: 
        !          69755:                 $this->setChannels($this->_registry[$layer]->listChannels(), $merge);
        !          69756:                 $this->_regInitialized[$layer] = true;
        !          69757:                 $merge = true;
        !          69758:             }
        !          69759:         }
        !          69760:     }
        !          69761: 
        !          69762:     /**
        !          69763:      * Set the list of channels.
        !          69764:      *
        !          69765:      * This should be set via a call to {@link PEAR_Registry::listChannels()}
        !          69766:      * @param array
        !          69767:      * @param bool
        !          69768:      * @return bool success of operation
        !          69769:      */
        !          69770:     function setChannels($channels, $merge = false)
        !          69771:     {
        !          69772:         if (!is_array($channels)) {
        !          69773:             return false;
        !          69774:         }
        !          69775: 
        !          69776:         if ($merge) {
        !          69777:             $this->_channels = array_merge($this->_channels, $channels);
        !          69778:         } else {
        !          69779:             $this->_channels = $channels;
        !          69780:         }
        !          69781: 
        !          69782:         foreach ($channels as $channel) {
        !          69783:             $channel = strtolower($channel);
        !          69784:             if ($channel == 'pear.php.net') {
        !          69785:                 continue;
        !          69786:             }
        !          69787: 
        !          69788:             foreach ($this->layers as $layer) {
        !          69789:                 if (!isset($this->configuration[$layer]['__channels'])) {
        !          69790:                     $this->configuration[$layer]['__channels'] = array();
        !          69791:                 }
        !          69792:                 if (!isset($this->configuration[$layer]['__channels'][$channel])
        !          69793:                       || !is_array($this->configuration[$layer]['__channels'][$channel])) {
        !          69794:                     $this->configuration[$layer]['__channels'][$channel] = array();
        !          69795:                 }
        !          69796:             }
        !          69797:         }
        !          69798: 
        !          69799:         return true;
        !          69800:     }
        !          69801: 
        !          69802:     /**
        !          69803:      * Get the type of a config value.
        !          69804:      *
        !          69805:      * @param string  config key
        !          69806:      *
        !          69807:      * @return string type, one of "string", "integer", "file",
        !          69808:      * "directory", "set" or "password".
        !          69809:      *
        !          69810:      * @access public
        !          69811:      *
        !          69812:      */
        !          69813:     function getType($key)
        !          69814:     {
        !          69815:         if (isset($this->configuration_info[$key])) {
        !          69816:             return $this->configuration_info[$key]['type'];
        !          69817:         }
        !          69818:         return false;
        !          69819:     }
        !          69820: 
        !          69821:     /**
        !          69822:      * Get the documentation for a config value.
        !          69823:      *
        !          69824:      * @param string  config key
        !          69825:      * @return string documentation string
        !          69826:      *
        !          69827:      * @access public
        !          69828:      *
        !          69829:      */
        !          69830:     function getDocs($key)
        !          69831:     {
        !          69832:         if (isset($this->configuration_info[$key])) {
        !          69833:             return $this->configuration_info[$key]['doc'];
        !          69834:         }
        !          69835: 
        !          69836:         return false;
        !          69837:     }
        !          69838: 
        !          69839:     /**
        !          69840:      * Get the short documentation for a config value.
        !          69841:      *
        !          69842:      * @param string  config key
        !          69843:      * @return string short documentation string
        !          69844:      *
        !          69845:      * @access public
        !          69846:      *
        !          69847:      */
        !          69848:     function getPrompt($key)
        !          69849:     {
        !          69850:         if (isset($this->configuration_info[$key])) {
        !          69851:             return $this->configuration_info[$key]['prompt'];
        !          69852:         }
        !          69853: 
        !          69854:         return false;
        !          69855:     }
        !          69856: 
        !          69857:     /**
        !          69858:      * Get the parameter group for a config key.
        !          69859:      *
        !          69860:      * @param string  config key
        !          69861:      * @return string parameter group
        !          69862:      *
        !          69863:      * @access public
        !          69864:      *
        !          69865:      */
        !          69866:     function getGroup($key)
        !          69867:     {
        !          69868:         if (isset($this->configuration_info[$key])) {
        !          69869:             return $this->configuration_info[$key]['group'];
        !          69870:         }
        !          69871: 
        !          69872:         return false;
        !          69873:     }
        !          69874: 
        !          69875:     /**
        !          69876:      * Get the list of parameter groups.
        !          69877:      *
        !          69878:      * @return array list of parameter groups
        !          69879:      *
        !          69880:      * @access public
        !          69881:      *
        !          69882:      */
        !          69883:     function getGroups()
        !          69884:     {
        !          69885:         $tmp = array();
        !          69886:         foreach ($this->configuration_info as $key => $info) {
        !          69887:             $tmp[$info['group']] = 1;
        !          69888:         }
        !          69889: 
        !          69890:         return array_keys($tmp);
        !          69891:     }
        !          69892: 
        !          69893:     /**
        !          69894:      * Get the list of the parameters in a group.
        !          69895:      *
        !          69896:      * @param string $group parameter group
        !          69897:      * @return array list of parameters in $group
        !          69898:      *
        !          69899:      * @access public
        !          69900:      *
        !          69901:      */
        !          69902:     function getGroupKeys($group)
        !          69903:     {
        !          69904:         $keys = array();
        !          69905:         foreach ($this->configuration_info as $key => $info) {
        !          69906:             if ($info['group'] == $group) {
        !          69907:                 $keys[] = $key;
        !          69908:             }
        !          69909:         }
        !          69910: 
        !          69911:         return $keys;
        !          69912:     }
        !          69913: 
        !          69914:     /**
        !          69915:      * Get the list of allowed set values for a config value.  Returns
        !          69916:      * NULL for config values that are not sets.
        !          69917:      *
        !          69918:      * @param string  config key
        !          69919:      * @return array enumerated array of set values, or NULL if the
        !          69920:      *               config key is unknown or not a set
        !          69921:      *
        !          69922:      * @access public
        !          69923:      *
        !          69924:      */
        !          69925:     function getSetValues($key)
        !          69926:     {
        !          69927:         if (isset($this->configuration_info[$key]) &&
        !          69928:             isset($this->configuration_info[$key]['type']) &&
        !          69929:             $this->configuration_info[$key]['type'] == 'set')
        !          69930:         {
        !          69931:             $valid_set = $this->configuration_info[$key]['valid_set'];
        !          69932:             reset($valid_set);
        !          69933:             if (key($valid_set) === 0) {
        !          69934:                 return $valid_set;
        !          69935:             }
1.1       misho    69936: 
1.1.1.2 ! misho    69937:             return array_keys($valid_set);
        !          69938:         }
1.1       misho    69939: 
1.1.1.2 ! misho    69940:         return null;
        !          69941:     }
1.1       misho    69942: 
                   69943:     /**
1.1.1.2 ! misho    69944:      * Get all the current config keys.
1.1       misho    69945:      *
1.1.1.2 ! misho    69946:      * @return array simple array of config keys
        !          69947:      *
        !          69948:      * @access public
1.1       misho    69949:      */
1.1.1.2 ! misho    69950:     function getKeys()
        !          69951:     {
        !          69952:         $keys = array();
        !          69953:         foreach ($this->layers as $layer) {
        !          69954:             $test = $this->configuration[$layer];
        !          69955:             if (isset($test['__channels'])) {
        !          69956:                 foreach ($test['__channels'] as $channel => $configs) {
        !          69957:                     $keys = array_merge($keys, $configs);
        !          69958:                 }
        !          69959:             }
1.1       misho    69960: 
1.1.1.2 ! misho    69961:             unset($test['__channels']);
        !          69962:             $keys = array_merge($keys, $test);
        !          69963: 
        !          69964:         }
        !          69965:         return array_keys($keys);
        !          69966:     }
1.1       misho    69967: 
                   69968:     /**
1.1.1.2 ! misho    69969:      * Remove the a config key from a specific config layer.
1.1       misho    69970:      *
1.1.1.2 ! misho    69971:      * @param string config key
        !          69972:      * @param string (optional) config layer
        !          69973:      * @param string (optional) channel (defaults to default channel)
        !          69974:      * @return bool TRUE on success, FALSE on failure
1.1       misho    69975:      *
1.1.1.2 ! misho    69976:      * @access public
1.1       misho    69977:      */
1.1.1.2 ! misho    69978:     function remove($key, $layer = 'user', $channel = null)
        !          69979:     {
        !          69980:         if ($channel === null) {
        !          69981:             $channel = $this->getDefaultChannel();
        !          69982:         }
        !          69983: 
        !          69984:         if ($channel !== 'pear.php.net') {
        !          69985:             if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
        !          69986:                 unset($this->configuration[$layer]['__channels'][$channel][$key]);
        !          69987:                 return true;
        !          69988:             }
        !          69989:         }
        !          69990: 
        !          69991:         if (isset($this->configuration[$layer][$key])) {
        !          69992:             unset($this->configuration[$layer][$key]);
        !          69993:             return true;
        !          69994:         }
        !          69995: 
        !          69996:         return false;
        !          69997:     }
1.1       misho    69998: 
                   69999:     /**
1.1.1.2 ! misho    70000:      * Temporarily remove an entire config layer.  USE WITH CARE!
1.1       misho    70001:      *
1.1.1.2 ! misho    70002:      * @param string config key
        !          70003:      * @param string (optional) config layer
        !          70004:      * @return bool TRUE on success, FALSE on failure
        !          70005:      *
        !          70006:      * @access public
1.1       misho    70007:      */
1.1.1.2 ! misho    70008:     function removeLayer($layer)
        !          70009:     {
        !          70010:         if (isset($this->configuration[$layer])) {
        !          70011:             $this->configuration[$layer] = array();
        !          70012:             return true;
        !          70013:         }
        !          70014: 
        !          70015:         return false;
        !          70016:     }
1.1       misho    70017: 
                   70018:     /**
1.1.1.2 ! misho    70019:      * Stores configuration data in a layer.
        !          70020:      *
        !          70021:      * @param string config layer to store
        !          70022:      * @return bool TRUE on success, or PEAR error on failure
        !          70023:      *
        !          70024:      * @access public
1.1       misho    70025:      */
1.1.1.2 ! misho    70026:     function store($layer = 'user', $data = null)
        !          70027:     {
        !          70028:         return $this->writeConfigFile(null, $layer, $data);
        !          70029:     }
1.1       misho    70030: 
                   70031:     /**
1.1.1.2 ! misho    70032:      * Tells what config layer that gets to define a key.
        !          70033:      *
        !          70034:      * @param string config key
        !          70035:      * @param boolean return the defining channel
        !          70036:      *
        !          70037:      * @return string|array the config layer, or an empty string if not found.
        !          70038:      *
        !          70039:      *         if $returnchannel, the return is an array array('layer' => layername,
        !          70040:      *         'channel' => channelname), or an empty string if not found
        !          70041:      *
        !          70042:      * @access public
1.1       misho    70043:      */
1.1.1.2 ! misho    70044:     function definedBy($key, $returnchannel = false)
        !          70045:     {
        !          70046:         foreach ($this->layers as $layer) {
        !          70047:             $channel = $this->getDefaultChannel();
        !          70048:             if ($channel !== 'pear.php.net') {
        !          70049:                 if (isset($this->configuration[$layer]['__channels'][$channel][$key])) {
        !          70050:                     if ($returnchannel) {
        !          70051:                         return array('layer' => $layer, 'channel' => $channel);
        !          70052:                     }
        !          70053:                     return $layer;
        !          70054:                 }
        !          70055:             }
        !          70056: 
        !          70057:             if (isset($this->configuration[$layer][$key])) {
        !          70058:                 if ($returnchannel) {
        !          70059:                     return array('layer' => $layer, 'channel' => 'pear.php.net');
        !          70060:                 }
        !          70061:                 return $layer;
        !          70062:             }
        !          70063:         }
        !          70064: 
        !          70065:         return '';
        !          70066:     }
1.1       misho    70067: 
                   70068:     /**
1.1.1.2 ! misho    70069:      * Tells whether a given key exists as a config value.
        !          70070:      *
        !          70071:      * @param string config key
        !          70072:      * @return bool whether <config key> exists in this object
        !          70073:      *
        !          70074:      * @access public
1.1       misho    70075:      */
1.1.1.2 ! misho    70076:     function isDefined($key)
        !          70077:     {
        !          70078:         foreach ($this->layers as $layer) {
        !          70079:             if (isset($this->configuration[$layer][$key])) {
        !          70080:                 return true;
        !          70081:             }
        !          70082:         }
        !          70083: 
        !          70084:         return false;
        !          70085:     }
1.1       misho    70086: 
                   70087:     /**
1.1.1.2 ! misho    70088:      * Tells whether a given config layer exists.
        !          70089:      *
        !          70090:      * @param string config layer
        !          70091:      * @return bool whether <config layer> exists in this object
        !          70092:      *
        !          70093:      * @access public
1.1       misho    70094:      */
1.1.1.2 ! misho    70095:     function isDefinedLayer($layer)
        !          70096:     {
        !          70097:         return isset($this->configuration[$layer]);
        !          70098:     }
1.1       misho    70099: 
                   70100:     /**
1.1.1.2 ! misho    70101:      * Returns the layers defined (except the 'default' one)
        !          70102:      *
        !          70103:      * @return array of the defined layers
1.1       misho    70104:      */
1.1.1.2 ! misho    70105:     function getLayers()
        !          70106:     {
        !          70107:         $cf = $this->configuration;
        !          70108:         unset($cf['default']);
        !          70109:         return array_keys($cf);
        !          70110:     }
        !          70111: 
        !          70112:     function apiVersion()
        !          70113:     {
        !          70114:         return '1.1';
        !          70115:     }
1.1       misho    70116: 
                   70117:     /**
1.1.1.2 ! misho    70118:      * @return PEAR_Registry
1.1       misho    70119:      */
1.1.1.2 ! misho    70120:     function &getRegistry($use = null)
        !          70121:     {
        !          70122:         $layer = $use === null ? 'user' : $use;
        !          70123:         if (isset($this->_registry[$layer])) {
        !          70124:             return $this->_registry[$layer];
        !          70125:         } elseif ($use === null && isset($this->_registry['system'])) {
        !          70126:             return $this->_registry['system'];
        !          70127:         } elseif ($use === null && isset($this->_registry['default'])) {
        !          70128:             return $this->_registry['default'];
        !          70129:         } elseif ($use) {
        !          70130:             $a = false;
        !          70131:             return $a;
        !          70132:         }
        !          70133: 
        !          70134:         // only go here if null was passed in
        !          70135:         echo "CRITICAL ERROR: Registry could not be initialized from any value";
        !          70136:         exit(1);
        !          70137:     }
1.1       misho    70138: 
                   70139:     /**
1.1.1.2 ! misho    70140:      * This is to allow customization like the use of installroot
        !          70141:      * @param PEAR_Registry
        !          70142:      * @return bool
1.1       misho    70143:      */
1.1.1.2 ! misho    70144:     function setRegistry(&$reg, $layer = 'user')
        !          70145:     {
        !          70146:         if ($this->_noRegistry) {
        !          70147:             return false;
        !          70148:         }
        !          70149: 
        !          70150:         if (!in_array($layer, array('user', 'system'))) {
        !          70151:             return false;
        !          70152:         }
        !          70153: 
        !          70154:         $this->_registry[$layer] = &$reg;
        !          70155:         if (is_object($reg)) {
        !          70156:             $this->_registry[$layer]->setConfig($this, false);
        !          70157:         }
        !          70158: 
        !          70159:         return true;
        !          70160:     }
        !          70161: 
        !          70162:     function noRegistry()
        !          70163:     {
        !          70164:         $this->_noRegistry = true;
        !          70165:     }
1.1       misho    70166: 
                   70167:     /**
1.1.1.2 ! misho    70168:      * @return PEAR_REST
1.1       misho    70169:      */
1.1.1.2 ! misho    70170:     function &getREST($version, $options = array())
1.1       misho    70171:     {
1.1.1.2 ! misho    70172:         $version = str_replace('.', '', $version);
        !          70173:         if (!class_exists($class = 'PEAR_REST_' . $version)) {
        !          70174:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/REST/' . $version . '.php';
1.1       misho    70175:         }
                   70176: 
1.1.1.2 ! misho    70177:         $remote = &new $class($this, $options);
        !          70178:         return $remote;
        !          70179:     }
        !          70180: 
        !          70181:     /**
        !          70182:      * The ftp server is set in {@link readFTPConfigFile()}.  It exists only if a
        !          70183:      * remote configuration file has been specified
        !          70184:      * @return PEAR_FTP|false
        !          70185:      */
        !          70186:     function &getFTP()
        !          70187:     {
        !          70188:         if (isset($this->_ftp)) {
        !          70189:             return $this->_ftp;
        !          70190:         }
        !          70191: 
        !          70192:         $a = false;
        !          70193:         return $a;
        !          70194:     }
        !          70195: 
        !          70196:     function _prependPath($path, $prepend)
        !          70197:     {
        !          70198:         if (strlen($prepend) > 0) {
        !          70199:             if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) {
        !          70200:                 if (preg_match('/^[a-z]:/i', $prepend)) {
        !          70201:                     $prepend = substr($prepend, 2);
        !          70202:                 } elseif ($prepend{0} != '\\') {
        !          70203:                     $prepend = "\\$prepend";
        !          70204:                 }
        !          70205:                 $path = substr($path, 0, 2) . $prepend . substr($path, 2);
1.1       misho    70206:             } else {
1.1.1.2 ! misho    70207:                 $path = $prepend . $path;
1.1       misho    70208:             }
                   70209:         }
1.1.1.2 ! misho    70210:         return $path;
        !          70211:     }
1.1       misho    70212: 
1.1.1.2 ! misho    70213:     /**
        !          70214:      * @param string|false installation directory to prepend to all _dir variables, or false to
        !          70215:      *                     disable
        !          70216:      */
        !          70217:     function setInstallRoot($root)
        !          70218:     {
        !          70219:         if (substr($root, -1) == DIRECTORY_SEPARATOR) {
        !          70220:             $root = substr($root, 0, -1);
        !          70221:         }
        !          70222:         $old = $this->_installRoot;
        !          70223:         $this->_installRoot = $root;
        !          70224:         if (($old != $root) && !$this->_noRegistry) {
        !          70225:             foreach (array_keys($this->_registry) as $layer) {
        !          70226:                 if ($layer == 'ftp' || !isset($this->_registry[$layer])) {
        !          70227:                     continue;
        !          70228:                 }
        !          70229:                 $this->_registry[$layer] =
        !          70230:                     &new PEAR_Registry($this->get('php_dir', $layer, 'pear.php.net'));
        !          70231:                 $this->_registry[$layer]->setConfig($this, false);
        !          70232:                 $this->_regInitialized[$layer] = false;
1.1       misho    70233:             }
                   70234:         }
1.1.1.2 ! misho    70235:     }
        !          70236: }
        !          70237: <?php
        !          70238: /**
        !          70239:  * PEAR_Dependency2, advanced dependency validation
        !          70240:  *
        !          70241:  * PHP versions 4 and 5
        !          70242:  *
        !          70243:  * @category   pear
        !          70244:  * @package    PEAR
        !          70245:  * @author     Greg Beaver <cellog@php.net>
        !          70246:  * @copyright  1997-2009 The Authors
        !          70247:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          70248:  * @version    CVS: $Id: Dependency2.php 313023 2011-07-06 19:17:11Z dufuz $
        !          70249:  * @link       http://pear.php.net/package/PEAR
        !          70250:  * @since      File available since Release 1.4.0a1
        !          70251:  */
1.1       misho    70252: 
1.1.1.2 ! misho    70253: /**
        !          70254:  * Required for the PEAR_VALIDATE_* constants
        !          70255:  */
        !          70256: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Validate.php';
        !          70257: 
        !          70258: /**
        !          70259:  * Dependency check for PEAR packages
        !          70260:  *
        !          70261:  * This class handles both version 1.0 and 2.0 dependencies
        !          70262:  * WARNING: *any* changes to this class must be duplicated in the
        !          70263:  * test_PEAR_Dependency2 class found in tests/PEAR_Dependency2/setup.php.inc,
        !          70264:  * or unit tests will not actually validate the changes
        !          70265:  * @category   pear
        !          70266:  * @package    PEAR
        !          70267:  * @author     Greg Beaver <cellog@php.net>
        !          70268:  * @copyright  1997-2009 The Authors
        !          70269:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          70270:  * @version    Release: 1.9.4
        !          70271:  * @link       http://pear.php.net/package/PEAR
        !          70272:  * @since      Class available since Release 1.4.0a1
        !          70273:  */
        !          70274: class PEAR_Dependency2
        !          70275: {
        !          70276:     /**
        !          70277:      * One of the PEAR_VALIDATE_* states
        !          70278:      * @see PEAR_VALIDATE_NORMAL
        !          70279:      * @var integer
        !          70280:      */
        !          70281:     var $_state;
        !          70282: 
        !          70283:     /**
        !          70284:      * Command-line options to install/upgrade/uninstall commands
        !          70285:      * @param array
        !          70286:      */
        !          70287:     var $_options;
        !          70288: 
        !          70289:     /**
        !          70290:      * @var OS_Guess
        !          70291:      */
        !          70292:     var $_os;
        !          70293: 
        !          70294:     /**
        !          70295:      * @var PEAR_Registry
        !          70296:      */
        !          70297:     var $_registry;
        !          70298: 
        !          70299:     /**
        !          70300:      * @var PEAR_Config
        !          70301:      */
        !          70302:     var $_config;
        !          70303: 
        !          70304:     /**
        !          70305:      * @var PEAR_DependencyDB
        !          70306:      */
        !          70307:     var $_dependencydb;
        !          70308: 
        !          70309:     /**
        !          70310:      * Output of PEAR_Registry::parsedPackageName()
        !          70311:      * @var array
        !          70312:      */
        !          70313:     var $_currentPackage;
1.1       misho    70314: 
1.1.1.2 ! misho    70315:     /**
        !          70316:      * @param PEAR_Config
        !          70317:      * @param array installation options
        !          70318:      * @param array format of PEAR_Registry::parsedPackageName()
        !          70319:      * @param int installation state (one of PEAR_VALIDATE_*)
        !          70320:      */
        !          70321:     function PEAR_Dependency2(&$config, $installoptions, $package,
        !          70322:                               $state = PEAR_VALIDATE_INSTALLING)
        !          70323:     {
        !          70324:         $this->_config = &$config;
        !          70325:         if (!class_exists('PEAR_DependencyDB')) {
        !          70326:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/DependencyDB.php';
1.1       misho    70327:         }
                   70328: 
1.1.1.2 ! misho    70329:         if (isset($installoptions['packagingroot'])) {
        !          70330:             // make sure depdb is in the right location
        !          70331:             $config->setInstallRoot($installoptions['packagingroot']);
1.1       misho    70332:         }
                   70333: 
1.1.1.2 ! misho    70334:         $this->_registry = &$config->getRegistry();
        !          70335:         $this->_dependencydb = &PEAR_DependencyDB::singleton($config);
        !          70336:         if (isset($installoptions['packagingroot'])) {
        !          70337:             $config->setInstallRoot(false);
1.1       misho    70338:         }
                   70339: 
1.1.1.2 ! misho    70340:         $this->_options = $installoptions;
        !          70341:         $this->_state = $state;
        !          70342:         if (!class_exists('OS_Guess')) {
        !          70343:             require_once 'phar://install-pear-nozlib.phar/' . 'OS/Guess.php';
1.1       misho    70344:         }
                   70345: 
1.1.1.2 ! misho    70346:         $this->_os = new OS_Guess;
        !          70347:         $this->_currentPackage = $package;
        !          70348:     }
        !          70349: 
        !          70350:     function _getExtraString($dep)
        !          70351:     {
        !          70352:         $extra = ' (';
        !          70353:         if (isset($dep['uri'])) {
        !          70354:             return '';
        !          70355:         }
        !          70356: 
        !          70357:         if (isset($dep['recommended'])) {
        !          70358:             $extra .= 'recommended version ' . $dep['recommended'];
        !          70359:         } else {
        !          70360:             if (isset($dep['min'])) {
        !          70361:                 $extra .= 'version >= ' . $dep['min'];
        !          70362:             }
        !          70363: 
        !          70364:             if (isset($dep['max'])) {
        !          70365:                 if ($extra != ' (') {
        !          70366:                     $extra .= ', ';
        !          70367:                 }
        !          70368:                 $extra .= 'version <= ' . $dep['max'];
        !          70369:             }
        !          70370: 
        !          70371:             if (isset($dep['exclude'])) {
        !          70372:                 if (!is_array($dep['exclude'])) {
        !          70373:                     $dep['exclude'] = array($dep['exclude']);
        !          70374:                 }
        !          70375: 
        !          70376:                 if ($extra != ' (') {
        !          70377:                     $extra .= ', ';
        !          70378:                 }
        !          70379: 
        !          70380:                 $extra .= 'excluded versions: ';
        !          70381:                 foreach ($dep['exclude'] as $i => $exclude) {
        !          70382:                     if ($i) {
        !          70383:                         $extra .= ', ';
        !          70384:                     }
        !          70385:                     $extra .= $exclude;
        !          70386:                 }
        !          70387:             }
        !          70388:         }
        !          70389: 
        !          70390:         $extra .= ')';
        !          70391:         if ($extra == ' ()') {
        !          70392:             $extra = '';
        !          70393:         }
        !          70394: 
        !          70395:         return $extra;
1.1       misho    70396:     }
                   70397: 
                   70398:     /**
1.1.1.2 ! misho    70399:      * This makes unit-testing a heck of a lot easier
1.1       misho    70400:      */
1.1.1.2 ! misho    70401:     function getPHP_OS()
1.1       misho    70402:     {
1.1.1.2 ! misho    70403:         return PHP_OS;
        !          70404:     }
1.1       misho    70405: 
1.1.1.2 ! misho    70406:     /**
        !          70407:      * This makes unit-testing a heck of a lot easier
        !          70408:      */
        !          70409:     function getsysname()
        !          70410:     {
        !          70411:         return $this->_os->getSysname();
1.1       misho    70412:     }
                   70413: 
                   70414:     /**
1.1.1.2 ! misho    70415:      * Specify a dependency on an OS.  Use arch for detailed os/processor information
1.1       misho    70416:      *
1.1.1.2 ! misho    70417:      * There are two generic OS dependencies that will be the most common, unix and windows.
        !          70418:      * Other options are linux, freebsd, darwin (OS X), sunos, irix, hpux, aix
1.1       misho    70419:      */
1.1.1.2 ! misho    70420:     function validateOsDependency($dep)
1.1       misho    70421:     {
1.1.1.2 ! misho    70422:         if ($this->_state != PEAR_VALIDATE_INSTALLING && $this->_state != PEAR_VALIDATE_DOWNLOADING) {
        !          70423:             return true;
1.1       misho    70424:         }
                   70425: 
1.1.1.2 ! misho    70426:         if ($dep['name'] == '*') {
        !          70427:             return true;
1.1       misho    70428:         }
                   70429: 
1.1.1.2 ! misho    70430:         $not = isset($dep['conflicts']) ? true : false;
        !          70431:         switch (strtolower($dep['name'])) {
        !          70432:             case 'windows' :
        !          70433:                 if ($not) {
        !          70434:                     if (strtolower(substr($this->getPHP_OS(), 0, 3)) == 'win') {
        !          70435:                         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70436:                             return $this->raiseError("Cannot install %s on Windows");
        !          70437:                         }
        !          70438: 
        !          70439:                         return $this->warning("warning: Cannot install %s on Windows");
        !          70440:                     }
        !          70441:                 } else {
        !          70442:                     if (strtolower(substr($this->getPHP_OS(), 0, 3)) != 'win') {
        !          70443:                         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70444:                             return $this->raiseError("Can only install %s on Windows");
        !          70445:                         }
        !          70446: 
        !          70447:                         return $this->warning("warning: Can only install %s on Windows");
        !          70448:                     }
        !          70449:                 }
        !          70450:             break;
        !          70451:             case 'unix' :
        !          70452:                 $unices = array('linux', 'freebsd', 'darwin', 'sunos', 'irix', 'hpux', 'aix');
        !          70453:                 if ($not) {
        !          70454:                     if (in_array($this->getSysname(), $unices)) {
        !          70455:                         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70456:                             return $this->raiseError("Cannot install %s on any Unix system");
        !          70457:                         }
        !          70458: 
        !          70459:                         return $this->warning( "warning: Cannot install %s on any Unix system");
        !          70460:                     }
        !          70461:                 } else {
        !          70462:                     if (!in_array($this->getSysname(), $unices)) {
        !          70463:                         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70464:                             return $this->raiseError("Can only install %s on a Unix system");
        !          70465:                         }
        !          70466: 
        !          70467:                         return $this->warning("warning: Can only install %s on a Unix system");
        !          70468:                     }
        !          70469:                 }
        !          70470:             break;
        !          70471:             default :
        !          70472:                 if ($not) {
        !          70473:                     if (strtolower($dep['name']) == strtolower($this->getSysname())) {
        !          70474:                         if (!isset($this->_options['nodeps']) &&
        !          70475:                               !isset($this->_options['force'])) {
        !          70476:                             return $this->raiseError('Cannot install %s on ' . $dep['name'] .
        !          70477:                                 ' operating system');
        !          70478:                         }
        !          70479: 
        !          70480:                         return $this->warning('warning: Cannot install %s on ' .
        !          70481:                             $dep['name'] . ' operating system');
        !          70482:                     }
        !          70483:                 } else {
        !          70484:                     if (strtolower($dep['name']) != strtolower($this->getSysname())) {
        !          70485:                         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70486:                             return $this->raiseError('Cannot install %s on ' .
        !          70487:                                 $this->getSysname() .
        !          70488:                                 ' operating system, can only install on ' . $dep['name']);
        !          70489:                         }
        !          70490: 
        !          70491:                         return $this->warning('warning: Cannot install %s on ' .
        !          70492:                             $this->getSysname() .
        !          70493:                             ' operating system, can only install on ' . $dep['name']);
        !          70494:                     }
        !          70495:                 }
        !          70496:         }
        !          70497:         return true;
1.1       misho    70498:     }
                   70499: 
                   70500:     /**
1.1.1.2 ! misho    70501:      * This makes unit-testing a heck of a lot easier
1.1       misho    70502:      */
1.1.1.2 ! misho    70503:     function matchSignature($pattern)
1.1       misho    70504:     {
1.1.1.2 ! misho    70505:         return $this->_os->matchSignature($pattern);
1.1       misho    70506:     }
                   70507: 
                   70508:     /**
1.1.1.2 ! misho    70509:      * Specify a complex dependency on an OS/processor/kernel version,
        !          70510:      * Use OS for simple operating system dependency.
        !          70511:      *
        !          70512:      * This is the only dependency that accepts an eregable pattern.  The pattern
        !          70513:      * will be matched against the php_uname() output parsed by OS_Guess
1.1       misho    70514:      */
1.1.1.2 ! misho    70515:     function validateArchDependency($dep)
1.1       misho    70516:     {
1.1.1.2 ! misho    70517:         if ($this->_state != PEAR_VALIDATE_INSTALLING) {
        !          70518:             return true;
1.1       misho    70519:         }
                   70520: 
1.1.1.2 ! misho    70521:         $not = isset($dep['conflicts']) ? true : false;
        !          70522:         if (!$this->matchSignature($dep['pattern'])) {
        !          70523:             if (!$not) {
        !          70524:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70525:                     return $this->raiseError('%s Architecture dependency failed, does not ' .
        !          70526:                         'match "' . $dep['pattern'] . '"');
        !          70527:                 }
1.1       misho    70528: 
1.1.1.2 ! misho    70529:                 return $this->warning('warning: %s Architecture dependency failed, does ' .
        !          70530:                     'not match "' . $dep['pattern'] . '"');
1.1       misho    70531:             }
                   70532: 
1.1.1.2 ! misho    70533:             return true;
1.1       misho    70534:         }
                   70535: 
1.1.1.2 ! misho    70536:         if ($not) {
        !          70537:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70538:                 return $this->raiseError('%s Architecture dependency failed, required "' .
        !          70539:                     $dep['pattern'] . '"');
        !          70540:             }
        !          70541: 
        !          70542:             return $this->warning('warning: %s Architecture dependency failed, ' .
        !          70543:                 'required "' . $dep['pattern'] . '"');
1.1       misho    70544:         }
1.1.1.2 ! misho    70545: 
1.1       misho    70546:         return true;
                   70547:     }
                   70548: 
                   70549:     /**
1.1.1.2 ! misho    70550:      * This makes unit-testing a heck of a lot easier
1.1       misho    70551:      */
1.1.1.2 ! misho    70552:     function extension_loaded($name)
1.1       misho    70553:     {
1.1.1.2 ! misho    70554:         return extension_loaded($name);
        !          70555:     }
1.1       misho    70556: 
1.1.1.2 ! misho    70557:     /**
        !          70558:      * This makes unit-testing a heck of a lot easier
        !          70559:      */
        !          70560:     function phpversion($name = null)
        !          70561:     {
        !          70562:         if ($name !== null) {
        !          70563:             return phpversion($name);
        !          70564:         }
        !          70565: 
        !          70566:         return phpversion();
        !          70567:     }
        !          70568: 
        !          70569:     function validateExtensionDependency($dep, $required = true)
        !          70570:     {
        !          70571:         if ($this->_state != PEAR_VALIDATE_INSTALLING &&
        !          70572:               $this->_state != PEAR_VALIDATE_DOWNLOADING) {
        !          70573:             return true;
        !          70574:         }
        !          70575: 
        !          70576:         $loaded = $this->extension_loaded($dep['name']);
        !          70577:         $extra  = $this->_getExtraString($dep);
        !          70578:         if (isset($dep['exclude'])) {
        !          70579:             if (!is_array($dep['exclude'])) {
        !          70580:                 $dep['exclude'] = array($dep['exclude']);
1.1       misho    70581:             }
1.1.1.2 ! misho    70582:         }
1.1       misho    70583: 
1.1.1.2 ! misho    70584:         if (!isset($dep['min']) && !isset($dep['max']) &&
        !          70585:             !isset($dep['recommended']) && !isset($dep['exclude'])
        !          70586:         ) {
        !          70587:             if ($loaded) {
        !          70588:                 if (isset($dep['conflicts'])) {
        !          70589:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70590:                         return $this->raiseError('%s conflicts with PHP extension "' .
        !          70591:                             $dep['name'] . '"' . $extra);
        !          70592:                     }
1.1       misho    70593: 
1.1.1.2 ! misho    70594:                     return $this->warning('warning: %s conflicts with PHP extension "' .
        !          70595:                         $dep['name'] . '"' . $extra);
        !          70596:                 }
        !          70597: 
        !          70598:                 return true;
1.1       misho    70599:             }
                   70600: 
1.1.1.2 ! misho    70601:             if (isset($dep['conflicts'])) {
        !          70602:                 return true;
1.1       misho    70603:             }
                   70604: 
1.1.1.2 ! misho    70605:             if ($required) {
        !          70606:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70607:                     return $this->raiseError('%s requires PHP extension "' .
        !          70608:                         $dep['name'] . '"' . $extra);
1.1       misho    70609:                 }
1.1.1.2 ! misho    70610: 
        !          70611:                 return $this->warning('warning: %s requires PHP extension "' .
        !          70612:                     $dep['name'] . '"' . $extra);
1.1       misho    70613:             }
                   70614: 
1.1.1.2 ! misho    70615:             return $this->warning('%s can optionally use PHP extension "' .
        !          70616:                 $dep['name'] . '"' . $extra);
        !          70617:         }
        !          70618: 
        !          70619:         if (!$loaded) {
        !          70620:             if (isset($dep['conflicts'])) {
1.1       misho    70621:                 return true;
                   70622:             }
                   70623: 
1.1.1.2 ! misho    70624:             if (!$required) {
        !          70625:                 return $this->warning('%s can optionally use PHP extension "' .
        !          70626:                     $dep['name'] . '"' . $extra);
1.1       misho    70627:             }
                   70628: 
1.1.1.2 ! misho    70629:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70630:                 return $this->raiseError('%s requires PHP extension "' . $dep['name'] .
        !          70631:                     '"' . $extra);
1.1       misho    70632:             }
1.1.1.2 ! misho    70633: 
        !          70634:             return $this->warning('warning: %s requires PHP extension "' . $dep['name'] .
        !          70635:                     '"' . $extra);
1.1       misho    70636:         }
                   70637: 
1.1.1.2 ! misho    70638:         $version = (string) $this->phpversion($dep['name']);
        !          70639:         if (empty($version)) {
        !          70640:             $version = '0';
        !          70641:         }
1.1       misho    70642: 
1.1.1.2 ! misho    70643:         $fail = false;
        !          70644:         if (isset($dep['min']) && !version_compare($version, $dep['min'], '>=')) {
        !          70645:             $fail = true;
1.1       misho    70646:         }
                   70647: 
1.1.1.2 ! misho    70648:         if (isset($dep['max']) && !version_compare($version, $dep['max'], '<=')) {
        !          70649:             $fail = true;
1.1       misho    70650:         }
                   70651: 
1.1.1.2 ! misho    70652:         if ($fail && !isset($dep['conflicts'])) {
        !          70653:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70654:                 return $this->raiseError('%s requires PHP extension "' . $dep['name'] .
        !          70655:                     '"' . $extra . ', installed version is ' . $version);
1.1       misho    70656:             }
                   70657: 
1.1.1.2 ! misho    70658:             return $this->warning('warning: %s requires PHP extension "' . $dep['name'] .
        !          70659:                 '"' . $extra . ', installed version is ' . $version);
        !          70660:         } elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail && isset($dep['conflicts'])) {
        !          70661:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70662:                 return $this->raiseError('%s conflicts with PHP extension "' .
        !          70663:                     $dep['name'] . '"' . $extra . ', installed version is ' . $version);
        !          70664:             }
1.1       misho    70665: 
1.1.1.2 ! misho    70666:             return $this->warning('warning: %s conflicts with PHP extension "' .
        !          70667:                 $dep['name'] . '"' . $extra . ', installed version is ' . $version);
1.1       misho    70668:         }
                   70669: 
1.1.1.2 ! misho    70670:         if (isset($dep['exclude'])) {
        !          70671:             foreach ($dep['exclude'] as $exclude) {
        !          70672:                 if (version_compare($version, $exclude, '==')) {
        !          70673:                     if (isset($dep['conflicts'])) {
        !          70674:                         continue;
        !          70675:                     }
1.1       misho    70676: 
1.1.1.2 ! misho    70677:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70678:                         return $this->raiseError('%s is not compatible with PHP extension "' .
        !          70679:                             $dep['name'] . '" version ' .
        !          70680:                             $exclude);
        !          70681:                     }
        !          70682: 
        !          70683:                     return $this->warning('warning: %s is not compatible with PHP extension "' .
        !          70684:                         $dep['name'] . '" version ' .
        !          70685:                         $exclude);
        !          70686:                 } elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) {
        !          70687:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70688:                         return $this->raiseError('%s conflicts with PHP extension "' .
        !          70689:                             $dep['name'] . '"' . $extra . ', installed version is ' . $version);
        !          70690:                     }
        !          70691: 
        !          70692:                     return $this->warning('warning: %s conflicts with PHP extension "' .
        !          70693:                         $dep['name'] . '"' . $extra . ', installed version is ' . $version);
        !          70694:                 }
        !          70695:             }
1.1       misho    70696:         }
                   70697: 
1.1.1.2 ! misho    70698:         if (isset($dep['recommended'])) {
        !          70699:             if (version_compare($version, $dep['recommended'], '==')) {
        !          70700:                 return true;
1.1       misho    70701:             }
1.1.1.2 ! misho    70702: 
        !          70703:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70704:                 return $this->raiseError('%s dependency: PHP extension ' . $dep['name'] .
        !          70705:                     ' version "' . $version . '"' .
        !          70706:                     ' is not the recommended version "' . $dep['recommended'] .
        !          70707:                     '", but may be compatible, use --force to install');
1.1       misho    70708:             }
1.1.1.2 ! misho    70709: 
        !          70710:             return $this->warning('warning: %s dependency: PHP extension ' .
        !          70711:                 $dep['name'] . ' version "' . $version . '"' .
        !          70712:                 ' is not the recommended version "' . $dep['recommended'].'"');
1.1       misho    70713:         }
                   70714: 
1.1.1.2 ! misho    70715:         return true;
1.1       misho    70716:     }
                   70717: 
1.1.1.2 ! misho    70718:     function validatePhpDependency($dep)
1.1       misho    70719:     {
1.1.1.2 ! misho    70720:         if ($this->_state != PEAR_VALIDATE_INSTALLING &&
        !          70721:               $this->_state != PEAR_VALIDATE_DOWNLOADING) {
1.1       misho    70722:             return true;
                   70723:         }
                   70724: 
1.1.1.2 ! misho    70725:         $version = $this->phpversion();
        !          70726:         $extra   = $this->_getExtraString($dep);
        !          70727:         if (isset($dep['exclude'])) {
        !          70728:             if (!is_array($dep['exclude'])) {
        !          70729:                 $dep['exclude'] = array($dep['exclude']);
        !          70730:             }
1.1       misho    70731:         }
                   70732: 
1.1.1.2 ! misho    70733:         if (isset($dep['min'])) {
        !          70734:             if (!version_compare($version, $dep['min'], '>=')) {
        !          70735:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70736:                     return $this->raiseError('%s requires PHP' .
        !          70737:                         $extra . ', installed version is ' . $version);
        !          70738:                 }
1.1       misho    70739: 
1.1.1.2 ! misho    70740:                 return $this->warning('warning: %s requires PHP' .
        !          70741:                     $extra . ', installed version is ' . $version);
        !          70742:             }
1.1       misho    70743:         }
                   70744: 
1.1.1.2 ! misho    70745:         if (isset($dep['max'])) {
        !          70746:             if (!version_compare($version, $dep['max'], '<=')) {
        !          70747:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70748:                     return $this->raiseError('%s requires PHP' .
        !          70749:                         $extra . ', installed version is ' . $version);
        !          70750:                 }
1.1       misho    70751: 
1.1.1.2 ! misho    70752:                 return $this->warning('warning: %s requires PHP' .
        !          70753:                     $extra . ', installed version is ' . $version);
        !          70754:             }
1.1       misho    70755:         }
                   70756: 
1.1.1.2 ! misho    70757:         if (isset($dep['exclude'])) {
        !          70758:             foreach ($dep['exclude'] as $exclude) {
        !          70759:                 if (version_compare($version, $exclude, '==')) {
        !          70760:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70761:                         return $this->raiseError('%s is not compatible with PHP version ' .
        !          70762:                             $exclude);
        !          70763:                     }
        !          70764: 
        !          70765:                     return $this->warning(
        !          70766:                         'warning: %s is not compatible with PHP version ' .
        !          70767:                         $exclude);
        !          70768:                 }
        !          70769:             }
1.1       misho    70770:         }
1.1.1.2 ! misho    70771: 
1.1       misho    70772:         return true;
                   70773:     }
                   70774: 
                   70775:     /**
1.1.1.2 ! misho    70776:      * This makes unit-testing a heck of a lot easier
1.1       misho    70777:      */
1.1.1.2 ! misho    70778:     function getPEARVersion()
1.1       misho    70779:     {
1.1.1.2 ! misho    70780:         return '1.9.4';
        !          70781:     }
1.1       misho    70782: 
1.1.1.2 ! misho    70783:     function validatePearinstallerDependency($dep)
        !          70784:     {
        !          70785:         $pearversion = $this->getPEARVersion();
        !          70786:         $extra = $this->_getExtraString($dep);
        !          70787:         if (isset($dep['exclude'])) {
        !          70788:             if (!is_array($dep['exclude'])) {
        !          70789:                 $dep['exclude'] = array($dep['exclude']);
        !          70790:             }
1.1       misho    70791:         }
                   70792: 
1.1.1.2 ! misho    70793:         if (version_compare($pearversion, $dep['min'], '<')) {
        !          70794:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70795:                 return $this->raiseError('%s requires PEAR Installer' . $extra .
        !          70796:                     ', installed version is ' . $pearversion);
        !          70797:             }
        !          70798: 
        !          70799:             return $this->warning('warning: %s requires PEAR Installer' . $extra .
        !          70800:                 ', installed version is ' . $pearversion);
1.1       misho    70801:         }
                   70802: 
1.1.1.2 ! misho    70803:         if (isset($dep['max'])) {
        !          70804:             if (version_compare($pearversion, $dep['max'], '>')) {
        !          70805:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70806:                     return $this->raiseError('%s requires PEAR Installer' . $extra .
        !          70807:                         ', installed version is ' . $pearversion);
        !          70808:                 }
1.1       misho    70809: 
1.1.1.2 ! misho    70810:                 return $this->warning('warning: %s requires PEAR Installer' . $extra .
        !          70811:                     ', installed version is ' . $pearversion);
1.1       misho    70812:             }
                   70813:         }
                   70814: 
1.1.1.2 ! misho    70815:         if (isset($dep['exclude'])) {
        !          70816:             if (!isset($dep['exclude'][0])) {
        !          70817:                 $dep['exclude'] = array($dep['exclude']);
1.1       misho    70818:             }
                   70819: 
1.1.1.2 ! misho    70820:             foreach ($dep['exclude'] as $exclude) {
        !          70821:                 if (version_compare($exclude, $pearversion, '==')) {
        !          70822:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70823:                         return $this->raiseError('%s is not compatible with PEAR Installer ' .
        !          70824:                             'version ' . $exclude);
        !          70825:                     }
        !          70826: 
        !          70827:                     return $this->warning('warning: %s is not compatible with PEAR ' .
        !          70828:                         'Installer version ' . $exclude);
        !          70829:                 }
1.1       misho    70830:             }
                   70831:         }
                   70832: 
1.1.1.2 ! misho    70833:         return true;
1.1       misho    70834:     }
                   70835: 
1.1.1.2 ! misho    70836:     function validateSubpackageDependency($dep, $required, $params)
1.1       misho    70837:     {
1.1.1.2 ! misho    70838:         return $this->validatePackageDependency($dep, $required, $params);
1.1       misho    70839:     }
                   70840: 
                   70841:     /**
1.1.1.2 ! misho    70842:      * @param array dependency information (2.0 format)
        !          70843:      * @param boolean whether this is a required dependency
        !          70844:      * @param array a list of downloaded packages to be installed, if any
        !          70845:      * @param boolean if true, then deps on pear.php.net that fail will also check
        !          70846:      *                against pecl.php.net packages to accomodate extensions that have
        !          70847:      *                moved to pecl.php.net from pear.php.net
1.1       misho    70848:      */
1.1.1.2 ! misho    70849:     function validatePackageDependency($dep, $required, $params, $depv1 = false)
1.1       misho    70850:     {
1.1.1.2 ! misho    70851:         if ($this->_state != PEAR_VALIDATE_INSTALLING &&
        !          70852:               $this->_state != PEAR_VALIDATE_DOWNLOADING) {
        !          70853:             return true;
1.1       misho    70854:         }
                   70855: 
1.1.1.2 ! misho    70856:         if (isset($dep['providesextension'])) {
        !          70857:             if ($this->extension_loaded($dep['providesextension'])) {
        !          70858:                 $save = $dep;
        !          70859:                 $subdep = $dep;
        !          70860:                 $subdep['name'] = $subdep['providesextension'];
        !          70861:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          70862:                 $ret = $this->validateExtensionDependency($subdep, $required);
        !          70863:                 PEAR::popErrorHandling();
        !          70864:                 if (!PEAR::isError($ret)) {
        !          70865:                     return true;
        !          70866:                 }
        !          70867:             }
1.1       misho    70868:         }
                   70869: 
1.1.1.2 ! misho    70870:         if ($this->_state == PEAR_VALIDATE_INSTALLING) {
        !          70871:             return $this->_validatePackageInstall($dep, $required, $depv1);
        !          70872:         }
        !          70873: 
        !          70874:         if ($this->_state == PEAR_VALIDATE_DOWNLOADING) {
        !          70875:             return $this->_validatePackageDownload($dep, $required, $params, $depv1);
        !          70876:         }
        !          70877:     }
        !          70878: 
        !          70879:     function _validatePackageDownload($dep, $required, $params, $depv1 = false)
        !          70880:     {
        !          70881:         $dep['package'] = $dep['name'];
        !          70882:         if (isset($dep['uri'])) {
        !          70883:             $dep['channel'] = '__uri';
        !          70884:         }
        !          70885: 
        !          70886:         $depname = $this->_registry->parsedPackageNameToString($dep, true);
        !          70887:         $found = false;
        !          70888:         foreach ($params as $param) {
        !          70889:             if ($param->isEqual(
        !          70890:                   array('package' => $dep['name'],
        !          70891:                         'channel' => $dep['channel']))) {
        !          70892:                 $found = true;
        !          70893:                 break;
        !          70894:             }
        !          70895: 
        !          70896:             if ($depv1 && $dep['channel'] == 'pear.php.net') {
        !          70897:                 if ($param->isEqual(
        !          70898:                   array('package' => $dep['name'],
        !          70899:                         'channel' => 'pecl.php.net'))) {
        !          70900:                     $found = true;
        !          70901:                     break;
        !          70902:                 }
        !          70903:             }
        !          70904:         }
        !          70905: 
        !          70906:         if (!$found && isset($dep['providesextension'])) {
        !          70907:             foreach ($params as $param) {
        !          70908:                 if ($param->isExtension($dep['providesextension'])) {
        !          70909:                     $found = true;
        !          70910:                     break;
        !          70911:                 }
        !          70912:             }
        !          70913:         }
        !          70914: 
        !          70915:         if ($found) {
        !          70916:             $version = $param->getVersion();
        !          70917:             $installed = false;
        !          70918:             $downloaded = true;
        !          70919:         } else {
        !          70920:             if ($this->_registry->packageExists($dep['name'], $dep['channel'])) {
        !          70921:                 $installed = true;
        !          70922:                 $downloaded = false;
        !          70923:                 $version = $this->_registry->packageinfo($dep['name'], 'version',
        !          70924:                     $dep['channel']);
        !          70925:             } else {
        !          70926:                 if ($dep['channel'] == 'pecl.php.net' && $this->_registry->packageExists($dep['name'],
        !          70927:                       'pear.php.net')) {
        !          70928:                     $installed = true;
        !          70929:                     $downloaded = false;
        !          70930:                     $version = $this->_registry->packageinfo($dep['name'], 'version',
        !          70931:                         'pear.php.net');
        !          70932:                 } else {
        !          70933:                     $version = 'not installed or downloaded';
        !          70934:                     $installed = false;
        !          70935:                     $downloaded = false;
        !          70936:                 }
1.1       misho    70937:             }
1.1.1.2 ! misho    70938:         }
1.1       misho    70939: 
1.1.1.2 ! misho    70940:         $extra = $this->_getExtraString($dep);
        !          70941:         if (isset($dep['exclude']) && !is_array($dep['exclude'])) {
        !          70942:             $dep['exclude'] = array($dep['exclude']);
        !          70943:         }
1.1       misho    70944: 
1.1.1.2 ! misho    70945:         if (!isset($dep['min']) && !isset($dep['max']) &&
        !          70946:               !isset($dep['recommended']) && !isset($dep['exclude'])
        !          70947:         ) {
        !          70948:             if ($installed || $downloaded) {
        !          70949:                 $installed = $installed ? 'installed' : 'downloaded';
        !          70950:                 if (isset($dep['conflicts'])) {
        !          70951:                     $rest = '';
        !          70952:                     if ($version) {
        !          70953:                         $rest = ", $installed version is " . $version;
        !          70954:                     }
1.1       misho    70955: 
1.1.1.2 ! misho    70956:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70957:                         return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra . $rest);
1.1       misho    70958:                     }
1.1.1.2 ! misho    70959: 
        !          70960:                     return $this->warning('warning: %s conflicts with package "' . $depname . '"' . $extra . $rest);
1.1       misho    70961:                 }
                   70962: 
1.1.1.2 ! misho    70963:                 return true;
1.1       misho    70964:             }
                   70965: 
1.1.1.2 ! misho    70966:             if (isset($dep['conflicts'])) {
        !          70967:                 return true;
1.1       misho    70968:             }
                   70969: 
1.1.1.2 ! misho    70970:             if ($required) {
        !          70971:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70972:                     return $this->raiseError('%s requires package "' . $depname . '"' . $extra);
        !          70973:                 }
        !          70974: 
        !          70975:                 return $this->warning('warning: %s requires package "' . $depname . '"' . $extra);
1.1       misho    70976:             }
                   70977: 
1.1.1.2 ! misho    70978:             return $this->warning('%s can optionally use package "' . $depname . '"' . $extra);
        !          70979:         }
        !          70980: 
        !          70981:         if (!$installed && !$downloaded) {
        !          70982:             if (isset($dep['conflicts'])) {
        !          70983:                 return true;
1.1       misho    70984:             }
                   70985: 
1.1.1.2 ! misho    70986:             if ($required) {
        !          70987:                 if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          70988:                     return $this->raiseError('%s requires package "' . $depname . '"' . $extra);
        !          70989:                 }
        !          70990: 
        !          70991:                 return $this->warning('warning: %s requires package "' . $depname . '"' . $extra);
1.1       misho    70992:             }
                   70993: 
1.1.1.2 ! misho    70994:             return $this->warning('%s can optionally use package "' . $depname . '"' . $extra);
1.1       misho    70995:         }
                   70996: 
1.1.1.2 ! misho    70997:         $fail = false;
        !          70998:         if (isset($dep['min']) && version_compare($version, $dep['min'], '<')) {
        !          70999:             $fail = true;
        !          71000:         }
1.1       misho    71001: 
1.1.1.2 ! misho    71002:         if (isset($dep['max']) && version_compare($version, $dep['max'], '>')) {
        !          71003:             $fail = true;
        !          71004:         }
1.1       misho    71005: 
1.1.1.2 ! misho    71006:         if ($fail && !isset($dep['conflicts'])) {
        !          71007:             $installed = $installed ? 'installed' : 'downloaded';
        !          71008:             $dep['package'] = $dep['name'];
        !          71009:             $dep = $this->_registry->parsedPackageNameToString($dep, true);
        !          71010:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          71011:                 return $this->raiseError('%s requires package "' . $depname . '"' .
        !          71012:                     $extra . ", $installed version is " . $version);
1.1       misho    71013:             }
                   71014: 
1.1.1.2 ! misho    71015:             return $this->warning('warning: %s requires package "' . $depname . '"' .
        !          71016:                 $extra . ", $installed version is " . $version);
        !          71017:         } elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail &&
        !          71018:               isset($dep['conflicts']) && !isset($dep['exclude'])) {
        !          71019:             $installed = $installed ? 'installed' : 'downloaded';
        !          71020:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          71021:                 return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra .
        !          71022:                     ", $installed version is " . $version);
1.1       misho    71023:             }
1.1.1.2 ! misho    71024: 
        !          71025:             return $this->warning('warning: %s conflicts with package "' . $depname . '"' .
        !          71026:                 $extra . ", $installed version is " . $version);
1.1       misho    71027:         }
                   71028: 
1.1.1.2 ! misho    71029:         if (isset($dep['exclude'])) {
        !          71030:             $installed = $installed ? 'installed' : 'downloaded';
        !          71031:             foreach ($dep['exclude'] as $exclude) {
        !          71032:                 if (version_compare($version, $exclude, '==') && !isset($dep['conflicts'])) {
        !          71033:                     if (!isset($this->_options['nodeps']) &&
        !          71034:                           !isset($this->_options['force'])
        !          71035:                     ) {
        !          71036:                         return $this->raiseError('%s is not compatible with ' .
        !          71037:                             $installed . ' package "' .
        !          71038:                             $depname . '" version ' .
        !          71039:                             $exclude);
        !          71040:                     }
1.1       misho    71041: 
1.1.1.2 ! misho    71042:                     return $this->warning('warning: %s is not compatible with ' .
        !          71043:                         $installed . ' package "' .
        !          71044:                         $depname . '" version ' .
        !          71045:                         $exclude);
        !          71046:                 } elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) {
        !          71047:                     $installed = $installed ? 'installed' : 'downloaded';
        !          71048:                     if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          71049:                         return $this->raiseError('%s conflicts with package "' . $depname . '"' .
        !          71050:                             $extra . ", $installed version is " . $version);
        !          71051:                     }
1.1       misho    71052: 
1.1.1.2 ! misho    71053:                     return $this->warning('warning: %s conflicts with package "' . $depname . '"' .
        !          71054:                         $extra . ", $installed version is " . $version);
1.1       misho    71055:                 }
                   71056:             }
1.1.1.2 ! misho    71057:         }
1.1       misho    71058: 
1.1.1.2 ! misho    71059:         if (isset($dep['recommended'])) {
        !          71060:             $installed = $installed ? 'installed' : 'downloaded';
        !          71061:             if (version_compare($version, $dep['recommended'], '==')) {
        !          71062:                 return true;
1.1       misho    71063:             }
                   71064: 
1.1.1.2 ! misho    71065:             if (!$found && $installed) {
        !          71066:                 $param = $this->_registry->getPackage($dep['name'], $dep['channel']);
        !          71067:             }
        !          71068: 
        !          71069:             if ($param) {
        !          71070:                 $found = false;
        !          71071:                 foreach ($params as $parent) {
        !          71072:                     if ($parent->isEqual($this->_currentPackage)) {
        !          71073:                         $found = true;
        !          71074:                         break;
        !          71075:                     }
1.1       misho    71076:                 }
1.1.1.2 ! misho    71077: 
        !          71078:                 if ($found) {
        !          71079:                     if ($param->isCompatible($parent)) {
        !          71080:                         return true;
        !          71081:                     }
        !          71082:                 } else { // this is for validPackage() calls
        !          71083:                     $parent = $this->_registry->getPackage($this->_currentPackage['package'],
        !          71084:                         $this->_currentPackage['channel']);
        !          71085:                     if ($parent !== null && $param->isCompatible($parent)) {
        !          71086:                         return true;
        !          71087:                     }
1.1       misho    71088:                 }
                   71089:             }
1.1.1.2 ! misho    71090: 
        !          71091:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force']) &&
        !          71092:                   !isset($this->_options['loose'])
        !          71093:             ) {
        !          71094:                 return $this->raiseError('%s dependency package "' . $depname .
        !          71095:                     '" ' . $installed . ' version ' . $version .
        !          71096:                     ' is not the recommended version ' . $dep['recommended'] .
        !          71097:                     ', but may be compatible, use --force to install');
        !          71098:             }
        !          71099: 
        !          71100:             return $this->warning('warning: %s dependency package "' . $depname .
        !          71101:                 '" ' . $installed . ' version ' . $version .
        !          71102:                 ' is not the recommended version ' . $dep['recommended']);
1.1       misho    71103:         }
                   71104: 
                   71105:         return true;
                   71106:     }
                   71107: 
1.1.1.2 ! misho    71108:     function _validatePackageInstall($dep, $required, $depv1 = false)
        !          71109:     {
        !          71110:         return $this->_validatePackageDownload($dep, $required, array(), $depv1);
        !          71111:     }
        !          71112: 
1.1       misho    71113:     /**
1.1.1.2 ! misho    71114:      * Verify that uninstalling packages passed in to command line is OK.
1.1       misho    71115:      *
1.1.1.2 ! misho    71116:      * @param PEAR_Installer $dl
        !          71117:      * @return PEAR_Error|true
1.1       misho    71118:      */
1.1.1.2 ! misho    71119:     function validatePackageUninstall(&$dl)
1.1       misho    71120:     {
1.1.1.2 ! misho    71121:         if (PEAR::isError($this->_dependencydb)) {
        !          71122:             return $this->_dependencydb;
1.1       misho    71123:         }
                   71124: 
1.1.1.2 ! misho    71125:         $params = array();
        !          71126:         // construct an array of "downloaded" packages to fool the package dependency checker
        !          71127:         // into using these to validate uninstalls of circular dependencies
        !          71128:         $downloaded = &$dl->getUninstallPackages();
        !          71129:         foreach ($downloaded as $i => $pf) {
        !          71130:             if (!class_exists('PEAR_Downloader_Package')) {
        !          71131:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Downloader/Package.php';
        !          71132:             }
        !          71133:             $dp = &new PEAR_Downloader_Package($dl);
        !          71134:             $dp->setPackageFile($downloaded[$i]);
        !          71135:             $params[$i] = &$dp;
1.1       misho    71136:         }
                   71137: 
1.1.1.2 ! misho    71138:         // check cache
        !          71139:         $memyselfandI = strtolower($this->_currentPackage['channel']) . '/' .
        !          71140:             strtolower($this->_currentPackage['package']);
        !          71141:         if (isset($dl->___uninstall_package_cache)) {
        !          71142:             $badpackages = $dl->___uninstall_package_cache;
        !          71143:             if (isset($badpackages[$memyselfandI]['warnings'])) {
        !          71144:                 foreach ($badpackages[$memyselfandI]['warnings'] as $warning) {
        !          71145:                     $dl->log(0, $warning[0]);
        !          71146:                 }
1.1       misho    71147:             }
                   71148: 
1.1.1.2 ! misho    71149:             if (isset($badpackages[$memyselfandI]['errors'])) {
        !          71150:                 foreach ($badpackages[$memyselfandI]['errors'] as $error) {
        !          71151:                     if (is_array($error)) {
        !          71152:                         $dl->log(0, $error[0]);
        !          71153:                     } else {
        !          71154:                         $dl->log(0, $error->getMessage());
        !          71155:                     }
        !          71156:                 }
1.1       misho    71157: 
1.1.1.2 ! misho    71158:                 if (isset($this->_options['nodeps']) || isset($this->_options['force'])) {
        !          71159:                     return $this->warning(
        !          71160:                         'warning: %s should not be uninstalled, other installed packages depend ' .
        !          71161:                         'on this package');
        !          71162:                 }
1.1       misho    71163: 
1.1.1.2 ! misho    71164:                 return $this->raiseError(
        !          71165:                     '%s cannot be uninstalled, other installed packages depend on this package');
        !          71166:             }
1.1       misho    71167: 
1.1.1.2 ! misho    71168:             return true;
1.1       misho    71169:         }
                   71170: 
1.1.1.2 ! misho    71171:         // first, list the immediate parents of each package to be uninstalled
        !          71172:         $perpackagelist = array();
        !          71173:         $allparents = array();
        !          71174:         foreach ($params as $i => $param) {
        !          71175:             $a = array(
        !          71176:                 'channel' => strtolower($param->getChannel()),
        !          71177:                 'package' => strtolower($param->getPackage())
        !          71178:             );
1.1       misho    71179: 
1.1.1.2 ! misho    71180:             $deps = $this->_dependencydb->getDependentPackages($a);
        !          71181:             if ($deps) {
        !          71182:                 foreach ($deps as $d) {
        !          71183:                     $pardeps = $this->_dependencydb->getDependencies($d);
        !          71184:                     foreach ($pardeps as $dep) {
        !          71185:                         if (strtolower($dep['dep']['channel']) == $a['channel'] &&
        !          71186:                               strtolower($dep['dep']['name']) == $a['package']) {
        !          71187:                             if (!isset($perpackagelist[$a['channel'] . '/' . $a['package']])) {
        !          71188:                                 $perpackagelist[$a['channel'] . '/' . $a['package']] = array();
        !          71189:                             }
        !          71190:                             $perpackagelist[$a['channel'] . '/' . $a['package']][]
        !          71191:                                 = array($d['channel'] . '/' . $d['package'], $dep);
        !          71192:                             if (!isset($allparents[$d['channel'] . '/' . $d['package']])) {
        !          71193:                                 $allparents[$d['channel'] . '/' . $d['package']] = array();
        !          71194:                             }
        !          71195:                             if (!isset($allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']])) {
        !          71196:                                 $allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']] = array();
        !          71197:                             }
        !          71198:                             $allparents[$d['channel'] . '/' . $d['package']]
        !          71199:                                        [$a['channel'] . '/' . $a['package']][]
        !          71200:                                 = array($d, $dep);
        !          71201:                         }
        !          71202:                     }
        !          71203:                 }
        !          71204:             }
1.1       misho    71205:         }
                   71206: 
1.1.1.2 ! misho    71207:         // next, remove any packages from the parents list that are not installed
        !          71208:         $remove = array();
        !          71209:         foreach ($allparents as $parent => $d1) {
        !          71210:             foreach ($d1 as $d) {
        !          71211:                 if ($this->_registry->packageExists($d[0][0]['package'], $d[0][0]['channel'])) {
        !          71212:                     continue;
1.1       misho    71213:                 }
1.1.1.2 ! misho    71214:                 $remove[$parent] = true;
1.1       misho    71215:             }
                   71216:         }
                   71217: 
1.1.1.2 ! misho    71218:         // next remove any packages from the parents list that are not passed in for
        !          71219:         // uninstallation
        !          71220:         foreach ($allparents as $parent => $d1) {
        !          71221:             foreach ($d1 as $d) {
        !          71222:                 foreach ($params as $param) {
        !          71223:                     if (strtolower($param->getChannel()) == $d[0][0]['channel'] &&
        !          71224:                           strtolower($param->getPackage()) == $d[0][0]['package']) {
        !          71225:                         // found it
        !          71226:                         continue 3;
1.1       misho    71227:                     }
1.1.1.2 ! misho    71228:                 }
        !          71229:                 $remove[$parent] = true;
        !          71230:             }
        !          71231:         }
1.1       misho    71232: 
1.1.1.2 ! misho    71233:         // remove all packages whose dependencies fail
        !          71234:         // save which ones failed for error reporting
        !          71235:         $badchildren = array();
        !          71236:         do {
        !          71237:             $fail = false;
        !          71238:             foreach ($remove as $package => $unused) {
        !          71239:                 if (!isset($allparents[$package])) {
        !          71240:                     continue;
        !          71241:                 }
1.1       misho    71242: 
1.1.1.2 ! misho    71243:                 foreach ($allparents[$package] as $kid => $d1) {
        !          71244:                     foreach ($d1 as $depinfo) {
        !          71245:                         if ($depinfo[1]['type'] != 'optional') {
        !          71246:                             if (isset($badchildren[$kid])) {
        !          71247:                                 continue;
1.1       misho    71248:                             }
1.1.1.2 ! misho    71249:                             $badchildren[$kid] = true;
        !          71250:                             $remove[$kid] = true;
        !          71251:                             $fail = true;
        !          71252:                             continue 2;
1.1       misho    71253:                         }
                   71254:                     }
1.1.1.2 ! misho    71255:                 }
        !          71256:                 if ($fail) {
        !          71257:                     // start over, we removed some children
        !          71258:                     continue 2;
1.1       misho    71259:                 }
                   71260:             }
1.1.1.2 ! misho    71261:         } while ($fail);
        !          71262: 
        !          71263:         // next, construct the list of packages that can't be uninstalled
        !          71264:         $badpackages = array();
        !          71265:         $save = $this->_currentPackage;
        !          71266:         foreach ($perpackagelist as $package => $packagedeps) {
        !          71267:             foreach ($packagedeps as $parent) {
        !          71268:                 if (!isset($remove[$parent[0]])) {
        !          71269:                     continue;
        !          71270:                 }
        !          71271: 
        !          71272:                 $packagename = $this->_registry->parsePackageName($parent[0]);
        !          71273:                 $packagename['channel'] = $this->_registry->channelAlias($packagename['channel']);
        !          71274:                 $pa = $this->_registry->getPackage($packagename['package'], $packagename['channel']);
        !          71275:                 $packagename['package'] = $pa->getPackage();
        !          71276:                 $this->_currentPackage = $packagename;
        !          71277:                 // parent is not present in uninstall list, make sure we can actually
        !          71278:                 // uninstall it (parent dep is optional)
        !          71279:                 $parentname['channel'] = $this->_registry->channelAlias($parent[1]['dep']['channel']);
        !          71280:                 $pa = $this->_registry->getPackage($parent[1]['dep']['name'], $parent[1]['dep']['channel']);
        !          71281:                 $parentname['package'] = $pa->getPackage();
        !          71282:                 $parent[1]['dep']['package'] = $parentname['package'];
        !          71283:                 $parent[1]['dep']['channel'] = $parentname['channel'];
        !          71284:                 if ($parent[1]['type'] == 'optional') {
        !          71285:                     $test = $this->_validatePackageUninstall($parent[1]['dep'], false, $dl);
        !          71286:                     if ($test !== true) {
        !          71287:                         $badpackages[$package]['warnings'][] = $test;
        !          71288:                     }
        !          71289:                 } else {
        !          71290:                     $test = $this->_validatePackageUninstall($parent[1]['dep'], true, $dl);
        !          71291:                     if ($test !== true) {
        !          71292:                         $badpackages[$package]['errors'][] = $test;
        !          71293:                     }
1.1       misho    71294:                 }
                   71295:             }
1.1.1.2 ! misho    71296:         }
1.1       misho    71297: 
1.1.1.2 ! misho    71298:         $this->_currentPackage          = $save;
        !          71299:         $dl->___uninstall_package_cache = $badpackages;
        !          71300:         if (isset($badpackages[$memyselfandI])) {
        !          71301:             if (isset($badpackages[$memyselfandI]['warnings'])) {
        !          71302:                 foreach ($badpackages[$memyselfandI]['warnings'] as $warning) {
        !          71303:                     $dl->log(0, $warning[0]);
        !          71304:                 }
        !          71305:             }
        !          71306: 
        !          71307:             if (isset($badpackages[$memyselfandI]['errors'])) {
        !          71308:                 foreach ($badpackages[$memyselfandI]['errors'] as $error) {
        !          71309:                     if (is_array($error)) {
        !          71310:                         $dl->log(0, $error[0]);
        !          71311:                     } else {
        !          71312:                         $dl->log(0, $error->getMessage());
1.1       misho    71313:                     }
1.1.1.2 ! misho    71314:                 }
1.1       misho    71315: 
1.1.1.2 ! misho    71316:                 if (isset($this->_options['nodeps']) || isset($this->_options['force'])) {
        !          71317:                     return $this->warning(
        !          71318:                         'warning: %s should not be uninstalled, other installed packages depend ' .
        !          71319:                         'on this package');
1.1       misho    71320:                 }
                   71321: 
1.1.1.2 ! misho    71322:                 return $this->raiseError(
        !          71323:                     '%s cannot be uninstalled, other installed packages depend on this package');
        !          71324:             }
1.1       misho    71325:         }
                   71326: 
1.1.1.2 ! misho    71327:         return true;
1.1       misho    71328:     }
                   71329: 
1.1.1.2 ! misho    71330:     function _validatePackageUninstall($dep, $required, $dl)
1.1       misho    71331:     {
1.1.1.2 ! misho    71332:         $depname = $this->_registry->parsedPackageNameToString($dep, true);
        !          71333:         $version = $this->_registry->packageinfo($dep['package'], 'version', $dep['channel']);
        !          71334:         if (!$version) {
        !          71335:             return true;
1.1       misho    71336:         }
                   71337: 
1.1.1.2 ! misho    71338:         $extra = $this->_getExtraString($dep);
        !          71339:         if (isset($dep['exclude']) && !is_array($dep['exclude'])) {
        !          71340:             $dep['exclude'] = array($dep['exclude']);
1.1       misho    71341:         }
                   71342: 
1.1.1.2 ! misho    71343:         if (isset($dep['conflicts'])) {
        !          71344:             return true; // uninstall OK - these packages conflict (probably installed with --force)
1.1       misho    71345:         }
                   71346: 
1.1.1.2 ! misho    71347:         if (!isset($dep['min']) && !isset($dep['max'])) {
        !          71348:             if (!$required) {
        !          71349:                 return $this->warning('"' . $depname . '" can be optionally used by ' .
        !          71350:                         'installed package %s' . $extra);
        !          71351:             }
1.1       misho    71352: 
1.1.1.2 ! misho    71353:             if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          71354:                 return $this->raiseError('"' . $depname . '" is required by ' .
        !          71355:                     'installed package %s' . $extra);
1.1       misho    71356:             }
                   71357: 
1.1.1.2 ! misho    71358:             return $this->warning('warning: "' . $depname . '" is required by ' .
        !          71359:                 'installed package %s' . $extra);
1.1       misho    71360:         }
                   71361: 
1.1.1.2 ! misho    71362:         $fail = false;
        !          71363:         if (isset($dep['min']) && version_compare($version, $dep['min'], '>=')) {
        !          71364:             $fail = true;
1.1       misho    71365:         }
                   71366: 
1.1.1.2 ! misho    71367:         if (isset($dep['max']) && version_compare($version, $dep['max'], '<=')) {
        !          71368:             $fail = true;
        !          71369:         }
        !          71370: 
        !          71371:         // we re-use this variable, preserve the original value
        !          71372:         $saverequired = $required;
        !          71373:         if (!$required) {
        !          71374:             return $this->warning($depname . $extra . ' can be optionally used by installed package' .
        !          71375:                     ' "%s"');
        !          71376:         }
        !          71377: 
        !          71378:         if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
        !          71379:             return $this->raiseError($depname . $extra . ' is required by installed package' .
        !          71380:                 ' "%s"');
        !          71381:         }
        !          71382: 
        !          71383:         return $this->raiseError('warning: ' . $depname . $extra .
        !          71384:             ' is required by installed package "%s"');
1.1       misho    71385:     }
                   71386: 
                   71387:     /**
1.1.1.2 ! misho    71388:      * validate a downloaded package against installed packages
1.1       misho    71389:      *
1.1.1.2 ! misho    71390:      * As of PEAR 1.4.3, this will only validate
        !          71391:      *
        !          71392:      * @param array|PEAR_Downloader_Package|PEAR_PackageFile_v1|PEAR_PackageFile_v2
        !          71393:      *              $pkg package identifier (either
        !          71394:      *                   array('package' => blah, 'channel' => blah) or an array with
        !          71395:      *                   index 'info' referencing an object)
        !          71396:      * @param PEAR_Downloader $dl
        !          71397:      * @param array $params full list of packages to install
        !          71398:      * @return true|PEAR_Error
1.1       misho    71399:      */
1.1.1.2 ! misho    71400:     function validatePackage($pkg, &$dl, $params = array())
1.1       misho    71401:     {
1.1.1.2 ! misho    71402:         if (is_array($pkg) && isset($pkg['info'])) {
        !          71403:             $deps = $this->_dependencydb->getDependentPackageDependencies($pkg['info']);
        !          71404:         } else {
        !          71405:             $deps = $this->_dependencydb->getDependentPackageDependencies($pkg);
1.1       misho    71406:         }
                   71407: 
1.1.1.2 ! misho    71408:         $fail = false;
        !          71409:         if ($deps) {
        !          71410:             if (!class_exists('PEAR_Downloader_Package')) {
        !          71411:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Downloader/Package.php';
1.1       misho    71412:             }
                   71413: 
1.1.1.2 ! misho    71414:             $dp = &new PEAR_Downloader_Package($dl);
        !          71415:             if (is_object($pkg)) {
        !          71416:                 $dp->setPackageFile($pkg);
        !          71417:             } else {
        !          71418:                 $dp->setDownloadURL($pkg);
1.1       misho    71419:             }
                   71420: 
1.1.1.2 ! misho    71421:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          71422:             foreach ($deps as $channel => $info) {
        !          71423:                 foreach ($info as $package => $ds) {
        !          71424:                     foreach ($params as $packd) {
        !          71425:                         if (strtolower($packd->getPackage()) == strtolower($package) &&
        !          71426:                               $packd->getChannel() == $channel) {
        !          71427:                             $dl->log(3, 'skipping installed package check of "' .
        !          71428:                                         $this->_registry->parsedPackageNameToString(
        !          71429:                                             array('channel' => $channel, 'package' => $package),
        !          71430:                                             true) .
        !          71431:                                         '", version "' . $packd->getVersion() . '" will be ' .
        !          71432:                                         'downloaded and installed');
        !          71433:                             continue 2; // jump to next package
        !          71434:                         }
        !          71435:                     }
1.1       misho    71436: 
1.1.1.2 ! misho    71437:                     foreach ($ds as $d) {
        !          71438:                         $checker = &new PEAR_Dependency2($this->_config, $this->_options,
        !          71439:                             array('channel' => $channel, 'package' => $package), $this->_state);
        !          71440:                         $dep = $d['dep'];
        !          71441:                         $required = $d['type'] == 'required';
        !          71442:                         $ret = $checker->_validatePackageDownload($dep, $required, array(&$dp));
        !          71443:                         if (is_array($ret)) {
        !          71444:                             $dl->log(0, $ret[0]);
        !          71445:                         } elseif (PEAR::isError($ret)) {
        !          71446:                             $dl->log(0, $ret->getMessage());
        !          71447:                             $fail = true;
        !          71448:                         }
        !          71449:                     }
1.1       misho    71450:                 }
                   71451:             }
1.1.1.2 ! misho    71452:             PEAR::popErrorHandling();
1.1       misho    71453:         }
                   71454: 
1.1.1.2 ! misho    71455:         if ($fail) {
        !          71456:             return $this->raiseError(
        !          71457:                 '%s cannot be installed, conflicts with installed packages');
1.1       misho    71458:         }
                   71459: 
1.1.1.2 ! misho    71460:         return true;
        !          71461:     }
        !          71462: 
        !          71463:     /**
        !          71464:      * validate a package.xml 1.0 dependency
        !          71465:      */
        !          71466:     function validateDependency1($dep, $params = array())
        !          71467:     {
        !          71468:         if (!isset($dep['optional'])) {
        !          71469:             $dep['optional'] = 'no';
1.1       misho    71470:         }
                   71471: 
1.1.1.2 ! misho    71472:         list($newdep, $type) = $this->normalizeDep($dep);
        !          71473:         if (!$newdep) {
        !          71474:             return $this->raiseError("Invalid Dependency");
1.1       misho    71475:         }
                   71476: 
1.1.1.2 ! misho    71477:         if (method_exists($this, "validate{$type}Dependency")) {
        !          71478:             return $this->{"validate{$type}Dependency"}($newdep, $dep['optional'] == 'no',
        !          71479:                 $params, true);
        !          71480:         }
        !          71481:     }
1.1       misho    71482: 
1.1.1.2 ! misho    71483:     /**
        !          71484:      * Convert a 1.0 dep into a 2.0 dep
        !          71485:      */
        !          71486:     function normalizeDep($dep)
        !          71487:     {
        !          71488:         $types = array(
        !          71489:             'pkg' => 'Package',
        !          71490:             'ext' => 'Extension',
        !          71491:             'os' => 'Os',
        !          71492:             'php' => 'Php'
        !          71493:         );
        !          71494: 
        !          71495:         if (!isset($types[$dep['type']])) {
        !          71496:             return array(false, false);
1.1       misho    71497:         }
                   71498: 
1.1.1.2 ! misho    71499:         $type = $types[$dep['type']];
1.1       misho    71500: 
1.1.1.2 ! misho    71501:         $newdep = array();
        !          71502:         switch ($type) {
        !          71503:             case 'Package' :
        !          71504:                 $newdep['channel'] = 'pear.php.net';
        !          71505:             case 'Extension' :
        !          71506:             case 'Os' :
        !          71507:                 $newdep['name'] = $dep['name'];
        !          71508:             break;
1.1       misho    71509:         }
                   71510: 
1.1.1.2 ! misho    71511:         $dep['rel'] = PEAR_Dependency2::signOperator($dep['rel']);
        !          71512:         switch ($dep['rel']) {
        !          71513:             case 'has' :
        !          71514:                 return array($newdep, $type);
        !          71515:             break;
        !          71516:             case 'not' :
        !          71517:                 $newdep['conflicts'] = true;
        !          71518:             break;
        !          71519:             case '>=' :
        !          71520:             case '>' :
        !          71521:                 $newdep['min'] = $dep['version'];
        !          71522:                 if ($dep['rel'] == '>') {
        !          71523:                     $newdep['exclude'] = $dep['version'];
1.1       misho    71524:                 }
1.1.1.2 ! misho    71525:             break;
        !          71526:             case '<=' :
        !          71527:             case '<' :
        !          71528:                 $newdep['max'] = $dep['version'];
        !          71529:                 if ($dep['rel'] == '<') {
        !          71530:                     $newdep['exclude'] = $dep['version'];
        !          71531:                 }
        !          71532:             break;
        !          71533:             case 'ne' :
        !          71534:             case '!=' :
        !          71535:                 $newdep['min'] = '0';
        !          71536:                 $newdep['max'] = '100000';
        !          71537:                 $newdep['exclude'] = $dep['version'];
        !          71538:             break;
        !          71539:             case '==' :
        !          71540:                 $newdep['min'] = $dep['version'];
        !          71541:                 $newdep['max'] = $dep['version'];
        !          71542:             break;
        !          71543:         }
        !          71544:         if ($type == 'Php') {
        !          71545:             if (!isset($newdep['min'])) {
        !          71546:                 $newdep['min'] = '4.4.0';
1.1       misho    71547:             }
                   71548: 
1.1.1.2 ! misho    71549:             if (!isset($newdep['max'])) {
        !          71550:                 $newdep['max'] = '6.0.0';
1.1       misho    71551:             }
                   71552:         }
1.1.1.2 ! misho    71553:         return array($newdep, $type);
        !          71554:     }
1.1       misho    71555: 
1.1.1.2 ! misho    71556:     /**
        !          71557:      * Converts text comparing operators to them sign equivalents
        !          71558:      *
        !          71559:      * Example: 'ge' to '>='
        !          71560:      *
        !          71561:      * @access public
        !          71562:      * @param  string Operator
        !          71563:      * @return string Sign equivalent
        !          71564:      */
        !          71565:     function signOperator($operator)
        !          71566:     {
        !          71567:         switch($operator) {
        !          71568:             case 'lt': return '<';
        !          71569:             case 'le': return '<=';
        !          71570:             case 'gt': return '>';
        !          71571:             case 'ge': return '>=';
        !          71572:             case 'eq': return '==';
        !          71573:             case 'ne': return '!=';
        !          71574:             default:
        !          71575:                 return $operator;
1.1       misho    71576:         }
                   71577:     }
                   71578: 
1.1.1.2 ! misho    71579:     function raiseError($msg)
1.1       misho    71580:     {
1.1.1.2 ! misho    71581:         if (isset($this->_options['ignore-errors'])) {
        !          71582:             return $this->warning($msg);
1.1       misho    71583:         }
                   71584: 
1.1.1.2 ! misho    71585:         return PEAR::raiseError(sprintf($msg, $this->_registry->parsedPackageNameToString(
        !          71586:             $this->_currentPackage, true)));
        !          71587:     }
1.1       misho    71588: 
1.1.1.2 ! misho    71589:     function warning($msg)
        !          71590:     {
        !          71591:         return array(sprintf($msg, $this->_registry->parsedPackageNameToString(
        !          71592:             $this->_currentPackage, true)));
        !          71593:     }
        !          71594: }<?php
        !          71595: /**
        !          71596:  * PEAR_DependencyDB, advanced installed packages dependency database
        !          71597:  *
        !          71598:  * PHP versions 4 and 5
        !          71599:  *
        !          71600:  * @category   pear
        !          71601:  * @package    PEAR
        !          71602:  * @author     Tomas V. V. Cox <cox@idecnet.com>
        !          71603:  * @author     Greg Beaver <cellog@php.net>
        !          71604:  * @copyright  1997-2009 The Authors
        !          71605:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          71606:  * @version    CVS: $Id: DependencyDB.php 313023 2011-07-06 19:17:11Z dufuz $
        !          71607:  * @link       http://pear.php.net/package/PEAR
        !          71608:  * @since      File available since Release 1.4.0a1
        !          71609:  */
1.1       misho    71610: 
1.1.1.2 ! misho    71611: /**
        !          71612:  * Needed for error handling
        !          71613:  */
        !          71614: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
        !          71615: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Config.php';
1.1       misho    71616: 
1.1.1.2 ! misho    71617: $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'] = array();
        !          71618: /**
        !          71619:  * Track dependency relationships between installed packages
        !          71620:  * @category   pear
        !          71621:  * @package    PEAR
        !          71622:  * @author     Greg Beaver <cellog@php.net>
        !          71623:  * @author     Tomas V.V.Cox <cox@idec.net.com>
        !          71624:  * @copyright  1997-2009 The Authors
        !          71625:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          71626:  * @version    Release: 1.9.4
        !          71627:  * @link       http://pear.php.net/package/PEAR
        !          71628:  * @since      Class available since Release 1.4.0a1
        !          71629:  */
        !          71630: class PEAR_DependencyDB
        !          71631: {
        !          71632:     // {{{ properties
1.1       misho    71633: 
                   71634:     /**
1.1.1.2 ! misho    71635:      * This is initialized by {@link setConfig()}
        !          71636:      * @var PEAR_Config
        !          71637:      * @access private
1.1       misho    71638:      */
1.1.1.2 ! misho    71639:     var $_config;
        !          71640:     /**
        !          71641:      * This is initialized by {@link setConfig()}
        !          71642:      * @var PEAR_Registry
        !          71643:      * @access private
        !          71644:      */
        !          71645:     var $_registry;
        !          71646:     /**
        !          71647:      * Filename of the dependency DB (usually .depdb)
        !          71648:      * @var string
        !          71649:      * @access private
        !          71650:      */
        !          71651:     var $_depdb = false;
        !          71652:     /**
        !          71653:      * File name of the lockfile (usually .depdblock)
        !          71654:      * @var string
        !          71655:      * @access private
        !          71656:      */
        !          71657:     var $_lockfile = false;
        !          71658:     /**
        !          71659:      * Open file resource for locking the lockfile
        !          71660:      * @var resource|false
        !          71661:      * @access private
        !          71662:      */
        !          71663:     var $_lockFp = false;
        !          71664:     /**
        !          71665:      * API version of this class, used to validate a file on-disk
        !          71666:      * @var string
        !          71667:      * @access private
        !          71668:      */
        !          71669:     var $_version = '1.0';
        !          71670:     /**
        !          71671:      * Cached dependency database file
        !          71672:      * @var array|null
        !          71673:      * @access private
        !          71674:      */
        !          71675:     var $_cache;
1.1       misho    71676: 
1.1.1.2 ! misho    71677:     // }}}
        !          71678:     // {{{ & singleton()
1.1       misho    71679: 
1.1.1.2 ! misho    71680:     /**
        !          71681:      * Get a raw dependency database.  Calls setConfig() and assertDepsDB()
        !          71682:      * @param PEAR_Config
        !          71683:      * @param string|false full path to the dependency database, or false to use default
        !          71684:      * @return PEAR_DependencyDB|PEAR_Error
        !          71685:      * @static
        !          71686:      */
        !          71687:     function &singleton(&$config, $depdb = false)
        !          71688:     {
        !          71689:         $phpdir = $config->get('php_dir', null, 'pear.php.net');
        !          71690:         if (!isset($GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir])) {
        !          71691:             $a = new PEAR_DependencyDB;
        !          71692:             $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir] = &$a;
        !          71693:             $a->setConfig($config, $depdb);
        !          71694:             $e = $a->assertDepsDB();
        !          71695:             if (PEAR::isError($e)) {
        !          71696:                 return $e;
1.1       misho    71697:             }
                   71698:         }
                   71699: 
1.1.1.2 ! misho    71700:         return $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir];
1.1       misho    71701:     }
                   71702: 
                   71703:     /**
1.1.1.2 ! misho    71704:      * Set up the registry/location of dependency DB
        !          71705:      * @param PEAR_Config|false
        !          71706:      * @param string|false full path to the dependency database, or false to use default
1.1       misho    71707:      */
1.1.1.2 ! misho    71708:     function setConfig(&$config, $depdb = false)
1.1       misho    71709:     {
1.1.1.2 ! misho    71710:         if (!$config) {
        !          71711:             $this->_config = &PEAR_Config::singleton();
        !          71712:         } else {
        !          71713:             $this->_config = &$config;
1.1       misho    71714:         }
1.1.1.2 ! misho    71715: 
        !          71716:         $this->_registry = &$this->_config->getRegistry();
        !          71717:         if (!$depdb) {
        !          71718:             $this->_depdb = $this->_config->get('php_dir', null, 'pear.php.net') .
        !          71719:                 DIRECTORY_SEPARATOR . '.depdb';
        !          71720:         } else {
        !          71721:             $this->_depdb = $depdb;
        !          71722:         }
        !          71723: 
        !          71724:         $this->_lockfile = dirname($this->_depdb) . DIRECTORY_SEPARATOR . '.depdblock';
1.1       misho    71725:     }
1.1.1.2 ! misho    71726:     // }}}
1.1       misho    71727: 
1.1.1.2 ! misho    71728:     function hasWriteAccess()
1.1       misho    71729:     {
1.1.1.2 ! misho    71730:         if (!file_exists($this->_depdb)) {
        !          71731:             $dir = $this->_depdb;
        !          71732:             while ($dir && $dir != '.') {
        !          71733:                 $dir = dirname($dir); // cd ..
        !          71734:                 if ($dir != '.' && file_exists($dir)) {
        !          71735:                     if (is_writeable($dir)) {
        !          71736:                         return true;
        !          71737:                     }
        !          71738: 
        !          71739:                     return false;
        !          71740:                 }
        !          71741:             }
        !          71742: 
        !          71743:             return false;
1.1       misho    71744:         }
                   71745: 
1.1.1.2 ! misho    71746:         return is_writeable($this->_depdb);
1.1       misho    71747:     }
                   71748: 
1.1.1.2 ! misho    71749:     // {{{ assertDepsDB()
        !          71750: 
1.1       misho    71751:     /**
1.1.1.2 ! misho    71752:      * Create the dependency database, if it doesn't exist.  Error if the database is
        !          71753:      * newer than the code reading it.
        !          71754:      * @return void|PEAR_Error
1.1       misho    71755:      */
1.1.1.2 ! misho    71756:     function assertDepsDB()
1.1       misho    71757:     {
1.1.1.2 ! misho    71758:         if (!is_file($this->_depdb)) {
        !          71759:             $this->rebuildDB();
        !          71760:             return;
1.1       misho    71761:         }
                   71762: 
1.1.1.2 ! misho    71763:         $depdb = $this->_getDepDB();
        !          71764:         // Datatype format has been changed, rebuild the Deps DB
        !          71765:         if ($depdb['_version'] < $this->_version) {
        !          71766:             $this->rebuildDB();
        !          71767:         }
        !          71768: 
        !          71769:         if ($depdb['_version']{0} > $this->_version{0}) {
        !          71770:             return PEAR::raiseError('Dependency database is version ' .
        !          71771:                 $depdb['_version'] . ', and we are version ' .
        !          71772:                 $this->_version . ', cannot continue');
        !          71773:         }
1.1       misho    71774:     }
                   71775: 
                   71776:     /**
1.1.1.2 ! misho    71777:      * Get a list of installed packages that depend on this package
        !          71778:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
        !          71779:      * @return array|false
1.1       misho    71780:      */
1.1.1.2 ! misho    71781:     function getDependentPackages(&$pkg)
1.1       misho    71782:     {
1.1.1.2 ! misho    71783:         $data = $this->_getDepDB();
        !          71784:         if (is_object($pkg)) {
        !          71785:             $channel = strtolower($pkg->getChannel());
        !          71786:             $package = strtolower($pkg->getPackage());
        !          71787:         } else {
        !          71788:             $channel = strtolower($pkg['channel']);
        !          71789:             $package = strtolower($pkg['package']);
        !          71790:         }
        !          71791: 
        !          71792:         if (isset($data['packages'][$channel][$package])) {
        !          71793:             return $data['packages'][$channel][$package];
1.1       misho    71794:         }
                   71795: 
                   71796:         return false;
                   71797:     }
                   71798: 
                   71799:     /**
1.1.1.2 ! misho    71800:      * Get a list of the actual dependencies of installed packages that depend on
        !          71801:      * a package.
        !          71802:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
        !          71803:      * @return array|false
1.1       misho    71804:      */
1.1.1.2 ! misho    71805:     function getDependentPackageDependencies(&$pkg)
1.1       misho    71806:     {
1.1.1.2 ! misho    71807:         $data = $this->_getDepDB();
        !          71808:         if (is_object($pkg)) {
        !          71809:             $channel = strtolower($pkg->getChannel());
        !          71810:             $package = strtolower($pkg->getPackage());
        !          71811:         } else {
        !          71812:             $channel = strtolower($pkg['channel']);
        !          71813:             $package = strtolower($pkg['package']);
1.1       misho    71814:         }
                   71815: 
1.1.1.2 ! misho    71816:         $depend = $this->getDependentPackages($pkg);
        !          71817:         if (!$depend) {
        !          71818:             return false;
        !          71819:         }
1.1       misho    71820: 
1.1.1.2 ! misho    71821:         $dependencies = array();
        !          71822:         foreach ($depend as $info) {
        !          71823:             $temp = $this->getDependencies($info);
        !          71824:             foreach ($temp as $dep) {
        !          71825:                 if (
        !          71826:                     isset($dep['dep'], $dep['dep']['channel'], $dep['dep']['name']) &&
        !          71827:                     strtolower($dep['dep']['channel']) == $channel &&
        !          71828:                     strtolower($dep['dep']['name']) == $package
        !          71829:                 ) {
        !          71830:                     if (!isset($dependencies[$info['channel']])) {
        !          71831:                         $dependencies[$info['channel']] = array();
        !          71832:                     }
        !          71833: 
        !          71834:                     if (!isset($dependencies[$info['channel']][$info['package']])) {
        !          71835:                         $dependencies[$info['channel']][$info['package']] = array();
        !          71836:                     }
        !          71837:                     $dependencies[$info['channel']][$info['package']][] = $dep;
        !          71838:                 }
1.1       misho    71839:             }
                   71840:         }
                   71841: 
1.1.1.2 ! misho    71842:         return $dependencies;
1.1       misho    71843:     }
                   71844: 
                   71845:     /**
1.1.1.2 ! misho    71846:      * Get a list of dependencies of this installed package
        !          71847:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
        !          71848:      * @return array|false
1.1       misho    71849:      */
1.1.1.2 ! misho    71850:     function getDependencies(&$pkg)
1.1       misho    71851:     {
1.1.1.2 ! misho    71852:         if (is_object($pkg)) {
        !          71853:             $channel = strtolower($pkg->getChannel());
        !          71854:             $package = strtolower($pkg->getPackage());
        !          71855:         } else {
        !          71856:             $channel = strtolower($pkg['channel']);
        !          71857:             $package = strtolower($pkg['package']);
        !          71858:         }
1.1       misho    71859: 
1.1.1.2 ! misho    71860:         $data = $this->_getDepDB();
        !          71861:         if (isset($data['dependencies'][$channel][$package])) {
        !          71862:             return $data['dependencies'][$channel][$package];
1.1       misho    71863:         }
                   71864: 
1.1.1.2 ! misho    71865:         return false;
1.1       misho    71866:     }
                   71867: 
                   71868:     /**
1.1.1.2 ! misho    71869:      * Determine whether $parent depends on $child, near or deep
        !          71870:      * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
        !          71871:      * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
1.1       misho    71872:      */
1.1.1.2 ! misho    71873:     function dependsOn($parent, $child)
1.1       misho    71874:     {
1.1.1.2 ! misho    71875:         $c = array();
        !          71876:         $this->_getDepDB();
        !          71877:         return $this->_dependsOn($parent, $child, $c);
        !          71878:     }
1.1       misho    71879: 
1.1.1.2 ! misho    71880:     function _dependsOn($parent, $child, &$checked)
        !          71881:     {
        !          71882:         if (is_object($parent)) {
        !          71883:             $channel = strtolower($parent->getChannel());
        !          71884:             $package = strtolower($parent->getPackage());
        !          71885:         } else {
        !          71886:             $channel = strtolower($parent['channel']);
        !          71887:             $package = strtolower($parent['package']);
        !          71888:         }
        !          71889: 
        !          71890:         if (is_object($child)) {
        !          71891:             $depchannel = strtolower($child->getChannel());
        !          71892:             $deppackage = strtolower($child->getPackage());
        !          71893:         } else {
        !          71894:             $depchannel = strtolower($child['channel']);
        !          71895:             $deppackage = strtolower($child['package']);
        !          71896:         }
1.1       misho    71897: 
1.1.1.2 ! misho    71898:         if (isset($checked[$channel][$package][$depchannel][$deppackage])) {
        !          71899:             return false; // avoid endless recursion
1.1       misho    71900:         }
                   71901: 
1.1.1.2 ! misho    71902:         $checked[$channel][$package][$depchannel][$deppackage] = true;
        !          71903:         if (!isset($this->_cache['dependencies'][$channel][$package])) {
        !          71904:             return false;
1.1       misho    71905:         }
                   71906: 
1.1.1.2 ! misho    71907:         foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
        !          71908:             if (isset($info['dep']['uri'])) {
        !          71909:                 if (is_object($child)) {
        !          71910:                     if ($info['dep']['uri'] == $child->getURI()) {
        !          71911:                         return true;
        !          71912:                     }
        !          71913:                 } elseif (isset($child['uri'])) {
        !          71914:                     if ($info['dep']['uri'] == $child['uri']) {
        !          71915:                         return true;
        !          71916:                     }
        !          71917:                 }
        !          71918:                 return false;
        !          71919:             }
        !          71920: 
        !          71921:             if (strtolower($info['dep']['channel']) == $depchannel &&
        !          71922:                   strtolower($info['dep']['name']) == $deppackage) {
1.1       misho    71923:                 return true;
                   71924:             }
                   71925:         }
                   71926: 
1.1.1.2 ! misho    71927:         foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
        !          71928:             if (isset($info['dep']['uri'])) {
        !          71929:                 if ($this->_dependsOn(array(
        !          71930:                         'uri' => $info['dep']['uri'],
        !          71931:                         'package' => $info['dep']['name']), $child, $checked)) {
        !          71932:                     return true;
        !          71933:                 }
        !          71934:             } else {
        !          71935:                 if ($this->_dependsOn(array(
        !          71936:                         'channel' => $info['dep']['channel'],
        !          71937:                         'package' => $info['dep']['name']), $child, $checked)) {
        !          71938:                     return true;
        !          71939:                 }
        !          71940:             }
1.1       misho    71941:         }
                   71942: 
                   71943:         return false;
                   71944:     }
                   71945: 
                   71946:     /**
1.1.1.2 ! misho    71947:      * Register dependencies of a package that is being installed or upgraded
        !          71948:      * @param PEAR_PackageFile_v2|PEAR_PackageFile_v2
1.1       misho    71949:      */
1.1.1.2 ! misho    71950:     function installPackage(&$package)
1.1       misho    71951:     {
1.1.1.2 ! misho    71952:         $data = $this->_getDepDB();
        !          71953:         unset($this->_cache);
        !          71954:         $this->_setPackageDeps($data, $package);
        !          71955:         $this->_writeDepDB($data);
1.1       misho    71956:     }
                   71957: 
                   71958:     /**
1.1.1.2 ! misho    71959:      * Remove dependencies of a package that is being uninstalled, or upgraded.
1.1       misho    71960:      *
1.1.1.2 ! misho    71961:      * Upgraded packages first uninstall, then install
        !          71962:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array If an array, then it must have
        !          71963:      *        indices 'channel' and 'package'
1.1       misho    71964:      */
1.1.1.2 ! misho    71965:     function uninstallPackage(&$pkg)
1.1       misho    71966:     {
1.1.1.2 ! misho    71967:         $data = $this->_getDepDB();
        !          71968:         unset($this->_cache);
        !          71969:         if (is_object($pkg)) {
        !          71970:             $channel = strtolower($pkg->getChannel());
        !          71971:             $package = strtolower($pkg->getPackage());
        !          71972:         } else {
        !          71973:             $channel = strtolower($pkg['channel']);
        !          71974:             $package = strtolower($pkg['package']);
        !          71975:         }
1.1       misho    71976: 
1.1.1.2 ! misho    71977:         if (!isset($data['dependencies'][$channel][$package])) {
        !          71978:             return true;
        !          71979:         }
        !          71980: 
        !          71981:         foreach ($data['dependencies'][$channel][$package] as $dep) {
        !          71982:             $found      = false;
        !          71983:             $depchannel = isset($dep['dep']['uri']) ? '__uri' : strtolower($dep['dep']['channel']);
        !          71984:             $depname    = strtolower($dep['dep']['name']);
        !          71985:             if (isset($data['packages'][$depchannel][$depname])) {
        !          71986:                 foreach ($data['packages'][$depchannel][$depname] as $i => $info) {
        !          71987:                     if ($info['channel'] == $channel && $info['package'] == $package) {
        !          71988:                         $found = true;
        !          71989:                         break;
1.1       misho    71990:                     }
                   71991:                 }
                   71992:             }
                   71993: 
1.1.1.2 ! misho    71994:             if ($found) {
        !          71995:                 unset($data['packages'][$depchannel][$depname][$i]);
        !          71996:                 if (!count($data['packages'][$depchannel][$depname])) {
        !          71997:                     unset($data['packages'][$depchannel][$depname]);
        !          71998:                     if (!count($data['packages'][$depchannel])) {
        !          71999:                         unset($data['packages'][$depchannel]);
        !          72000:                     }
        !          72001:                 } else {
        !          72002:                     $data['packages'][$depchannel][$depname] =
        !          72003:                         array_values($data['packages'][$depchannel][$depname]);
1.1       misho    72004:                 }
                   72005:             }
                   72006:         }
                   72007: 
1.1.1.2 ! misho    72008:         unset($data['dependencies'][$channel][$package]);
        !          72009:         if (!count($data['dependencies'][$channel])) {
        !          72010:             unset($data['dependencies'][$channel]);
        !          72011:         }
        !          72012: 
        !          72013:         if (!count($data['dependencies'])) {
        !          72014:             unset($data['dependencies']);
        !          72015:         }
        !          72016: 
        !          72017:         if (!count($data['packages'])) {
        !          72018:             unset($data['packages']);
        !          72019:         }
        !          72020: 
        !          72021:         $this->_writeDepDB($data);
1.1       misho    72022:     }
                   72023: 
                   72024:     /**
1.1.1.2 ! misho    72025:      * Rebuild the dependency DB by reading registry entries.
        !          72026:      * @return true|PEAR_Error
1.1       misho    72027:      */
1.1.1.2 ! misho    72028:     function rebuildDB()
1.1       misho    72029:     {
1.1.1.2 ! misho    72030:         $depdb = array('_version' => $this->_version);
        !          72031:         if (!$this->hasWriteAccess()) {
        !          72032:             // allow startup for read-only with older Registry
        !          72033:             return $depdb;
        !          72034:         }
        !          72035: 
        !          72036:         $packages = $this->_registry->listAllPackages();
        !          72037:         if (PEAR::isError($packages)) {
        !          72038:             return $packages;
        !          72039:         }
        !          72040: 
        !          72041:         foreach ($packages as $channel => $ps) {
        !          72042:             foreach ($ps as $package) {
        !          72043:                 $package = $this->_registry->getPackage($package, $channel);
        !          72044:                 if (PEAR::isError($package)) {
        !          72045:                     return $package;
        !          72046:                 }
        !          72047:                 $this->_setPackageDeps($depdb, $package);
1.1       misho    72048:             }
                   72049:         }
                   72050: 
1.1.1.2 ! misho    72051:         $error = $this->_writeDepDB($depdb);
        !          72052:         if (PEAR::isError($error)) {
        !          72053:             return $error;
        !          72054:         }
        !          72055: 
        !          72056:         $this->_cache = $depdb;
        !          72057:         return true;
1.1       misho    72058:     }
                   72059: 
                   72060:     /**
1.1.1.2 ! misho    72061:      * Register usage of the dependency DB to prevent race conditions
        !          72062:      * @param int one of the LOCK_* constants
        !          72063:      * @return true|PEAR_Error
        !          72064:      * @access private
1.1       misho    72065:      */
1.1.1.2 ! misho    72066:     function _lock($mode = LOCK_EX)
1.1       misho    72067:     {
1.1.1.2 ! misho    72068:         if (stristr(php_uname(), 'Windows 9')) {
        !          72069:             return true;
        !          72070:         }
        !          72071: 
        !          72072:         if ($mode != LOCK_UN && is_resource($this->_lockFp)) {
        !          72073:             // XXX does not check type of lock (LOCK_SH/LOCK_EX)
        !          72074:             return true;
        !          72075:         }
        !          72076: 
        !          72077:         $open_mode = 'w';
        !          72078:         // XXX People reported problems with LOCK_SH and 'w'
        !          72079:         if ($mode === LOCK_SH) {
        !          72080:             if (!file_exists($this->_lockfile)) {
        !          72081:                 touch($this->_lockfile);
        !          72082:             } elseif (!is_file($this->_lockfile)) {
        !          72083:                 return PEAR::raiseError('could not create Dependency lock file, ' .
        !          72084:                     'it exists and is not a regular file');
        !          72085:             }
        !          72086:             $open_mode = 'r';
        !          72087:         }
        !          72088: 
        !          72089:         if (!is_resource($this->_lockFp)) {
        !          72090:             $this->_lockFp = @fopen($this->_lockfile, $open_mode);
        !          72091:         }
        !          72092: 
        !          72093:         if (!is_resource($this->_lockFp)) {
        !          72094:             return PEAR::raiseError("could not create Dependency lock file" .
        !          72095:                                      (isset($php_errormsg) ? ": " . $php_errormsg : ""));
        !          72096:         }
        !          72097: 
        !          72098:         if (!(int)flock($this->_lockFp, $mode)) {
        !          72099:             switch ($mode) {
        !          72100:                 case LOCK_SH: $str = 'shared';    break;
        !          72101:                 case LOCK_EX: $str = 'exclusive'; break;
        !          72102:                 case LOCK_UN: $str = 'unlock';    break;
        !          72103:                 default:      $str = 'unknown';   break;
        !          72104:             }
1.1       misho    72105: 
1.1.1.2 ! misho    72106:             return PEAR::raiseError("could not acquire $str lock ($this->_lockfile)");
        !          72107:         }
1.1       misho    72108: 
1.1.1.2 ! misho    72109:         return true;
1.1       misho    72110:     }
                   72111: 
                   72112:     /**
1.1.1.2 ! misho    72113:      * Release usage of dependency DB
        !          72114:      * @return true|PEAR_Error
        !          72115:      * @access private
1.1       misho    72116:      */
1.1.1.2 ! misho    72117:     function _unlock()
1.1       misho    72118:     {
1.1.1.2 ! misho    72119:         $ret = $this->_lock(LOCK_UN);
        !          72120:         if (is_resource($this->_lockFp)) {
        !          72121:             fclose($this->_lockFp);
1.1       misho    72122:         }
1.1.1.2 ! misho    72123:         $this->_lockFp = null;
        !          72124:         return $ret;
1.1       misho    72125:     }
                   72126: 
                   72127:     /**
1.1.1.2 ! misho    72128:      * Load the dependency database from disk, or return the cache
        !          72129:      * @return array|PEAR_Error
1.1       misho    72130:      */
1.1.1.2 ! misho    72131:     function _getDepDB()
1.1       misho    72132:     {
1.1.1.2 ! misho    72133:         if (!$this->hasWriteAccess()) {
        !          72134:             return array('_version' => $this->_version);
1.1       misho    72135:         }
                   72136: 
1.1.1.2 ! misho    72137:         if (isset($this->_cache)) {
        !          72138:             return $this->_cache;
1.1       misho    72139:         }
                   72140: 
1.1.1.2 ! misho    72141:         if (!$fp = fopen($this->_depdb, 'r')) {
        !          72142:             $err = PEAR::raiseError("Could not open dependencies file `".$this->_depdb."'");
        !          72143:             return $err;
1.1       misho    72144:         }
                   72145: 
1.1.1.2 ! misho    72146:         $rt = get_magic_quotes_runtime();
        !          72147:         set_magic_quotes_runtime(0);
        !          72148:         clearstatcache();
        !          72149:         fclose($fp);
        !          72150:         $data = unserialize(file_get_contents($this->_depdb));
        !          72151:         set_magic_quotes_runtime($rt);
        !          72152:         $this->_cache = $data;
        !          72153:         return $data;
1.1       misho    72154:     }
                   72155: 
                   72156:     /**
1.1.1.2 ! misho    72157:      * Write out the dependency database to disk
        !          72158:      * @param array the database
        !          72159:      * @return true|PEAR_Error
        !          72160:      * @access private
1.1       misho    72161:      */
1.1.1.2 ! misho    72162:     function _writeDepDB(&$deps)
1.1       misho    72163:     {
1.1.1.2 ! misho    72164:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
        !          72165:             return $e;
1.1       misho    72166:         }
                   72167: 
1.1.1.2 ! misho    72168:         if (!$fp = fopen($this->_depdb, 'wb')) {
        !          72169:             $this->_unlock();
        !          72170:             return PEAR::raiseError("Could not open dependencies file `".$this->_depdb."' for writing");
        !          72171:         }
        !          72172: 
        !          72173:         $rt = get_magic_quotes_runtime();
        !          72174:         set_magic_quotes_runtime(0);
        !          72175:         fwrite($fp, serialize($deps));
        !          72176:         set_magic_quotes_runtime($rt);
        !          72177:         fclose($fp);
        !          72178:         $this->_unlock();
        !          72179:         $this->_cache = $deps;
        !          72180:         return true;
1.1       misho    72181:     }
                   72182: 
                   72183:     /**
1.1.1.2 ! misho    72184:      * Register all dependencies from a package in the dependencies database, in essence
        !          72185:      * "installing" the package's dependency information
        !          72186:      * @param array the database
        !          72187:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
        !          72188:      * @access private
1.1       misho    72189:      */
1.1.1.2 ! misho    72190:     function _setPackageDeps(&$data, &$pkg)
1.1       misho    72191:     {
1.1.1.2 ! misho    72192:         $pkg->setConfig($this->_config);
        !          72193:         if ($pkg->getPackagexmlVersion() == '1.0') {
        !          72194:             $gen = &$pkg->getDefaultGenerator();
        !          72195:             $deps = $gen->dependenciesToV2();
        !          72196:         } else {
        !          72197:             $deps = $pkg->getDeps(true);
1.1       misho    72198:         }
                   72199: 
1.1.1.2 ! misho    72200:         if (!$deps) {
        !          72201:             return;
        !          72202:         }
1.1       misho    72203: 
1.1.1.2 ! misho    72204:         if (!is_array($data)) {
        !          72205:             $data = array();
        !          72206:         }
        !          72207: 
        !          72208:         if (!isset($data['dependencies'])) {
        !          72209:             $data['dependencies'] = array();
        !          72210:         }
        !          72211: 
        !          72212:         $channel = strtolower($pkg->getChannel());
        !          72213:         $package = strtolower($pkg->getPackage());
        !          72214: 
        !          72215:         if (!isset($data['dependencies'][$channel])) {
        !          72216:             $data['dependencies'][$channel] = array();
        !          72217:         }
        !          72218: 
        !          72219:         $data['dependencies'][$channel][$package] = array();
        !          72220:         if (isset($deps['required']['package'])) {
        !          72221:             if (!isset($deps['required']['package'][0])) {
        !          72222:                 $deps['required']['package'] = array($deps['required']['package']);
        !          72223:             }
        !          72224: 
        !          72225:             foreach ($deps['required']['package'] as $dep) {
        !          72226:                 $this->_registerDep($data, $pkg, $dep, 'required');
        !          72227:             }
        !          72228:         }
        !          72229: 
        !          72230:         if (isset($deps['optional']['package'])) {
        !          72231:             if (!isset($deps['optional']['package'][0])) {
        !          72232:                 $deps['optional']['package'] = array($deps['optional']['package']);
        !          72233:             }
        !          72234: 
        !          72235:             foreach ($deps['optional']['package'] as $dep) {
        !          72236:                 $this->_registerDep($data, $pkg, $dep, 'optional');
        !          72237:             }
        !          72238:         }
        !          72239: 
        !          72240:         if (isset($deps['required']['subpackage'])) {
        !          72241:             if (!isset($deps['required']['subpackage'][0])) {
        !          72242:                 $deps['required']['subpackage'] = array($deps['required']['subpackage']);
        !          72243:             }
        !          72244: 
        !          72245:             foreach ($deps['required']['subpackage'] as $dep) {
        !          72246:                 $this->_registerDep($data, $pkg, $dep, 'required');
        !          72247:             }
        !          72248:         }
        !          72249: 
        !          72250:         if (isset($deps['optional']['subpackage'])) {
        !          72251:             if (!isset($deps['optional']['subpackage'][0])) {
        !          72252:                 $deps['optional']['subpackage'] = array($deps['optional']['subpackage']);
        !          72253:             }
        !          72254: 
        !          72255:             foreach ($deps['optional']['subpackage'] as $dep) {
        !          72256:                 $this->_registerDep($data, $pkg, $dep, 'optional');
        !          72257:             }
        !          72258:         }
        !          72259: 
        !          72260:         if (isset($deps['group'])) {
        !          72261:             if (!isset($deps['group'][0])) {
        !          72262:                 $deps['group'] = array($deps['group']);
        !          72263:             }
        !          72264: 
        !          72265:             foreach ($deps['group'] as $group) {
        !          72266:                 if (isset($group['package'])) {
        !          72267:                     if (!isset($group['package'][0])) {
        !          72268:                         $group['package'] = array($group['package']);
        !          72269:                     }
        !          72270: 
        !          72271:                     foreach ($group['package'] as $dep) {
        !          72272:                         $this->_registerDep($data, $pkg, $dep, 'optional',
        !          72273:                             $group['attribs']['name']);
        !          72274:                     }
        !          72275:                 }
        !          72276: 
        !          72277:                 if (isset($group['subpackage'])) {
        !          72278:                     if (!isset($group['subpackage'][0])) {
        !          72279:                         $group['subpackage'] = array($group['subpackage']);
        !          72280:                     }
        !          72281: 
        !          72282:                     foreach ($group['subpackage'] as $dep) {
        !          72283:                         $this->_registerDep($data, $pkg, $dep, 'optional',
        !          72284:                             $group['attribs']['name']);
        !          72285:                     }
1.1       misho    72286:                 }
                   72287:             }
                   72288:         }
1.1.1.2 ! misho    72289: 
        !          72290:         if ($data['dependencies'][$channel][$package] == array()) {
        !          72291:             unset($data['dependencies'][$channel][$package]);
        !          72292:             if (!count($data['dependencies'][$channel])) {
        !          72293:                 unset($data['dependencies'][$channel]);
        !          72294:             }
        !          72295:         }
1.1       misho    72296:     }
                   72297: 
                   72298:     /**
1.1.1.2 ! misho    72299:      * @param array the database
        !          72300:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
        !          72301:      * @param array the specific dependency
        !          72302:      * @param required|optional whether this is a required or an optional dep
        !          72303:      * @param string|false dependency group this dependency is from, or false for ordinary dep
1.1       misho    72304:      */
1.1.1.2 ! misho    72305:     function _registerDep(&$data, &$pkg, $dep, $type, $group = false)
1.1       misho    72306:     {
1.1.1.2 ! misho    72307:         $info = array(
        !          72308:             'dep'   => $dep,
        !          72309:             'type'  => $type,
        !          72310:             'group' => $group
        !          72311:         );
        !          72312: 
        !          72313:         $dep  = array_map('strtolower', $dep);
        !          72314:         $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
        !          72315:         if (!isset($data['dependencies'])) {
        !          72316:             $data['dependencies'] = array();
1.1       misho    72317:         }
1.1.1.2 ! misho    72318: 
        !          72319:         $channel = strtolower($pkg->getChannel());
        !          72320:         $package = strtolower($pkg->getPackage());
        !          72321: 
        !          72322:         if (!isset($data['dependencies'][$channel])) {
        !          72323:             $data['dependencies'][$channel] = array();
        !          72324:         }
        !          72325: 
        !          72326:         if (!isset($data['dependencies'][$channel][$package])) {
        !          72327:             $data['dependencies'][$channel][$package] = array();
        !          72328:         }
        !          72329: 
        !          72330:         $data['dependencies'][$channel][$package][] = $info;
        !          72331:         if (isset($data['packages'][$depchannel][$dep['name']])) {
        !          72332:             $found = false;
        !          72333:             foreach ($data['packages'][$depchannel][$dep['name']] as $i => $p) {
        !          72334:                 if ($p['channel'] == $channel && $p['package'] == $package) {
        !          72335:                     $found = true;
        !          72336:                     break;
1.1       misho    72337:                 }
                   72338:             }
1.1.1.2 ! misho    72339:         } else {
        !          72340:             if (!isset($data['packages'])) {
        !          72341:                 $data['packages'] = array();
        !          72342:             }
        !          72343: 
        !          72344:             if (!isset($data['packages'][$depchannel])) {
        !          72345:                 $data['packages'][$depchannel] = array();
        !          72346:             }
        !          72347: 
        !          72348:             if (!isset($data['packages'][$depchannel][$dep['name']])) {
        !          72349:                 $data['packages'][$depchannel][$dep['name']] = array();
        !          72350:             }
        !          72351: 
        !          72352:             $found = false;
        !          72353:         }
        !          72354: 
        !          72355:         if (!$found) {
        !          72356:             $data['packages'][$depchannel][$dep['name']][] = array(
        !          72357:                 'channel' => $channel,
        !          72358:                 'package' => $package
        !          72359:             );
1.1       misho    72360:         }
                   72361:     }
1.1.1.2 ! misho    72362: }<?php
1.1       misho    72363: /**
1.1.1.2 ! misho    72364:  * PEAR_Downloader, the PEAR Installer's download utility class
1.1       misho    72365:  *
                   72366:  * PHP versions 4 and 5
                   72367:  *
                   72368:  * @category   pear
                   72369:  * @package    PEAR
                   72370:  * @author     Greg Beaver <cellog@php.net>
1.1.1.2 ! misho    72371:  * @author     Stig Bakken <ssb@php.net>
        !          72372:  * @author     Tomas V. V. Cox <cox@idecnet.com>
        !          72373:  * @author     Martin Jansen <mj@php.net>
1.1       misho    72374:  * @copyright  1997-2009 The Authors
                   72375:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    72376:  * @version    CVS: $Id: Downloader.php 313024 2011-07-06 19:51:24Z dufuz $
1.1       misho    72377:  * @link       http://pear.php.net/package/PEAR
1.1.1.2 ! misho    72378:  * @since      File available since Release 1.3.0
1.1       misho    72379:  */
                   72380: 
                   72381: /**
1.1.1.2 ! misho    72382:  * Needed for constants, extending
1.1       misho    72383:  */
1.1.1.2 ! misho    72384: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
        !          72385: 
        !          72386: define('PEAR_INSTALLER_OK',       1);
        !          72387: define('PEAR_INSTALLER_FAILED',   0);
        !          72388: define('PEAR_INSTALLER_SKIPPED', -1);
        !          72389: define('PEAR_INSTALLER_ERROR_NO_PREF_STATE', 2);
1.1       misho    72390: 
                   72391: /**
1.1.1.2 ! misho    72392:  * Administration class used to download anything from the internet (PEAR Packages,
        !          72393:  * static URLs, xml files)
1.1       misho    72394:  *
                   72395:  * @category   pear
                   72396:  * @package    PEAR
                   72397:  * @author     Greg Beaver <cellog@php.net>
1.1.1.2 ! misho    72398:  * @author     Stig Bakken <ssb@php.net>
        !          72399:  * @author     Tomas V. V. Cox <cox@idecnet.com>
        !          72400:  * @author     Martin Jansen <mj@php.net>
1.1       misho    72401:  * @copyright  1997-2009 The Authors
                   72402:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    72403:  * @version    Release: 1.9.4
1.1       misho    72404:  * @link       http://pear.php.net/package/PEAR
1.1.1.2 ! misho    72405:  * @since      Class available since Release 1.3.0
1.1       misho    72406:  */
1.1.1.2 ! misho    72407: class PEAR_Downloader extends PEAR_Common
1.1       misho    72408: {
                   72409:     /**
1.1.1.2 ! misho    72410:      * @var PEAR_Registry
        !          72411:      * @access private
1.1       misho    72412:      */
1.1.1.2 ! misho    72413:     var $_registry;
1.1       misho    72414: 
                   72415:     /**
1.1.1.2 ! misho    72416:      * Preferred Installation State (snapshot, devel, alpha, beta, stable)
        !          72417:      * @var string|null
        !          72418:      * @access private
        !          72419:      */
        !          72420:     var $_preferredState;
        !          72421: 
        !          72422:     /**
        !          72423:      * Options from command-line passed to Install.
        !          72424:      *
        !          72425:      * Recognized options:<br />
        !          72426:      *  - onlyreqdeps   : install all required dependencies as well
        !          72427:      *  - alldeps       : install all dependencies, including optional
        !          72428:      *  - installroot   : base relative path to install files in
        !          72429:      *  - force         : force a download even if warnings would prevent it
        !          72430:      *  - nocompress    : download uncompressed tarballs
        !          72431:      * @see PEAR_Command_Install
        !          72432:      * @access private
        !          72433:      * @var array
1.1       misho    72434:      */
                   72435:     var $_options;
                   72436: 
                   72437:     /**
1.1.1.2 ! misho    72438:      * Downloaded Packages after a call to download().
        !          72439:      *
        !          72440:      * Format of each entry:
        !          72441:      *
        !          72442:      * <code>
        !          72443:      * array('pkg' => 'package_name', 'file' => '/path/to/local/file',
        !          72444:      *    'info' => array() // parsed package.xml
        !          72445:      * );
        !          72446:      * </code>
        !          72447:      * @access private
        !          72448:      * @var array
1.1       misho    72449:      */
1.1.1.2 ! misho    72450:     var $_downloadedPackages = array();
1.1       misho    72451: 
                   72452:     /**
1.1.1.2 ! misho    72453:      * Packages slated for download.
        !          72454:      *
        !          72455:      * This is used to prevent downloading a package more than once should it be a dependency
        !          72456:      * for two packages to be installed.
        !          72457:      * Format of each entry:
        !          72458:      *
        !          72459:      * <pre>
        !          72460:      * array('package_name1' => parsed package.xml, 'package_name2' => parsed package.xml,
        !          72461:      * );
        !          72462:      * </pre>
        !          72463:      * @access private
        !          72464:      * @var array
1.1       misho    72465:      */
1.1.1.2 ! misho    72466:     var $_toDownload = array();
1.1       misho    72467: 
                   72468:     /**
1.1.1.2 ! misho    72469:      * Array of every package installed, with names lower-cased.
        !          72470:      *
        !          72471:      * Format:
        !          72472:      * <code>
        !          72473:      * array('package1' => 0, 'package2' => 1, );
        !          72474:      * </code>
        !          72475:      * @var array
1.1       misho    72476:      */
1.1.1.2 ! misho    72477:     var $_installed = array();
        !          72478: 
        !          72479:     /**
        !          72480:      * @var array
        !          72481:      * @access private
        !          72482:      */
        !          72483:     var $_errorStack = array();
        !          72484: 
        !          72485:     /**
        !          72486:      * @var boolean
        !          72487:      * @access private
        !          72488:      */
        !          72489:     var $_internalDownload = false;
        !          72490: 
        !          72491:     /**
        !          72492:      * Temporary variable used in sorting packages by dependency in {@link sortPkgDeps()}
        !          72493:      * @var array
        !          72494:      * @access private
        !          72495:      */
        !          72496:     var $_packageSortTree;
        !          72497: 
        !          72498:     /**
        !          72499:      * Temporary directory, or configuration value where downloads will occur
        !          72500:      * @var string
        !          72501:      */
        !          72502:     var $_downloadDir;
        !          72503: 
        !          72504:     /**
        !          72505:      * @param PEAR_Frontend_*
        !          72506:      * @param array
        !          72507:      * @param PEAR_Config
        !          72508:      */
        !          72509:     function PEAR_Downloader(&$ui, $options, &$config)
        !          72510:     {
        !          72511:         parent::PEAR_Common();
        !          72512:         $this->_options = $options;
        !          72513:         $this->config = &$config;
        !          72514:         $this->_preferredState = $this->config->get('preferred_state');
        !          72515:         $this->ui = &$ui;
        !          72516:         if (!$this->_preferredState) {
        !          72517:             // don't inadvertantly use a non-set preferred_state
        !          72518:             $this->_preferredState = null;
        !          72519:         }
        !          72520: 
        !          72521:         if (isset($this->_options['installroot'])) {
        !          72522:             $this->config->setInstallRoot($this->_options['installroot']);
        !          72523:         }
        !          72524:         $this->_registry = &$config->getRegistry();
        !          72525: 
        !          72526:         if (isset($this->_options['alldeps']) || isset($this->_options['onlyreqdeps'])) {
        !          72527:             $this->_installed = $this->_registry->listAllPackages();
        !          72528:             foreach ($this->_installed as $key => $unused) {
        !          72529:                 if (!count($unused)) {
        !          72530:                     continue;
        !          72531:                 }
        !          72532:                 $strtolower = create_function('$a','return strtolower($a);');
        !          72533:                 array_walk($this->_installed[$key], $strtolower);
        !          72534:             }
        !          72535:         }
        !          72536:     }
        !          72537: 
        !          72538:     /**
        !          72539:      * Attempt to discover a channel's remote capabilities from
        !          72540:      * its server name
        !          72541:      * @param string
        !          72542:      * @return boolean
        !          72543:      */
        !          72544:     function discover($channel)
        !          72545:     {
        !          72546:         $this->log(1, 'Attempting to discover channel "' . $channel . '"...');
        !          72547:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          72548:         $callback = $this->ui ? array(&$this, '_downloadCallback') : null;
        !          72549:         if (!class_exists('System')) {
        !          72550:             require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
        !          72551:         }
        !          72552: 
        !          72553:         $tmpdir = $this->config->get('temp_dir');
        !          72554:         $tmp = System::mktemp('-d -t "' . $tmpdir . '"');
        !          72555:         $a   = $this->downloadHttp('http://' . $channel . '/channel.xml', $this->ui, $tmp, $callback, false);
        !          72556:         PEAR::popErrorHandling();
        !          72557:         if (PEAR::isError($a)) {
        !          72558:             // Attempt to fallback to https automatically.
        !          72559:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          72560:             $this->log(1, 'Attempting fallback to https instead of http on channel "' . $channel . '"...');
        !          72561:             $a = $this->downloadHttp('https://' . $channel . '/channel.xml', $this->ui, $tmp, $callback, false);
        !          72562:             PEAR::popErrorHandling();
        !          72563:             if (PEAR::isError($a)) {
        !          72564:                 return false;
        !          72565:             }
        !          72566:         }
        !          72567: 
        !          72568:         list($a, $lastmodified) = $a;
        !          72569:         if (!class_exists('PEAR_ChannelFile')) {
        !          72570:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
        !          72571:         }
        !          72572: 
        !          72573:         $b = new PEAR_ChannelFile;
        !          72574:         if ($b->fromXmlFile($a)) {
        !          72575:             unlink($a);
        !          72576:             if ($this->config->get('auto_discover')) {
        !          72577:                 $this->_registry->addChannel($b, $lastmodified);
        !          72578:                 $alias = $b->getName();
        !          72579:                 if ($b->getName() == $this->_registry->channelName($b->getAlias())) {
        !          72580:                     $alias = $b->getAlias();
        !          72581:                 }
        !          72582: 
        !          72583:                 $this->log(1, 'Auto-discovered channel "' . $channel .
        !          72584:                     '", alias "' . $alias . '", adding to registry');
        !          72585:             }
        !          72586: 
        !          72587:             return true;
        !          72588:         }
1.1       misho    72589: 
1.1.1.2 ! misho    72590:         unlink($a);
        !          72591:         return false;
        !          72592:     }
1.1       misho    72593: 
                   72594:     /**
1.1.1.2 ! misho    72595:      * For simpler unit-testing
        !          72596:      * @param PEAR_Downloader
        !          72597:      * @return PEAR_Downloader_Package
1.1       misho    72598:      */
1.1.1.2 ! misho    72599:     function &newDownloaderPackage(&$t)
        !          72600:     {
        !          72601:         if (!class_exists('PEAR_Downloader_Package')) {
        !          72602:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Downloader/Package.php';
        !          72603:         }
        !          72604:         $a = &new PEAR_Downloader_Package($t);
        !          72605:         return $a;
        !          72606:     }
1.1       misho    72607: 
                   72608:     /**
1.1.1.2 ! misho    72609:      * For simpler unit-testing
1.1       misho    72610:      * @param PEAR_Config
1.1.1.2 ! misho    72611:      * @param array
        !          72612:      * @param array
        !          72613:      * @param int
1.1       misho    72614:      */
1.1.1.2 ! misho    72615:     function &getDependency2Object(&$c, $i, $p, $s)
1.1       misho    72616:     {
1.1.1.2 ! misho    72617:         if (!class_exists('PEAR_Dependency2')) {
        !          72618:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Dependency2.php';
1.1       misho    72619:         }
1.1.1.2 ! misho    72620:         $z = &new PEAR_Dependency2($c, $i, $p, $s);
        !          72621:         return $z;
        !          72622:     }
1.1       misho    72623: 
1.1.1.2 ! misho    72624:     function &download($params)
        !          72625:     {
        !          72626:         if (!count($params)) {
        !          72627:             $a = array();
        !          72628:             return $a;
1.1       misho    72629:         }
                   72630: 
1.1.1.2 ! misho    72631:         if (!isset($this->_registry)) {
        !          72632:             $this->_registry = &$this->config->getRegistry();
1.1       misho    72633:         }
                   72634: 
1.1.1.2 ! misho    72635:         $channelschecked = array();
        !          72636:         // convert all parameters into PEAR_Downloader_Package objects
        !          72637:         foreach ($params as $i => $param) {
        !          72638:             $params[$i] = &$this->newDownloaderPackage($this);
        !          72639:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          72640:             $err = $params[$i]->initialize($param);
        !          72641:             PEAR::staticPopErrorHandling();
        !          72642:             if (!$err) {
        !          72643:                 // skip parameters that were missed by preferred_state
        !          72644:                 continue;
        !          72645:             }
1.1       misho    72646: 
1.1.1.2 ! misho    72647:             if (PEAR::isError($err)) {
        !          72648:                 if (!isset($this->_options['soft']) && $err->getMessage() !== '') {
        !          72649:                     $this->log(0, $err->getMessage());
        !          72650:                 }
1.1       misho    72651: 
1.1.1.2 ! misho    72652:                 $params[$i] = false;
        !          72653:                 if (is_object($param)) {
        !          72654:                     $param = $param->getChannel() . '/' . $param->getPackage();
        !          72655:                 }
1.1       misho    72656: 
1.1.1.2 ! misho    72657:                 if (!isset($this->_options['soft'])) {
        !          72658:                     $this->log(2, 'Package "' . $param . '" is not valid');
        !          72659:                 }
1.1       misho    72660: 
1.1.1.2 ! misho    72661:                 // Message logged above in a specific verbose mode, passing null to not show up on CLI
        !          72662:                 $this->pushError(null, PEAR_INSTALLER_SKIPPED);
        !          72663:             } else {
        !          72664:                 do {
        !          72665:                     if ($params[$i] && $params[$i]->getType() == 'local') {
        !          72666:                         // bug #7090 skip channel.xml check for local packages
        !          72667:                         break;
        !          72668:                     }
        !          72669: 
        !          72670:                     if ($params[$i] && !isset($channelschecked[$params[$i]->getChannel()]) &&
        !          72671:                           !isset($this->_options['offline'])
        !          72672:                     ) {
        !          72673:                         $channelschecked[$params[$i]->getChannel()] = true;
        !          72674:                         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          72675:                         if (!class_exists('System')) {
        !          72676:                             require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
        !          72677:                         }
        !          72678: 
        !          72679:                         $curchannel = &$this->_registry->getChannel($params[$i]->getChannel());
        !          72680:                         if (PEAR::isError($curchannel)) {
        !          72681:                             PEAR::staticPopErrorHandling();
        !          72682:                             return $this->raiseError($curchannel);
        !          72683:                         }
        !          72684: 
        !          72685:                         if (PEAR::isError($dir = $this->getDownloadDir())) {
        !          72686:                             PEAR::staticPopErrorHandling();
        !          72687:                             break;
        !          72688:                         }
        !          72689: 
        !          72690:                         $mirror = $this->config->get('preferred_mirror', null, $params[$i]->getChannel());
        !          72691:                         $url    = 'http://' . $mirror . '/channel.xml';
        !          72692:                         $a = $this->downloadHttp($url, $this->ui, $dir, null, $curchannel->lastModified());
        !          72693: 
        !          72694:                         PEAR::staticPopErrorHandling();
        !          72695:                         if (PEAR::isError($a) || !$a) {
        !          72696:                             // Attempt fallback to https automatically
        !          72697:                             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          72698:                             $a = $this->downloadHttp('https://' . $mirror .
        !          72699:                                 '/channel.xml', $this->ui, $dir, null, $curchannel->lastModified());
        !          72700: 
        !          72701:                             PEAR::staticPopErrorHandling();
        !          72702:                             if (PEAR::isError($a) || !$a) {
        !          72703:                                 break;
        !          72704:                             }
        !          72705:                         }
        !          72706:                         $this->log(0, 'WARNING: channel "' . $params[$i]->getChannel() . '" has ' .
        !          72707:                             'updated its protocols, use "' . PEAR_RUNTYPE . ' channel-update ' . $params[$i]->getChannel() .
        !          72708:                             '" to update');
        !          72709:                     }
        !          72710:                 } while (false);
        !          72711: 
        !          72712:                 if ($params[$i] && !isset($this->_options['downloadonly'])) {
        !          72713:                     if (isset($this->_options['packagingroot'])) {
        !          72714:                         $checkdir = $this->_prependPath(
        !          72715:                             $this->config->get('php_dir', null, $params[$i]->getChannel()),
        !          72716:                             $this->_options['packagingroot']);
        !          72717:                     } else {
        !          72718:                         $checkdir = $this->config->get('php_dir',
        !          72719:                             null, $params[$i]->getChannel());
        !          72720:                     }
        !          72721: 
        !          72722:                     while ($checkdir && $checkdir != '/' && !file_exists($checkdir)) {
        !          72723:                         $checkdir = dirname($checkdir);
        !          72724:                     }
        !          72725: 
        !          72726:                     if ($checkdir == '.') {
        !          72727:                         $checkdir = '/';
        !          72728:                     }
        !          72729: 
        !          72730:                     if (!is_writeable($checkdir)) {
        !          72731:                         return PEAR::raiseError('Cannot install, php_dir for channel "' .
        !          72732:                             $params[$i]->getChannel() . '" is not writeable by the current user');
        !          72733:                     }
1.1       misho    72734:                 }
                   72735:             }
1.1.1.2 ! misho    72736:         }
1.1       misho    72737: 
1.1.1.2 ! misho    72738:         unset($channelschecked);
        !          72739:         PEAR_Downloader_Package::removeDuplicates($params);
        !          72740:         if (!count($params)) {
        !          72741:             $a = array();
        !          72742:             return $a;
        !          72743:         }
1.1       misho    72744: 
1.1.1.2 ! misho    72745:         if (!isset($this->_options['nodeps']) && !isset($this->_options['offline'])) {
        !          72746:             $reverify = true;
        !          72747:             while ($reverify) {
        !          72748:                 $reverify = false;
        !          72749:                 foreach ($params as $i => $param) {
        !          72750:                     //PHP Bug 40768 / PEAR Bug #10944
        !          72751:                     //Nested foreaches fail in PHP 5.2.1
        !          72752:                     key($params);
        !          72753:                     $ret = $params[$i]->detectDependencies($params);
        !          72754:                     if (PEAR::isError($ret)) {
        !          72755:                         $reverify = true;
        !          72756:                         $params[$i] = false;
        !          72757:                         PEAR_Downloader_Package::removeDuplicates($params);
        !          72758:                         if (!isset($this->_options['soft'])) {
        !          72759:                             $this->log(0, $ret->getMessage());
        !          72760:                         }
        !          72761:                         continue 2;
        !          72762:                     }
1.1       misho    72763:                 }
1.1.1.2 ! misho    72764:             }
        !          72765:         }
1.1       misho    72766: 
1.1.1.2 ! misho    72767:         if (isset($this->_options['offline'])) {
        !          72768:             $this->log(3, 'Skipping dependency download check, --offline specified');
        !          72769:         }
        !          72770: 
        !          72771:         if (!count($params)) {
        !          72772:             $a = array();
        !          72773:             return $a;
        !          72774:         }
        !          72775: 
        !          72776:         while (PEAR_Downloader_Package::mergeDependencies($params));
        !          72777:         PEAR_Downloader_Package::removeDuplicates($params, true);
        !          72778:         $errorparams = array();
        !          72779:         if (PEAR_Downloader_Package::detectStupidDuplicates($params, $errorparams)) {
        !          72780:             if (count($errorparams)) {
        !          72781:                 foreach ($errorparams as $param) {
        !          72782:                     $name = $this->_registry->parsedPackageNameToString($param->getParsedPackage());
        !          72783:                     $this->pushError('Duplicate package ' . $name . ' found', PEAR_INSTALLER_FAILED);
1.1       misho    72784:                 }
1.1.1.2 ! misho    72785:                 $a = array();
        !          72786:                 return $a;
1.1       misho    72787:             }
                   72788:         }
                   72789: 
1.1.1.2 ! misho    72790:         PEAR_Downloader_Package::removeInstalled($params);
        !          72791:         if (!count($params)) {
        !          72792:             $this->pushError('No valid packages found', PEAR_INSTALLER_FAILED);
        !          72793:             $a = array();
        !          72794:             return $a;
1.1       misho    72795:         }
                   72796: 
1.1.1.2 ! misho    72797:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          72798:         $err = $this->analyzeDependencies($params);
        !          72799:         PEAR::popErrorHandling();
        !          72800:         if (!count($params)) {
        !          72801:             $this->pushError('No valid packages found', PEAR_INSTALLER_FAILED);
        !          72802:             $a = array();
        !          72803:             return $a;
        !          72804:         }
1.1       misho    72805: 
1.1.1.2 ! misho    72806:         $ret = array();
        !          72807:         $newparams = array();
        !          72808:         if (isset($this->_options['pretend'])) {
        !          72809:             return $params;
        !          72810:         }
1.1       misho    72811: 
1.1.1.2 ! misho    72812:         $somefailed = false;
        !          72813:         foreach ($params as $i => $package) {
        !          72814:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          72815:             $pf = &$params[$i]->download();
        !          72816:             PEAR::staticPopErrorHandling();
        !          72817:             if (PEAR::isError($pf)) {
        !          72818:                 if (!isset($this->_options['soft'])) {
        !          72819:                     $this->log(1, $pf->getMessage());
        !          72820:                     $this->log(0, 'Error: cannot download "' .
        !          72821:                         $this->_registry->parsedPackageNameToString($package->getParsedPackage(),
        !          72822:                             true) .
        !          72823:                         '"');
        !          72824:                 }
        !          72825:                 $somefailed = true;
        !          72826:                 continue;
        !          72827:             }
        !          72828: 
        !          72829:             $newparams[] = &$params[$i];
        !          72830:             $ret[] = array(
        !          72831:                 'file' => $pf->getArchiveFile(),
        !          72832:                 'info' => &$pf,
        !          72833:                 'pkg'  => $pf->getPackage()
        !          72834:             );
        !          72835:         }
        !          72836: 
        !          72837:         if ($somefailed) {
        !          72838:             // remove params that did not download successfully
        !          72839:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          72840:             $err = $this->analyzeDependencies($newparams, true);
        !          72841:             PEAR::popErrorHandling();
        !          72842:             if (!count($newparams)) {
        !          72843:                 $this->pushError('Download failed', PEAR_INSTALLER_FAILED);
        !          72844:                 $a = array();
        !          72845:                 return $a;
        !          72846:             }
        !          72847:         }
        !          72848: 
        !          72849:         $this->_downloadedPackages = $ret;
        !          72850:         return $newparams;
1.1       misho    72851:     }
                   72852: 
                   72853:     /**
1.1.1.2 ! misho    72854:      * @param array all packages to be installed
1.1       misho    72855:      */
1.1.1.2 ! misho    72856:     function analyzeDependencies(&$params, $force = false)
1.1       misho    72857:     {
1.1.1.2 ! misho    72858:         if (isset($this->_options['downloadonly'])) {
        !          72859:             return;
1.1       misho    72860:         }
                   72861: 
1.1.1.2 ! misho    72862:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          72863:         $redo  = true;
        !          72864:         $reset = $hasfailed = $failed = false;
        !          72865:         while ($redo) {
        !          72866:             $redo = false;
        !          72867:             foreach ($params as $i => $param) {
        !          72868:                 $deps = $param->getDeps();
        !          72869:                 if (!$deps) {
        !          72870:                     $depchecker = &$this->getDependency2Object($this->config, $this->getOptions(),
        !          72871:                         $param->getParsedPackage(), PEAR_VALIDATE_DOWNLOADING);
        !          72872:                     $send = $param->getPackageFile();
1.1       misho    72873: 
1.1.1.2 ! misho    72874:                     $installcheck = $depchecker->validatePackage($send, $this, $params);
        !          72875:                     if (PEAR::isError($installcheck)) {
        !          72876:                         if (!isset($this->_options['soft'])) {
        !          72877:                             $this->log(0, $installcheck->getMessage());
1.1       misho    72878:                         }
1.1.1.2 ! misho    72879:                         $hasfailed  = true;
        !          72880:                         $params[$i] = false;
        !          72881:                         $reset      = true;
        !          72882:                         $redo       = true;
        !          72883:                         $failed     = false;
        !          72884:                         PEAR_Downloader_Package::removeDuplicates($params);
        !          72885:                         continue 2;
        !          72886:                     }
        !          72887:                     continue;
        !          72888:                 }
1.1       misho    72889: 
1.1.1.2 ! misho    72890:                 if (!$reset && $param->alreadyValidated() && !$force) {
        !          72891:                     continue;
        !          72892:                 }
        !          72893: 
        !          72894:                 if (count($deps)) {
        !          72895:                     $depchecker = &$this->getDependency2Object($this->config, $this->getOptions(),
        !          72896:                         $param->getParsedPackage(), PEAR_VALIDATE_DOWNLOADING);
        !          72897:                     $send = $param->getPackageFile();
        !          72898:                     if ($send === null) {
        !          72899:                         $send = $param->getDownloadURL();
1.1       misho    72900:                     }
                   72901: 
1.1.1.2 ! misho    72902:                     $installcheck = $depchecker->validatePackage($send, $this, $params);
        !          72903:                     if (PEAR::isError($installcheck)) {
        !          72904:                         if (!isset($this->_options['soft'])) {
        !          72905:                             $this->log(0, $installcheck->getMessage());
        !          72906:                         }
        !          72907:                         $hasfailed  = true;
        !          72908:                         $params[$i] = false;
        !          72909:                         $reset      = true;
        !          72910:                         $redo       = true;
        !          72911:                         $failed     = false;
        !          72912:                         PEAR_Downloader_Package::removeDuplicates($params);
        !          72913:                         continue 2;
1.1       misho    72914:                     }
1.1.1.2 ! misho    72915: 
        !          72916:                     $failed = false;
        !          72917:                     if (isset($deps['required']) && is_array($deps['required'])) {
        !          72918:                         foreach ($deps['required'] as $type => $dep) {
        !          72919:                             // note: Dependency2 will never return a PEAR_Error if ignore-errors
        !          72920:                             // is specified, so soft is needed to turn off logging
        !          72921:                             if (!isset($dep[0])) {
        !          72922:                                 if (PEAR::isError($e = $depchecker->{"validate{$type}Dependency"}($dep,
        !          72923:                                       true, $params))) {
        !          72924:                                     $failed = true;
        !          72925:                                     if (!isset($this->_options['soft'])) {
        !          72926:                                         $this->log(0, $e->getMessage());
        !          72927:                                     }
        !          72928:                                 } elseif (is_array($e) && !$param->alreadyValidated()) {
        !          72929:                                     if (!isset($this->_options['soft'])) {
        !          72930:                                         $this->log(0, $e[0]);
        !          72931:                                     }
        !          72932:                                 }
        !          72933:                             } else {
        !          72934:                                 foreach ($dep as $d) {
        !          72935:                                     if (PEAR::isError($e =
        !          72936:                                           $depchecker->{"validate{$type}Dependency"}($d,
        !          72937:                                           true, $params))) {
        !          72938:                                         $failed = true;
        !          72939:                                         if (!isset($this->_options['soft'])) {
        !          72940:                                             $this->log(0, $e->getMessage());
        !          72941:                                         }
        !          72942:                                     } elseif (is_array($e) && !$param->alreadyValidated()) {
        !          72943:                                         if (!isset($this->_options['soft'])) {
        !          72944:                                             $this->log(0, $e[0]);
        !          72945:                                         }
        !          72946:                                     }
        !          72947:                                 }
        !          72948:                             }
1.1       misho    72949:                         }
                   72950: 
1.1.1.2 ! misho    72951:                         if (isset($deps['optional']) && is_array($deps['optional'])) {
        !          72952:                             foreach ($deps['optional'] as $type => $dep) {
        !          72953:                                 if (!isset($dep[0])) {
        !          72954:                                     if (PEAR::isError($e =
        !          72955:                                           $depchecker->{"validate{$type}Dependency"}($dep,
        !          72956:                                           false, $params))) {
        !          72957:                                         $failed = true;
        !          72958:                                         if (!isset($this->_options['soft'])) {
        !          72959:                                             $this->log(0, $e->getMessage());
        !          72960:                                         }
        !          72961:                                     } elseif (is_array($e) && !$param->alreadyValidated()) {
        !          72962:                                         if (!isset($this->_options['soft'])) {
        !          72963:                                             $this->log(0, $e[0]);
        !          72964:                                         }
        !          72965:                                     }
        !          72966:                                 } else {
        !          72967:                                     foreach ($dep as $d) {
        !          72968:                                         if (PEAR::isError($e =
        !          72969:                                               $depchecker->{"validate{$type}Dependency"}($d,
        !          72970:                                               false, $params))) {
        !          72971:                                             $failed = true;
        !          72972:                                             if (!isset($this->_options['soft'])) {
        !          72973:                                                 $this->log(0, $e->getMessage());
        !          72974:                                             }
        !          72975:                                         } elseif (is_array($e) && !$param->alreadyValidated()) {
        !          72976:                                             if (!isset($this->_options['soft'])) {
        !          72977:                                                 $this->log(0, $e[0]);
        !          72978:                                             }
        !          72979:                                         }
        !          72980:                                     }
        !          72981:                                 }
        !          72982:                             }
        !          72983:                         }
        !          72984: 
        !          72985:                         $groupname = $param->getGroup();
        !          72986:                         if (isset($deps['group']) && $groupname) {
        !          72987:                             if (!isset($deps['group'][0])) {
        !          72988:                                 $deps['group'] = array($deps['group']);
        !          72989:                             }
        !          72990: 
        !          72991:                             $found = false;
        !          72992:                             foreach ($deps['group'] as $group) {
        !          72993:                                 if ($group['attribs']['name'] == $groupname) {
        !          72994:                                     $found = true;
        !          72995:                                     break;
        !          72996:                                 }
        !          72997:                             }
        !          72998: 
        !          72999:                             if ($found) {
        !          73000:                                 unset($group['attribs']);
        !          73001:                                 foreach ($group as $type => $dep) {
        !          73002:                                     if (!isset($dep[0])) {
        !          73003:                                         if (PEAR::isError($e =
        !          73004:                                               $depchecker->{"validate{$type}Dependency"}($dep,
        !          73005:                                               false, $params))) {
        !          73006:                                             $failed = true;
        !          73007:                                             if (!isset($this->_options['soft'])) {
        !          73008:                                                 $this->log(0, $e->getMessage());
        !          73009:                                             }
        !          73010:                                         } elseif (is_array($e) && !$param->alreadyValidated()) {
        !          73011:                                             if (!isset($this->_options['soft'])) {
        !          73012:                                                 $this->log(0, $e[0]);
        !          73013:                                             }
        !          73014:                                         }
        !          73015:                                     } else {
        !          73016:                                         foreach ($dep as $d) {
        !          73017:                                             if (PEAR::isError($e =
        !          73018:                                                   $depchecker->{"validate{$type}Dependency"}($d,
        !          73019:                                                   false, $params))) {
        !          73020:                                                 $failed = true;
        !          73021:                                                 if (!isset($this->_options['soft'])) {
        !          73022:                                                     $this->log(0, $e->getMessage());
        !          73023:                                                 }
        !          73024:                                             } elseif (is_array($e) && !$param->alreadyValidated()) {
        !          73025:                                                 if (!isset($this->_options['soft'])) {
        !          73026:                                                     $this->log(0, $e[0]);
        !          73027:                                                 }
        !          73028:                                             }
        !          73029:                                         }
        !          73030:                                     }
        !          73031:                                 }
        !          73032:                             }
1.1       misho    73033:                         }
1.1.1.2 ! misho    73034:                     } else {
        !          73035:                         foreach ($deps as $dep) {
        !          73036:                             if (PEAR::isError($e = $depchecker->validateDependency1($dep, $params))) {
        !          73037:                                 $failed = true;
        !          73038:                                 if (!isset($this->_options['soft'])) {
        !          73039:                                     $this->log(0, $e->getMessage());
        !          73040:                                 }
        !          73041:                             } elseif (is_array($e) && !$param->alreadyValidated()) {
        !          73042:                                 if (!isset($this->_options['soft'])) {
        !          73043:                                     $this->log(0, $e[0]);
        !          73044:                                 }
        !          73045:                             }
1.1       misho    73046:                         }
                   73047:                     }
1.1.1.2 ! misho    73048:                     $params[$i]->setValidated();
        !          73049:                 }
1.1       misho    73050: 
1.1.1.2 ! misho    73051:                 if ($failed) {
        !          73052:                     $hasfailed  = true;
        !          73053:                     $params[$i] = false;
        !          73054:                     $reset      = true;
        !          73055:                     $redo       = true;
        !          73056:                     $failed     = false;
        !          73057:                     PEAR_Downloader_Package::removeDuplicates($params);
        !          73058:                     continue 2;
1.1       misho    73059:                 }
1.1.1.2 ! misho    73060:             }
1.1       misho    73061:         }
                   73062: 
1.1.1.2 ! misho    73063:         PEAR::staticPopErrorHandling();
        !          73064:         if ($hasfailed && (isset($this->_options['ignore-errors']) ||
        !          73065:               isset($this->_options['nodeps']))) {
        !          73066:             // this is probably not needed, but just in case
        !          73067:             if (!isset($this->_options['soft'])) {
        !          73068:                 $this->log(0, 'WARNING: dependencies failed');
        !          73069:             }
        !          73070:         }
1.1       misho    73071:     }
                   73072: 
                   73073:     /**
1.1.1.2 ! misho    73074:      * Retrieve the directory that downloads will happen in
        !          73075:      * @access private
        !          73076:      * @return string
1.1       misho    73077:      */
1.1.1.2 ! misho    73078:     function getDownloadDir()
1.1       misho    73079:     {
1.1.1.2 ! misho    73080:         if (isset($this->_downloadDir)) {
        !          73081:             return $this->_downloadDir;
1.1       misho    73082:         }
                   73083: 
1.1.1.2 ! misho    73084:         $downloaddir = $this->config->get('download_dir');
        !          73085:         if (empty($downloaddir) || (is_dir($downloaddir) && !is_writable($downloaddir))) {
        !          73086:             if  (is_dir($downloaddir) && !is_writable($downloaddir)) {
        !          73087:                 $this->log(0, 'WARNING: configuration download directory "' . $downloaddir .
        !          73088:                     '" is not writeable.  Change download_dir config variable to ' .
        !          73089:                     'a writeable dir to avoid this warning');
        !          73090:             }
1.1       misho    73091: 
1.1.1.2 ! misho    73092:             if (!class_exists('System')) {
        !          73093:                 require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
1.1       misho    73094:             }
                   73095: 
1.1.1.2 ! misho    73096:             if (PEAR::isError($downloaddir = System::mktemp('-d'))) {
        !          73097:                 return $downloaddir;
        !          73098:             }
        !          73099:             $this->log(3, '+ tmp dir created at ' . $downloaddir);
1.1       misho    73100:         }
                   73101: 
1.1.1.2 ! misho    73102:         if (!is_writable($downloaddir)) {
        !          73103:             if (PEAR::isError(System::mkdir(array('-p', $downloaddir))) ||
        !          73104:                   !is_writable($downloaddir)) {
        !          73105:                 return PEAR::raiseError('download directory "' . $downloaddir .
        !          73106:                     '" is not writeable.  Change download_dir config variable to ' .
        !          73107:                     'a writeable dir');
1.1       misho    73108:             }
                   73109:         }
                   73110: 
1.1.1.2 ! misho    73111:         return $this->_downloadDir = $downloaddir;
1.1       misho    73112:     }
                   73113: 
1.1.1.2 ! misho    73114:     function setDownloadDir($dir)
1.1       misho    73115:     {
1.1.1.2 ! misho    73116:         if (!@is_writable($dir)) {
        !          73117:             if (PEAR::isError(System::mkdir(array('-p', $dir)))) {
        !          73118:                 return PEAR::raiseError('download directory "' . $dir .
        !          73119:                     '" is not writeable.  Change download_dir config variable to ' .
        !          73120:                     'a writeable dir');
        !          73121:             }
        !          73122:         }
        !          73123:         $this->_downloadDir = $dir;
1.1       misho    73124:     }
                   73125: 
1.1.1.2 ! misho    73126:     function configSet($key, $value, $layer = 'user', $channel = false)
1.1       misho    73127:     {
1.1.1.2 ! misho    73128:         $this->config->set($key, $value, $layer, $channel);
        !          73129:         $this->_preferredState = $this->config->get('preferred_state', null, $channel);
        !          73130:         if (!$this->_preferredState) {
        !          73131:             // don't inadvertantly use a non-set preferred_state
        !          73132:             $this->_preferredState = null;
1.1       misho    73133:         }
                   73134:     }
                   73135: 
1.1.1.2 ! misho    73136:     function setOptions($options)
1.1       misho    73137:     {
1.1.1.2 ! misho    73138:         $this->_options = $options;
        !          73139:     }
1.1       misho    73140: 
1.1.1.2 ! misho    73141:     function getOptions()
        !          73142:     {
        !          73143:         return $this->_options;
        !          73144:     }
1.1       misho    73145: 
                   73146: 
1.1.1.2 ! misho    73147:     /**
        !          73148:      * @param array output of {@link parsePackageName()}
        !          73149:      * @access private
        !          73150:      */
        !          73151:     function _getPackageDownloadUrl($parr)
        !          73152:     {
        !          73153:         $curchannel = $this->config->get('default_channel');
        !          73154:         $this->configSet('default_channel', $parr['channel']);
        !          73155:         // getDownloadURL returns an array.  On error, it only contains information
        !          73156:         // on the latest release as array(version, info).  On success it contains
        !          73157:         // array(version, info, download url string)
        !          73158:         $state = isset($parr['state']) ? $parr['state'] : $this->config->get('preferred_state');
        !          73159:         if (!$this->_registry->channelExists($parr['channel'])) {
        !          73160:             do {
        !          73161:                 if ($this->config->get('auto_discover') && $this->discover($parr['channel'])) {
        !          73162:                     break;
1.1       misho    73163:                 }
                   73164: 
1.1.1.2 ! misho    73165:                 $this->configSet('default_channel', $curchannel);
        !          73166:                 return PEAR::raiseError('Unknown remote channel: ' . $parr['channel']);
        !          73167:             } while (false);
1.1       misho    73168:         }
                   73169: 
1.1.1.2 ! misho    73170:         $chan = &$this->_registry->getChannel($parr['channel']);
        !          73171:         if (PEAR::isError($chan)) {
        !          73172:             return $chan;
1.1       misho    73173:         }
                   73174: 
1.1.1.2 ! misho    73175:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          73176:         $version   = $this->_registry->packageInfo($parr['package'], 'version', $parr['channel']);
        !          73177:         $stability = $this->_registry->packageInfo($parr['package'], 'stability', $parr['channel']);
        !          73178:         // package is installed - use the installed release stability level
        !          73179:         if (!isset($parr['state']) && $stability !== null) {
        !          73180:             $state = $stability['release'];
1.1       misho    73181:         }
1.1.1.2 ! misho    73182:         PEAR::staticPopErrorHandling();
        !          73183:         $base2 = false;
1.1       misho    73184: 
1.1.1.2 ! misho    73185:         $preferred_mirror = $this->config->get('preferred_mirror');
        !          73186:         if (!$chan->supportsREST($preferred_mirror) ||
        !          73187:               (
        !          73188:                !($base2 = $chan->getBaseURL('REST1.3', $preferred_mirror))
        !          73189:                &&
        !          73190:                !($base = $chan->getBaseURL('REST1.0', $preferred_mirror))
        !          73191:               )
        !          73192:         ) {
        !          73193:             return $this->raiseError($parr['channel'] . ' is using a unsupported protocol - This should never happen.');
1.1       misho    73194:         }
                   73195: 
1.1.1.2 ! misho    73196:         if ($base2) {
        !          73197:             $rest = &$this->config->getREST('1.3', $this->_options);
        !          73198:             $base = $base2;
        !          73199:         } else {
        !          73200:             $rest = &$this->config->getREST('1.0', $this->_options);
1.1       misho    73201:         }
                   73202: 
1.1.1.2 ! misho    73203:         $downloadVersion = false;
        !          73204:         if (!isset($parr['version']) && !isset($parr['state']) && $version
        !          73205:               && !PEAR::isError($version)
        !          73206:               && !isset($this->_options['downloadonly'])
        !          73207:         ) {
        !          73208:             $downloadVersion = $version;
1.1       misho    73209:         }
                   73210: 
1.1.1.2 ! misho    73211:         $url = $rest->getDownloadURL($base, $parr, $state, $downloadVersion, $chan->getName());
        !          73212:         if (PEAR::isError($url)) {
        !          73213:             $this->configSet('default_channel', $curchannel);
        !          73214:             return $url;
1.1       misho    73215:         }
                   73216: 
1.1.1.2 ! misho    73217:         if ($parr['channel'] != $curchannel) {
        !          73218:             $this->configSet('default_channel', $curchannel);
1.1       misho    73219:         }
                   73220: 
1.1.1.2 ! misho    73221:         if (!is_array($url)) {
        !          73222:             return $url;
1.1       misho    73223:         }
                   73224: 
1.1.1.2 ! misho    73225:         $url['raw'] = false; // no checking is necessary for REST
        !          73226:         if (!is_array($url['info'])) {
        !          73227:             return PEAR::raiseError('Invalid remote dependencies retrieved from REST - ' .
        !          73228:                 'this should never happen');
1.1       misho    73229:         }
                   73230: 
1.1.1.2 ! misho    73231:         if (!isset($this->_options['force']) &&
        !          73232:               !isset($this->_options['downloadonly']) &&
        !          73233:               $version &&
        !          73234:               !PEAR::isError($version) &&
        !          73235:               !isset($parr['group'])
        !          73236:         ) {
        !          73237:             if (version_compare($version, $url['version'], '=')) {
        !          73238:                 return PEAR::raiseError($this->_registry->parsedPackageNameToString(
        !          73239:                     $parr, true) . ' is already installed and is the same as the ' .
        !          73240:                     'released version ' . $url['version'], -976);
1.1       misho    73241:             }
                   73242: 
1.1.1.2 ! misho    73243:             if (version_compare($version, $url['version'], '>')) {
        !          73244:                 return PEAR::raiseError($this->_registry->parsedPackageNameToString(
        !          73245:                     $parr, true) . ' is already installed and is newer than detected ' .
        !          73246:                     'released version ' . $url['version'], -976);
1.1       misho    73247:             }
                   73248:         }
                   73249: 
1.1.1.2 ! misho    73250:         if (isset($url['info']['required']) || $url['compatible']) {
        !          73251:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2.php';
        !          73252:             $pf = new PEAR_PackageFile_v2;
        !          73253:             $pf->setRawChannel($parr['channel']);
        !          73254:             if ($url['compatible']) {
        !          73255:                 $pf->setRawCompatible($url['compatible']);
1.1       misho    73256:             }
1.1.1.2 ! misho    73257:         } else {
        !          73258:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v1.php';
        !          73259:             $pf = new PEAR_PackageFile_v1;
1.1       misho    73260:         }
                   73261: 
1.1.1.2 ! misho    73262:         $pf->setRawPackage($url['package']);
        !          73263:         $pf->setDeps($url['info']);
        !          73264:         if ($url['compatible']) {
        !          73265:             $pf->setCompatible($url['compatible']);
1.1       misho    73266:         }
                   73267: 
1.1.1.2 ! misho    73268:         $pf->setRawState($url['stability']);
        !          73269:         $url['info'] = &$pf;
        !          73270:         if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) {
        !          73271:             $ext = '.tar';
        !          73272:         } else {
        !          73273:             $ext = '.tgz';
1.1       misho    73274:         }
                   73275: 
1.1.1.2 ! misho    73276:         if (is_array($url) && isset($url['url'])) {
        !          73277:             $url['url'] .= $ext;
1.1       misho    73278:         }
1.1.1.2 ! misho    73279: 
        !          73280:         return $url;
1.1       misho    73281:     }
                   73282: 
1.1.1.2 ! misho    73283:     /**
        !          73284:      * @param array dependency array
        !          73285:      * @access private
        !          73286:      */
        !          73287:     function _getDepPackageDownloadUrl($dep, $parr)
1.1       misho    73288:     {
1.1.1.2 ! misho    73289:         $xsdversion = isset($dep['rel']) ? '1.0' : '2.0';
        !          73290:         $curchannel = $this->config->get('default_channel');
1.1       misho    73291:         if (isset($dep['uri'])) {
1.1.1.2 ! misho    73292:             $xsdversion = '2.0';
        !          73293:             $chan = &$this->_registry->getChannel('__uri');
        !          73294:             if (PEAR::isError($chan)) {
        !          73295:                 return $chan;
1.1       misho    73296:             }
                   73297: 
1.1.1.2 ! misho    73298:             $version = $this->_registry->packageInfo($dep['name'], 'version', '__uri');
        !          73299:             $this->configSet('default_channel', '__uri');
        !          73300:         } else {
        !          73301:             if (isset($dep['channel'])) {
        !          73302:                 $remotechannel = $dep['channel'];
        !          73303:             } else {
        !          73304:                 $remotechannel = 'pear.php.net';
1.1       misho    73305:             }
                   73306: 
1.1.1.2 ! misho    73307:             if (!$this->_registry->channelExists($remotechannel)) {
        !          73308:                 do {
        !          73309:                     if ($this->config->get('auto_discover')) {
        !          73310:                         if ($this->discover($remotechannel)) {
        !          73311:                             break;
        !          73312:                         }
        !          73313:                     }
        !          73314:                     return PEAR::raiseError('Unknown remote channel: ' . $remotechannel);
        !          73315:                 } while (false);
1.1       misho    73316:             }
                   73317: 
1.1.1.2 ! misho    73318:             $chan = &$this->_registry->getChannel($remotechannel);
        !          73319:             if (PEAR::isError($chan)) {
        !          73320:                 return $chan;
1.1       misho    73321:             }
                   73322: 
1.1.1.2 ! misho    73323:             $version = $this->_registry->packageInfo($dep['name'], 'version', $remotechannel);
        !          73324:             $this->configSet('default_channel', $remotechannel);
1.1       misho    73325:         }
                   73326: 
1.1.1.2 ! misho    73327:         $state = isset($parr['state']) ? $parr['state'] : $this->config->get('preferred_state');
        !          73328:         if (isset($parr['state']) && isset($parr['version'])) {
        !          73329:             unset($parr['state']);
        !          73330:         }
1.1       misho    73331: 
1.1.1.2 ! misho    73332:         if (isset($dep['uri'])) {
        !          73333:             $info = &$this->newDownloaderPackage($this);
        !          73334:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          73335:             $err = $info->initialize($dep);
        !          73336:             PEAR::staticPopErrorHandling();
        !          73337:             if (!$err) {
        !          73338:                 // skip parameters that were missed by preferred_state
        !          73339:                 return PEAR::raiseError('Cannot initialize dependency');
        !          73340:             }
1.1       misho    73341: 
1.1.1.2 ! misho    73342:             if (PEAR::isError($err)) {
        !          73343:                 if (!isset($this->_options['soft'])) {
        !          73344:                     $this->log(0, $err->getMessage());
1.1       misho    73345:                 }
                   73346: 
1.1.1.2 ! misho    73347:                 if (is_object($info)) {
        !          73348:                     $param = $info->getChannel() . '/' . $info->getPackage();
        !          73349:                 }
        !          73350:                 return PEAR::raiseError('Package "' . $param . '" is not valid');
1.1       misho    73351:             }
1.1.1.2 ! misho    73352:             return $info;
        !          73353:         } elseif ($chan->supportsREST($this->config->get('preferred_mirror'))
        !          73354:               &&
        !          73355:                 (
        !          73356:                   ($base2 = $chan->getBaseURL('REST1.3', $this->config->get('preferred_mirror')))
        !          73357:                     ||
        !          73358:                   ($base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror')))
        !          73359:                 )
        !          73360:         ) {
        !          73361:             if ($base2) {
        !          73362:                 $base = $base2;
        !          73363:                 $rest = &$this->config->getREST('1.3', $this->_options);
        !          73364:             } else {
        !          73365:                 $rest = &$this->config->getREST('1.0', $this->_options);
1.1       misho    73366:             }
                   73367: 
1.1.1.2 ! misho    73368:             $url = $rest->getDepDownloadURL($base, $xsdversion, $dep, $parr,
        !          73369:                     $state, $version, $chan->getName());
        !          73370:             if (PEAR::isError($url)) {
        !          73371:                 return $url;
        !          73372:             }
1.1       misho    73373: 
1.1.1.2 ! misho    73374:             if ($parr['channel'] != $curchannel) {
        !          73375:                 $this->configSet('default_channel', $curchannel);
1.1       misho    73376:             }
                   73377: 
1.1.1.2 ! misho    73378:             if (!is_array($url)) {
        !          73379:                 return $url;
        !          73380:             }
1.1       misho    73381: 
1.1.1.2 ! misho    73382:             $url['raw'] = false; // no checking is necessary for REST
        !          73383:             if (!is_array($url['info'])) {
        !          73384:                 return PEAR::raiseError('Invalid remote dependencies retrieved from REST - ' .
        !          73385:                     'this should never happen');
1.1       misho    73386:             }
                   73387: 
1.1.1.2 ! misho    73388:             if (isset($url['info']['required'])) {
        !          73389:                 if (!class_exists('PEAR_PackageFile_v2')) {
        !          73390:                     require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2.php';
        !          73391:                 }
        !          73392:                 $pf = new PEAR_PackageFile_v2;
        !          73393:                 $pf->setRawChannel($remotechannel);
        !          73394:             } else {
        !          73395:                 if (!class_exists('PEAR_PackageFile_v1')) {
        !          73396:                     require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v1.php';
1.1       misho    73397:                 }
1.1.1.2 ! misho    73398:                 $pf = new PEAR_PackageFile_v1;
1.1       misho    73399: 
1.1.1.2 ! misho    73400:             }
        !          73401:             $pf->setRawPackage($url['package']);
        !          73402:             $pf->setDeps($url['info']);
        !          73403:             if ($url['compatible']) {
        !          73404:                 $pf->setCompatible($url['compatible']);
1.1       misho    73405:             }
                   73406: 
1.1.1.2 ! misho    73407:             $pf->setRawState($url['stability']);
        !          73408:             $url['info'] = &$pf;
        !          73409:             if (!extension_loaded("zlib") || isset($this->_options['nocompress'])) {
        !          73410:                 $ext = '.tar';
        !          73411:             } else {
        !          73412:                 $ext = '.tgz';
1.1       misho    73413:             }
                   73414: 
1.1.1.2 ! misho    73415:             if (is_array($url) && isset($url['url'])) {
        !          73416:                 $url['url'] .= $ext;
1.1       misho    73417:             }
                   73418: 
1.1.1.2 ! misho    73419:             return $url;
1.1       misho    73420:         }
                   73421: 
1.1.1.2 ! misho    73422:         return $this->raiseError($parr['channel'] . ' is using a unsupported protocol - This should never happen.');
        !          73423:     }
1.1       misho    73424: 
1.1.1.2 ! misho    73425:     /**
        !          73426:      * @deprecated in favor of _getPackageDownloadUrl
        !          73427:      */
        !          73428:     function getPackageDownloadUrl($package, $version = null, $channel = false)
        !          73429:     {
        !          73430:         if ($version) {
        !          73431:             $package .= "-$version";
1.1       misho    73432:         }
1.1.1.2 ! misho    73433:         if ($this === null || $this->_registry === null) {
        !          73434:             $package = "http://pear.php.net/get/$package";
        !          73435:         } else {
        !          73436:             $chan = $this->_registry->getChannel($channel);
        !          73437:             if (PEAR::isError($chan)) {
        !          73438:                 return '';
1.1       misho    73439:             }
1.1.1.2 ! misho    73440:             $package = "http://" . $chan->getServer() . "/get/$package";
        !          73441:         }
        !          73442:         if (!extension_loaded("zlib")) {
        !          73443:             $package .= '?uncompress=yes';
        !          73444:         }
        !          73445:         return $package;
        !          73446:     }
1.1       misho    73447: 
1.1.1.2 ! misho    73448:     /**
        !          73449:      * Retrieve a list of downloaded packages after a call to {@link download()}.
        !          73450:      *
        !          73451:      * Also resets the list of downloaded packages.
        !          73452:      * @return array
        !          73453:      */
        !          73454:     function getDownloadedPackages()
        !          73455:     {
        !          73456:         $ret = $this->_downloadedPackages;
        !          73457:         $this->_downloadedPackages = array();
        !          73458:         $this->_toDownload = array();
        !          73459:         return $ret;
        !          73460:     }
1.1       misho    73461: 
1.1.1.2 ! misho    73462:     function _downloadCallback($msg, $params = null)
        !          73463:     {
        !          73464:         switch ($msg) {
        !          73465:             case 'saveas':
        !          73466:                 $this->log(1, "downloading $params ...");
        !          73467:                 break;
        !          73468:             case 'done':
        !          73469:                 $this->log(1, '...done: ' . number_format($params, 0, '', ',') . ' bytes');
        !          73470:                 break;
        !          73471:             case 'bytesread':
        !          73472:                 static $bytes;
        !          73473:                 if (empty($bytes)) {
        !          73474:                     $bytes = 0;
        !          73475:                 }
        !          73476:                 if (!($bytes % 10240)) {
        !          73477:                     $this->log(1, '.', false);
        !          73478:                 }
        !          73479:                 $bytes += $params;
        !          73480:                 break;
        !          73481:             case 'start':
        !          73482:                 if($params[1] == -1) {
        !          73483:                     $length = "Unknown size";
        !          73484:                 } else {
        !          73485:                     $length = number_format($params[1], 0, '', ',')." bytes";
1.1       misho    73486:                 }
1.1.1.2 ! misho    73487:                 $this->log(1, "Starting to download {$params[0]} ($length)");
        !          73488:                 break;
        !          73489:         }
        !          73490:         if (method_exists($this->ui, '_downloadCallback'))
        !          73491:             $this->ui->_downloadCallback($msg, $params);
        !          73492:     }
1.1       misho    73493: 
1.1.1.2 ! misho    73494:     function _prependPath($path, $prepend)
        !          73495:     {
        !          73496:         if (strlen($prepend) > 0) {
        !          73497:             if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) {
        !          73498:                 if (preg_match('/^[a-z]:/i', $prepend)) {
        !          73499:                     $prepend = substr($prepend, 2);
        !          73500:                 } elseif ($prepend{0} != '\\') {
        !          73501:                     $prepend = "\\$prepend";
1.1       misho    73502:                 }
1.1.1.2 ! misho    73503:                 $path = substr($path, 0, 2) . $prepend . substr($path, 2);
        !          73504:             } else {
        !          73505:                 $path = $prepend . $path;
1.1       misho    73506:             }
1.1.1.2 ! misho    73507:         }
        !          73508:         return $path;
        !          73509:     }
1.1       misho    73510: 
1.1.1.2 ! misho    73511:     /**
        !          73512:      * @param string
        !          73513:      * @param integer
        !          73514:      */
        !          73515:     function pushError($errmsg, $code = -1)
        !          73516:     {
        !          73517:         array_push($this->_errorStack, array($errmsg, $code));
        !          73518:     }
1.1       misho    73519: 
1.1.1.2 ! misho    73520:     function getErrorMsgs()
        !          73521:     {
        !          73522:         $msgs = array();
        !          73523:         $errs = $this->_errorStack;
        !          73524:         foreach ($errs as $err) {
        !          73525:             $msgs[] = $err[0];
1.1       misho    73526:         }
1.1.1.2 ! misho    73527:         $this->_errorStack = array();
        !          73528:         return $msgs;
1.1       misho    73529:     }
                   73530: 
1.1.1.2 ! misho    73531:     /**
        !          73532:      * for BC
        !          73533:      *
        !          73534:      * @deprecated
        !          73535:      */
        !          73536:     function sortPkgDeps(&$packages, $uninstall = false)
1.1       misho    73537:     {
1.1.1.2 ! misho    73538:         $uninstall ?
        !          73539:             $this->sortPackagesForUninstall($packages) :
        !          73540:             $this->sortPackagesForInstall($packages);
1.1       misho    73541:     }
                   73542: 
                   73543:     /**
1.1.1.2 ! misho    73544:      * Sort a list of arrays of array(downloaded packagefilename) by dependency.
1.1       misho    73545:      *
1.1.1.2 ! misho    73546:      * This uses the topological sort method from graph theory, and the
        !          73547:      * Structures_Graph package to properly sort dependencies for installation.
        !          73548:      * @param array an array of downloaded PEAR_Downloader_Packages
        !          73549:      * @return array array of array(packagefilename, package.xml contents)
1.1       misho    73550:      */
1.1.1.2 ! misho    73551:     function sortPackagesForInstall(&$packages)
1.1       misho    73552:     {
1.1.1.2 ! misho    73553:         require_once 'phar://install-pear-nozlib.phar/' . 'Structures/Graph.php';
        !          73554:         require_once 'phar://install-pear-nozlib.phar/' . 'Structures/Graph/Node.php';
        !          73555:         require_once 'phar://install-pear-nozlib.phar/' . 'Structures/Graph/Manipulator/TopologicalSorter.php';
        !          73556:         $depgraph = new Structures_Graph(true);
        !          73557:         $nodes = array();
        !          73558:         $reg = &$this->config->getRegistry();
        !          73559:         foreach ($packages as $i => $package) {
        !          73560:             $pname = $reg->parsedPackageNameToString(
        !          73561:                 array(
        !          73562:                     'channel' => $package->getChannel(),
        !          73563:                     'package' => strtolower($package->getPackage()),
        !          73564:                 ));
        !          73565:             $nodes[$pname] = new Structures_Graph_Node;
        !          73566:             $nodes[$pname]->setData($packages[$i]);
        !          73567:             $depgraph->addNode($nodes[$pname]);
1.1       misho    73568:         }
                   73569: 
1.1.1.2 ! misho    73570:         $deplinks = array();
        !          73571:         foreach ($nodes as $package => $node) {
        !          73572:             $pf = &$node->getData();
        !          73573:             $pdeps = $pf->getDeps(true);
        !          73574:             if (!$pdeps) {
        !          73575:                 continue;
1.1       misho    73576:             }
                   73577: 
1.1.1.2 ! misho    73578:             if ($pf->getPackagexmlVersion() == '1.0') {
        !          73579:                 foreach ($pdeps as $dep) {
        !          73580:                     if ($dep['type'] != 'pkg' ||
        !          73581:                           (isset($dep['optional']) && $dep['optional'] == 'yes')) {
        !          73582:                         continue;
        !          73583:                     }
        !          73584: 
        !          73585:                     $dname = $reg->parsedPackageNameToString(
        !          73586:                           array(
        !          73587:                               'channel' => 'pear.php.net',
        !          73588:                               'package' => strtolower($dep['name']),
        !          73589:                           ));
        !          73590: 
        !          73591:                     if (isset($nodes[$dname])) {
        !          73592:                         if (!isset($deplinks[$dname])) {
        !          73593:                             $deplinks[$dname] = array();
        !          73594:                         }
        !          73595: 
        !          73596:                         $deplinks[$dname][$package] = 1;
        !          73597:                         // dependency is in installed packages
        !          73598:                         continue;
        !          73599:                     }
        !          73600: 
        !          73601:                     $dname = $reg->parsedPackageNameToString(
        !          73602:                           array(
        !          73603:                               'channel' => 'pecl.php.net',
        !          73604:                               'package' => strtolower($dep['name']),
        !          73605:                           ));
        !          73606: 
        !          73607:                     if (isset($nodes[$dname])) {
        !          73608:                         if (!isset($deplinks[$dname])) {
        !          73609:                             $deplinks[$dname] = array();
        !          73610:                         }
        !          73611: 
        !          73612:                         $deplinks[$dname][$package] = 1;
        !          73613:                         // dependency is in installed packages
        !          73614:                         continue;
        !          73615:                     }
1.1       misho    73616:                 }
1.1.1.2 ! misho    73617:             } else {
        !          73618:                 // the only ordering we care about is:
        !          73619:                 // 1) subpackages must be installed before packages that depend on them
        !          73620:                 // 2) required deps must be installed before packages that depend on them
        !          73621:                 if (isset($pdeps['required']['subpackage'])) {
        !          73622:                     $t = $pdeps['required']['subpackage'];
        !          73623:                     if (!isset($t[0])) {
        !          73624:                         $t = array($t);
        !          73625:                     }
        !          73626: 
        !          73627:                     $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
        !          73628:                 }
        !          73629: 
        !          73630:                 if (isset($pdeps['group'])) {
        !          73631:                     if (!isset($pdeps['group'][0])) {
        !          73632:                         $pdeps['group'] = array($pdeps['group']);
        !          73633:                     }
        !          73634: 
        !          73635:                     foreach ($pdeps['group'] as $group) {
        !          73636:                         if (isset($group['subpackage'])) {
        !          73637:                             $t = $group['subpackage'];
        !          73638:                             if (!isset($t[0])) {
        !          73639:                                 $t = array($t);
        !          73640:                             }
1.1       misho    73641: 
1.1.1.2 ! misho    73642:                             $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
        !          73643:                         }
1.1       misho    73644:                     }
                   73645:                 }
                   73646: 
1.1.1.2 ! misho    73647:                 if (isset($pdeps['optional']['subpackage'])) {
        !          73648:                     $t = $pdeps['optional']['subpackage'];
        !          73649:                     if (!isset($t[0])) {
        !          73650:                         $t = array($t);
        !          73651:                     }
        !          73652: 
        !          73653:                     $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
1.1       misho    73654:                 }
                   73655: 
1.1.1.2 ! misho    73656:                 if (isset($pdeps['required']['package'])) {
        !          73657:                     $t = $pdeps['required']['package'];
        !          73658:                     if (!isset($t[0])) {
        !          73659:                         $t = array($t);
        !          73660:                     }
1.1       misho    73661: 
1.1.1.2 ! misho    73662:                     $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
        !          73663:                 }
1.1       misho    73664: 
1.1.1.2 ! misho    73665:                 if (isset($pdeps['group'])) {
        !          73666:                     if (!isset($pdeps['group'][0])) {
        !          73667:                         $pdeps['group'] = array($pdeps['group']);
        !          73668:                     }
1.1       misho    73669: 
1.1.1.2 ! misho    73670:                     foreach ($pdeps['group'] as $group) {
        !          73671:                         if (isset($group['package'])) {
        !          73672:                             $t = $group['package'];
        !          73673:                             if (!isset($t[0])) {
        !          73674:                                 $t = array($t);
1.1       misho    73675:                             }
1.1.1.2 ! misho    73676: 
        !          73677:                             $this->_setupGraph($t, $reg, $deplinks, $nodes, $package);
1.1       misho    73678:                         }
                   73679:                     }
                   73680:                 }
                   73681:             }
                   73682:         }
                   73683: 
1.1.1.2 ! misho    73684:         $this->_detectDepCycle($deplinks);
        !          73685:         foreach ($deplinks as $dependent => $parents) {
        !          73686:             foreach ($parents as $parent => $unused) {
        !          73687:                 $nodes[$dependent]->connectTo($nodes[$parent]);
1.1       misho    73688:             }
                   73689:         }
                   73690: 
1.1.1.2 ! misho    73691:         $installOrder = Structures_Graph_Manipulator_TopologicalSorter::sort($depgraph);
        !          73692:         $ret = array();
        !          73693:         for ($i = 0, $count = count($installOrder); $i < $count; $i++) {
        !          73694:             foreach ($installOrder[$i] as $index => $sortedpackage) {
        !          73695:                 $data = &$installOrder[$i][$index]->getData();
        !          73696:                 $ret[] = &$nodes[$reg->parsedPackageNameToString(
        !          73697:                           array(
        !          73698:                               'channel' => $data->getChannel(),
        !          73699:                               'package' => strtolower($data->getPackage()),
        !          73700:                           ))]->getData();
1.1       misho    73701:             }
                   73702:         }
                   73703: 
1.1.1.2 ! misho    73704:         $packages = $ret;
        !          73705:         return;
        !          73706:     }
1.1       misho    73707: 
1.1.1.2 ! misho    73708:     /**
        !          73709:      * Detect recursive links between dependencies and break the cycles
        !          73710:      *
        !          73711:      * @param array
        !          73712:      * @access private
        !          73713:      */
        !          73714:     function _detectDepCycle(&$deplinks)
        !          73715:     {
        !          73716:         do {
        !          73717:             $keepgoing = false;
        !          73718:             foreach ($deplinks as $dep => $parents) {
        !          73719:                 foreach ($parents as $parent => $unused) {
        !          73720:                     // reset the parent cycle detector
        !          73721:                     $this->_testCycle(null, null, null);
        !          73722:                     if ($this->_testCycle($dep, $deplinks, $parent)) {
        !          73723:                         $keepgoing = true;
        !          73724:                         unset($deplinks[$dep][$parent]);
        !          73725:                         if (count($deplinks[$dep]) == 0) {
        !          73726:                             unset($deplinks[$dep]);
1.1       misho    73727:                         }
1.1.1.2 ! misho    73728: 
        !          73729:                         continue 3;
1.1       misho    73730:                     }
                   73731:                 }
                   73732:             }
1.1.1.2 ! misho    73733:         } while ($keepgoing);
        !          73734:     }
1.1       misho    73735: 
1.1.1.2 ! misho    73736:     function _testCycle($test, $deplinks, $dep)
        !          73737:     {
        !          73738:         static $visited = array();
        !          73739:         if ($test === null) {
        !          73740:             $visited = array();
        !          73741:             return;
        !          73742:         }
1.1       misho    73743: 
1.1.1.2 ! misho    73744:         // this happens when a parent has a dep cycle on another dependency
        !          73745:         // but the child is not part of the cycle
        !          73746:         if (isset($visited[$dep])) {
        !          73747:             return false;
1.1       misho    73748:         }
                   73749: 
1.1.1.2 ! misho    73750:         $visited[$dep] = 1;
        !          73751:         if ($test == $dep) {
        !          73752:             return true;
        !          73753:         }
1.1       misho    73754: 
1.1.1.2 ! misho    73755:         if (isset($deplinks[$dep])) {
        !          73756:             if (in_array($test, array_keys($deplinks[$dep]), true)) {
        !          73757:                 return true;
        !          73758:             }
1.1       misho    73759: 
1.1.1.2 ! misho    73760:             foreach ($deplinks[$dep] as $parent => $unused) {
        !          73761:                 if ($this->_testCycle($test, $deplinks, $parent)) {
        !          73762:                     return true;
1.1       misho    73763:                 }
                   73764:             }
                   73765:         }
                   73766: 
1.1.1.2 ! misho    73767:         return false;
1.1       misho    73768:     }
                   73769: 
1.1.1.2 ! misho    73770:     /**
        !          73771:      * Set up the dependency for installation parsing
        !          73772:      *
        !          73773:      * @param array $t dependency information
        !          73774:      * @param PEAR_Registry $reg
        !          73775:      * @param array $deplinks list of dependency links already established
        !          73776:      * @param array $nodes all existing package nodes
        !          73777:      * @param string $package parent package name
        !          73778:      * @access private
        !          73779:      */
        !          73780:     function _setupGraph($t, $reg, &$deplinks, &$nodes, $package)
1.1       misho    73781:     {
1.1.1.2 ! misho    73782:         foreach ($t as $dep) {
        !          73783:             $depchannel = !isset($dep['channel']) ? '__uri': $dep['channel'];
        !          73784:             $dname = $reg->parsedPackageNameToString(
        !          73785:                   array(
        !          73786:                       'channel' => $depchannel,
        !          73787:                       'package' => strtolower($dep['name']),
        !          73788:                   ));
        !          73789: 
        !          73790:             if (isset($nodes[$dname])) {
        !          73791:                 if (!isset($deplinks[$dname])) {
        !          73792:                     $deplinks[$dname] = array();
        !          73793:                 }
        !          73794:                 $deplinks[$dname][$package] = 1;
        !          73795:             }
1.1       misho    73796:         }
1.1.1.2 ! misho    73797:     }
1.1       misho    73798: 
1.1.1.2 ! misho    73799:     function _dependsOn($a, $b)
        !          73800:     {
        !          73801:         return $this->_checkDepTree(strtolower($a->getChannel()), strtolower($a->getPackage()), $b);
        !          73802:     }
        !          73803: 
        !          73804:     function _checkDepTree($channel, $package, $b, $checked = array())
        !          73805:     {
        !          73806:         $checked[$channel][$package] = true;
        !          73807:         if (!isset($this->_depTree[$channel][$package])) {
        !          73808:             return false;
1.1       misho    73809:         }
                   73810: 
1.1.1.2 ! misho    73811:         if (isset($this->_depTree[$channel][$package][strtolower($b->getChannel())]
        !          73812:               [strtolower($b->getPackage())])) {
        !          73813:             return true;
1.1       misho    73814:         }
                   73815: 
1.1.1.2 ! misho    73816:         foreach ($this->_depTree[$channel][$package] as $ch => $packages) {
        !          73817:             foreach ($packages as $pa => $true) {
        !          73818:                 if ($this->_checkDepTree($ch, $pa, $b, $checked)) {
        !          73819:                     return true;
        !          73820:                 }
1.1       misho    73821:             }
1.1.1.2 ! misho    73822:         }
1.1       misho    73823: 
1.1.1.2 ! misho    73824:         return false;
        !          73825:     }
1.1       misho    73826: 
1.1.1.2 ! misho    73827:     function _sortInstall($a, $b)
        !          73828:     {
        !          73829:         if (!$a->getDeps() && !$b->getDeps()) {
        !          73830:             return 0; // neither package has dependencies, order is insignificant
1.1       misho    73831:         }
1.1.1.2 ! misho    73832:         if ($a->getDeps() && !$b->getDeps()) {
        !          73833:             return 1; // $a must be installed after $b because $a has dependencies
1.1       misho    73834:         }
1.1.1.2 ! misho    73835:         if (!$a->getDeps() && $b->getDeps()) {
        !          73836:             return -1; // $b must be installed after $a because $b has dependencies
1.1       misho    73837:         }
1.1.1.2 ! misho    73838:         // both packages have dependencies
        !          73839:         if ($this->_dependsOn($a, $b)) {
        !          73840:             return 1;
1.1       misho    73841:         }
1.1.1.2 ! misho    73842:         if ($this->_dependsOn($b, $a)) {
        !          73843:             return -1;
1.1       misho    73844:         }
1.1.1.2 ! misho    73845:         return 0;
1.1       misho    73846:     }
                   73847: 
                   73848:     /**
1.1.1.2 ! misho    73849:      * Download a file through HTTP.  Considers suggested file name in
        !          73850:      * Content-disposition: header and can run a callback function for
        !          73851:      * different events.  The callback will be called with two
        !          73852:      * parameters: the callback type, and parameters.  The implemented
        !          73853:      * callback types are:
1.1       misho    73854:      *
1.1.1.2 ! misho    73855:      *  'setup'       called at the very beginning, parameter is a UI object
        !          73856:      *                that should be used for all output
        !          73857:      *  'message'     the parameter is a string with an informational message
        !          73858:      *  'saveas'      may be used to save with a different file name, the
        !          73859:      *                parameter is the filename that is about to be used.
        !          73860:      *                If a 'saveas' callback returns a non-empty string,
        !          73861:      *                that file name will be used as the filename instead.
        !          73862:      *                Note that $save_dir will not be affected by this, only
        !          73863:      *                the basename of the file.
        !          73864:      *  'start'       download is starting, parameter is number of bytes
        !          73865:      *                that are expected, or -1 if unknown
        !          73866:      *  'bytesread'   parameter is the number of bytes read so far
        !          73867:      *  'done'        download is complete, parameter is the total number
        !          73868:      *                of bytes read
        !          73869:      *  'connfailed'  if the TCP/SSL connection fails, this callback is called
        !          73870:      *                with array(host,port,errno,errmsg)
        !          73871:      *  'writefailed' if writing to disk fails, this callback is called
        !          73872:      *                with array(destfile,errmsg)
1.1       misho    73873:      *
1.1.1.2 ! misho    73874:      * If an HTTP proxy has been configured (http_proxy PEAR_Config
        !          73875:      * setting), the proxy will be used.
        !          73876:      *
        !          73877:      * @param string  $url       the URL to download
        !          73878:      * @param object  $ui        PEAR_Frontend_* instance
        !          73879:      * @param object  $config    PEAR_Config instance
        !          73880:      * @param string  $save_dir  directory to save file in
        !          73881:      * @param mixed   $callback  function/method to call for status
        !          73882:      *                           updates
        !          73883:      * @param false|string|array $lastmodified header values to check against for caching
        !          73884:      *                           use false to return the header values from this download
        !          73885:      * @param false|array $accept Accept headers to send
        !          73886:      * @param false|string $channel Channel to use for retrieving authentication
        !          73887:      * @return string|array  Returns the full path of the downloaded file or a PEAR
        !          73888:      *                       error on failure.  If the error is caused by
        !          73889:      *                       socket-related errors, the error object will
        !          73890:      *                       have the fsockopen error code available through
        !          73891:      *                       getCode().  If caching is requested, then return the header
        !          73892:      *                       values.
        !          73893:      *
        !          73894:      * @access public
1.1       misho    73895:      */
1.1.1.2 ! misho    73896:     function downloadHttp($url, &$ui, $save_dir = '.', $callback = null, $lastmodified = null,
        !          73897:                           $accept = false, $channel = false)
1.1       misho    73898:     {
1.1.1.2 ! misho    73899:         static $redirect = 0;
        !          73900:         // always reset , so we are clean case of error
        !          73901:         $wasredirect = $redirect;
        !          73902:         $redirect = 0;
        !          73903:         if ($callback) {
        !          73904:             call_user_func($callback, 'setup', array(&$ui));
        !          73905:         }
        !          73906: 
        !          73907:         $info = parse_url($url);
        !          73908:         if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) {
        !          73909:             return PEAR::raiseError('Cannot download non-http URL "' . $url . '"');
        !          73910:         }
        !          73911: 
        !          73912:         if (!isset($info['host'])) {
        !          73913:             return PEAR::raiseError('Cannot download from non-URL "' . $url . '"');
        !          73914:         }
        !          73915: 
        !          73916:         $host = isset($info['host']) ? $info['host'] : null;
        !          73917:         $port = isset($info['port']) ? $info['port'] : null;
        !          73918:         $path = isset($info['path']) ? $info['path'] : null;
        !          73919: 
        !          73920:         if (isset($this)) {
        !          73921:             $config = &$this->config;
1.1       misho    73922:         } else {
1.1.1.2 ! misho    73923:             $config = &PEAR_Config::singleton();
1.1       misho    73924:         }
                   73925: 
1.1.1.2 ! misho    73926:         $proxy_host = $proxy_port = $proxy_user = $proxy_pass = '';
        !          73927:         if ($config->get('http_proxy') &&
        !          73928:               $proxy = parse_url($config->get('http_proxy'))) {
        !          73929:             $proxy_host = isset($proxy['host']) ? $proxy['host'] : null;
        !          73930:             if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') {
        !          73931:                 $proxy_host = 'ssl://' . $proxy_host;
1.1       misho    73932:             }
1.1.1.2 ! misho    73933:             $proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080;
        !          73934:             $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null;
        !          73935:             $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null;
1.1       misho    73936: 
1.1.1.2 ! misho    73937:             if ($callback) {
        !          73938:                 call_user_func($callback, 'message', "Using HTTP proxy $host:$port");
1.1       misho    73939:             }
1.1.1.2 ! misho    73940:         }
1.1       misho    73941: 
1.1.1.2 ! misho    73942:         if (empty($port)) {
        !          73943:             $port = (isset($info['scheme']) && $info['scheme'] == 'https') ? 443 : 80;
        !          73944:         }
1.1       misho    73945: 
1.1.1.2 ! misho    73946:         $scheme = (isset($info['scheme']) && $info['scheme'] == 'https') ? 'https' : 'http';
        !          73947: 
        !          73948:         if ($proxy_host != '') {
        !          73949:             $fp = @fsockopen($proxy_host, $proxy_port, $errno, $errstr);
        !          73950:             if (!$fp) {
        !          73951:                 if ($callback) {
        !          73952:                     call_user_func($callback, 'connfailed', array($proxy_host, $proxy_port,
        !          73953:                                                                   $errno, $errstr));
        !          73954:                 }
        !          73955:                 return PEAR::raiseError("Connection to `$proxy_host:$proxy_port' failed: $errstr", $errno);
        !          73956:             }
        !          73957: 
        !          73958:             if ($lastmodified === false || $lastmodified) {
        !          73959:                 $request  = "GET $url HTTP/1.1\r\n";
        !          73960:                 $request .= "Host: $host\r\n";
        !          73961:             } else {
        !          73962:                 $request  = "GET $url HTTP/1.0\r\n";
        !          73963:                 $request .= "Host: $host\r\n";
        !          73964:             }
        !          73965:         } else {
        !          73966:             $network_host = $host;
        !          73967:             if (isset($info['scheme']) && $info['scheme'] == 'https') {
        !          73968:                 $network_host = 'ssl://' . $host;
        !          73969:             }
        !          73970: 
        !          73971:             $fp = @fsockopen($network_host, $port, $errno, $errstr);
        !          73972:             if (!$fp) {
        !          73973:                 if ($callback) {
        !          73974:                     call_user_func($callback, 'connfailed', array($host, $port,
        !          73975:                                                                   $errno, $errstr));
1.1       misho    73976:                 }
1.1.1.2 ! misho    73977:                 return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno);
        !          73978:             }
        !          73979: 
        !          73980:             if ($lastmodified === false || $lastmodified) {
        !          73981:                 $request = "GET $path HTTP/1.1\r\n";
        !          73982:                 $request .= "Host: $host\r\n";
        !          73983:             } else {
        !          73984:                 $request = "GET $path HTTP/1.0\r\n";
        !          73985:                 $request .= "Host: $host\r\n";
        !          73986:             }
        !          73987:         }
        !          73988: 
        !          73989:         $ifmodifiedsince = '';
        !          73990:         if (is_array($lastmodified)) {
        !          73991:             if (isset($lastmodified['Last-Modified'])) {
        !          73992:                 $ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n";
1.1       misho    73993:             }
                   73994: 
1.1.1.2 ! misho    73995:             if (isset($lastmodified['ETag'])) {
        !          73996:                 $ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n";
        !          73997:             }
        !          73998:         } else {
        !          73999:             $ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : '');
1.1       misho    74000:         }
                   74001: 
1.1.1.2 ! misho    74002:         $request .= $ifmodifiedsince .
        !          74003:             "User-Agent: PEAR/1.9.4/PHP/" . PHP_VERSION . "\r\n";
1.1       misho    74004: 
1.1.1.2 ! misho    74005:         if (isset($this)) { // only pass in authentication for non-static calls
        !          74006:             $username = $config->get('username', null, $channel);
        !          74007:             $password = $config->get('password', null, $channel);
        !          74008:             if ($username && $password) {
        !          74009:                 $tmp = base64_encode("$username:$password");
        !          74010:                 $request .= "Authorization: Basic $tmp\r\n";
        !          74011:             }
1.1       misho    74012:         }
                   74013: 
1.1.1.2 ! misho    74014:         if ($proxy_host != '' && $proxy_user != '') {
        !          74015:             $request .= 'Proxy-Authorization: Basic ' .
        !          74016:                 base64_encode($proxy_user . ':' . $proxy_pass) . "\r\n";
1.1       misho    74017:         }
                   74018: 
1.1.1.2 ! misho    74019:         if ($accept) {
        !          74020:             $request .= 'Accept: ' . implode(', ', $accept) . "\r\n";
1.1       misho    74021:         }
                   74022: 
1.1.1.2 ! misho    74023:         $request .= "Connection: close\r\n";
        !          74024:         $request .= "\r\n";
        !          74025:         fwrite($fp, $request);
        !          74026:         $headers = array();
        !          74027:         $reply = 0;
        !          74028:         while (trim($line = fgets($fp, 1024))) {
        !          74029:             if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) {
        !          74030:                 $headers[strtolower($matches[1])] = trim($matches[2]);
        !          74031:             } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) {
        !          74032:                 $reply = (int)$matches[1];
        !          74033:                 if ($reply == 304 && ($lastmodified || ($lastmodified === false))) {
        !          74034:                     return false;
        !          74035:                 }
1.1       misho    74036: 
1.1.1.2 ! misho    74037:                 if (!in_array($reply, array(200, 301, 302, 303, 305, 307))) {
        !          74038:                     return PEAR::raiseError("File $scheme://$host:$port$path not valid (received: $line)");
        !          74039:                 }
        !          74040:             }
1.1       misho    74041:         }
                   74042: 
1.1.1.2 ! misho    74043:         if ($reply != 200) {
        !          74044:             if (!isset($headers['location'])) {
        !          74045:                 return PEAR::raiseError("File $scheme://$host:$port$path not valid (redirected but no location)");
        !          74046:             }
1.1       misho    74047: 
1.1.1.2 ! misho    74048:             if ($wasredirect > 4) {
        !          74049:                 return PEAR::raiseError("File $scheme://$host:$port$path not valid (redirection looped more than 5 times)");
        !          74050:             }
        !          74051: 
        !          74052:             $redirect = $wasredirect + 1;
        !          74053:             return $this->downloadHttp($headers['location'],
        !          74054:                     $ui, $save_dir, $callback, $lastmodified, $accept);
1.1       misho    74055:         }
                   74056: 
1.1.1.2 ! misho    74057:         if (isset($headers['content-disposition']) &&
        !          74058:             preg_match('/\sfilename=\"([^;]*\S)\"\s*(;|\\z)/', $headers['content-disposition'], $matches)) {
        !          74059:             $save_as = basename($matches[1]);
        !          74060:         } else {
        !          74061:             $save_as = basename($url);
1.1       misho    74062:         }
1.1.1.2 ! misho    74063: 
        !          74064:         if ($callback) {
        !          74065:             $tmp = call_user_func($callback, 'saveas', $save_as);
        !          74066:             if ($tmp) {
        !          74067:                 $save_as = $tmp;
1.1       misho    74068:             }
1.1.1.2 ! misho    74069:         }
1.1       misho    74070: 
1.1.1.2 ! misho    74071:         $dest_file = $save_dir . DIRECTORY_SEPARATOR . $save_as;
        !          74072:         if (is_link($dest_file)) {
        !          74073:             return PEAR::raiseError('SECURITY ERROR: Will not write to ' . $dest_file . ' as it is symlinked to ' . readlink($dest_file) . ' - Possible symlink attack');
        !          74074:         }
        !          74075: 
        !          74076:         if (!$wp = @fopen($dest_file, 'wb')) {
        !          74077:             fclose($fp);
        !          74078:             if ($callback) {
        !          74079:                 call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg));
1.1       misho    74080:             }
1.1.1.2 ! misho    74081:             return PEAR::raiseError("could not open $dest_file for writing");
1.1       misho    74082:         }
                   74083: 
1.1.1.2 ! misho    74084:         $length = isset($headers['content-length']) ? $headers['content-length'] : -1;
        !          74085: 
        !          74086:         $bytes = 0;
        !          74087:         if ($callback) {
        !          74088:             call_user_func($callback, 'start', array(basename($dest_file), $length));
1.1       misho    74089:         }
                   74090: 
1.1.1.2 ! misho    74091:         while ($data = fread($fp, 1024)) {
        !          74092:             $bytes += strlen($data);
        !          74093:             if ($callback) {
        !          74094:                 call_user_func($callback, 'bytesread', $bytes);
        !          74095:             }
        !          74096:             if (!@fwrite($wp, $data)) {
        !          74097:                 fclose($fp);
        !          74098:                 if ($callback) {
        !          74099:                     call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg));
        !          74100:                 }
        !          74101:                 return PEAR::raiseError("$dest_file: write failed ($php_errormsg)");
        !          74102:             }
1.1       misho    74103:         }
                   74104: 
1.1.1.2 ! misho    74105:         fclose($fp);
        !          74106:         fclose($wp);
        !          74107:         if ($callback) {
        !          74108:             call_user_func($callback, 'done', $bytes);
        !          74109:         }
1.1       misho    74110: 
1.1.1.2 ! misho    74111:         if ($lastmodified === false || $lastmodified) {
        !          74112:             if (isset($headers['etag'])) {
        !          74113:                 $lastmodified = array('ETag' => $headers['etag']);
        !          74114:             }
        !          74115: 
        !          74116:             if (isset($headers['last-modified'])) {
        !          74117:                 if (is_array($lastmodified)) {
        !          74118:                     $lastmodified['Last-Modified'] = $headers['last-modified'];
        !          74119:                 } else {
        !          74120:                     $lastmodified = $headers['last-modified'];
        !          74121:                 }
        !          74122:             }
        !          74123:             return array($dest_file, $lastmodified, $headers);
        !          74124:         }
        !          74125:         return $dest_file;
1.1       misho    74126:     }
                   74127: }<?php
                   74128: /**
1.1.1.2 ! misho    74129:  * PEAR_Downloader_Package
1.1       misho    74130:  *
                   74131:  * PHP versions 4 and 5
                   74132:  *
                   74133:  * @category   pear
                   74134:  * @package    PEAR
                   74135:  * @author     Greg Beaver <cellog@php.net>
                   74136:  * @copyright  1997-2009 The Authors
                   74137:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    74138:  * @version    CVS: $Id: Package.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    74139:  * @link       http://pear.php.net/package/PEAR
                   74140:  * @since      File available since Release 1.4.0a1
                   74141:  */
                   74142: 
                   74143: /**
1.1.1.2 ! misho    74144:  * Error code when parameter initialization fails because no releases
        !          74145:  * exist within preferred_state, but releases do exist
1.1       misho    74146:  */
1.1.1.2 ! misho    74147: define('PEAR_DOWNLOADER_PACKAGE_STATE', -1003);
        !          74148: /**
        !          74149:  * Error code when parameter initialization fails because no releases
        !          74150:  * exist that will work with the existing PHP version
        !          74151:  */
        !          74152: define('PEAR_DOWNLOADER_PACKAGE_PHPVERSION', -1004);
1.1       misho    74153: 
                   74154: /**
1.1.1.2 ! misho    74155:  * Coordinates download parameters and manages their dependencies
        !          74156:  * prior to downloading them.
        !          74157:  *
        !          74158:  * Input can come from three sources:
        !          74159:  *
        !          74160:  * - local files (archives or package.xml)
        !          74161:  * - remote files (downloadable urls)
        !          74162:  * - abstract package names
        !          74163:  *
        !          74164:  * The first two elements are handled cleanly by PEAR_PackageFile, but the third requires
        !          74165:  * accessing pearweb's xml-rpc interface to determine necessary dependencies, and the
        !          74166:  * format returned of dependencies is slightly different from that used in package.xml.
        !          74167:  *
        !          74168:  * This class hides the differences between these elements, and makes automatic
        !          74169:  * dependency resolution a piece of cake.  It also manages conflicts when
        !          74170:  * two classes depend on incompatible dependencies, or differing versions of the same
        !          74171:  * package dependency.  In addition, download will not be attempted if the php version is
        !          74172:  * not supported, PEAR installer version is not supported, or non-PECL extensions are not
        !          74173:  * installed.
1.1       misho    74174:  * @category   pear
                   74175:  * @package    PEAR
                   74176:  * @author     Greg Beaver <cellog@php.net>
                   74177:  * @copyright  1997-2009 The Authors
                   74178:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    74179:  * @version    Release: 1.9.4
1.1       misho    74180:  * @link       http://pear.php.net/package/PEAR
                   74181:  * @since      Class available since Release 1.4.0a1
                   74182:  */
1.1.1.2 ! misho    74183: class PEAR_Downloader_Package
1.1       misho    74184: {
                   74185:     /**
1.1.1.2 ! misho    74186:      * @var PEAR_Downloader
        !          74187:      */
        !          74188:     var $_downloader;
        !          74189:     /**
1.1       misho    74190:      * @var PEAR_Config
                   74191:      */
                   74192:     var $_config;
                   74193:     /**
                   74194:      * @var PEAR_Registry
                   74195:      */
                   74196:     var $_registry;
                   74197:     /**
1.1.1.2 ! misho    74198:      * Used to implement packagingroot properly
        !          74199:      * @var PEAR_Registry
1.1       misho    74200:      */
1.1.1.2 ! misho    74201:     var $_installRegistry;
1.1       misho    74202:     /**
1.1.1.2 ! misho    74203:      * @var PEAR_PackageFile_v1|PEAR_PackageFile|v2
1.1       misho    74204:      */
1.1.1.2 ! misho    74205:     var $_packagefile;
1.1       misho    74206:     /**
1.1.1.2 ! misho    74207:      * @var array
1.1       misho    74208:      */
1.1.1.2 ! misho    74209:     var $_parsedname;
1.1       misho    74210:     /**
1.1.1.2 ! misho    74211:      * @var array
        !          74212:      */
        !          74213:     var $_downloadURL;
        !          74214:     /**
        !          74215:      * @var array
        !          74216:      */
        !          74217:     var $_downloadDeps = array();
        !          74218:     /**
        !          74219:      * @var boolean
        !          74220:      */
        !          74221:     var $_valid = false;
        !          74222:     /**
        !          74223:      * @var boolean
        !          74224:      */
        !          74225:     var $_analyzed = false;
        !          74226:     /**
        !          74227:      * if this or a parent package was invoked with Package-state, this is set to the
        !          74228:      * state variable.
        !          74229:      *
        !          74230:      * This allows temporary reassignment of preferred_state for a parent package and all of
        !          74231:      * its dependencies.
        !          74232:      * @var string|false
        !          74233:      */
        !          74234:     var $_explicitState = false;
        !          74235:     /**
        !          74236:      * If this package is invoked with Package#group, this variable will be true
        !          74237:      */
        !          74238:     var $_explicitGroup = false;
        !          74239:     /**
        !          74240:      * Package type local|url
1.1       misho    74241:      * @var string
1.1.1.2 ! misho    74242:      */
        !          74243:     var $_type;
        !          74244:     /**
        !          74245:      * Contents of package.xml, if downloaded from a remote channel
        !          74246:      * @var string|false
1.1       misho    74247:      * @access private
                   74248:      */
1.1.1.2 ! misho    74249:     var $_rawpackagefile;
1.1       misho    74250:     /**
1.1.1.2 ! misho    74251:      * @var boolean
1.1       misho    74252:      * @access private
                   74253:      */
1.1.1.2 ! misho    74254:     var $_validated = false;
        !          74255: 
        !          74256:     /**
        !          74257:      * @param PEAR_Downloader
        !          74258:      */
        !          74259:     function PEAR_Downloader_Package(&$downloader)
        !          74260:     {
        !          74261:         $this->_downloader = &$downloader;
        !          74262:         $this->_config = &$this->_downloader->config;
        !          74263:         $this->_registry = &$this->_config->getRegistry();
        !          74264:         $options = $downloader->getOptions();
        !          74265:         if (isset($options['packagingroot'])) {
        !          74266:             $this->_config->setInstallRoot($options['packagingroot']);
        !          74267:             $this->_installRegistry = &$this->_config->getRegistry();
        !          74268:             $this->_config->setInstallRoot(false);
        !          74269:         } else {
        !          74270:             $this->_installRegistry = &$this->_registry;
        !          74271:         }
        !          74272:         $this->_valid = $this->_analyzed = false;
        !          74273:     }
        !          74274: 
        !          74275:     /**
        !          74276:      * Parse the input and determine whether this is a local file, a remote uri, or an
        !          74277:      * abstract package name.
        !          74278:      *
        !          74279:      * This is the heart of the PEAR_Downloader_Package(), and is used in
        !          74280:      * {@link PEAR_Downloader::download()}
        !          74281:      * @param string
        !          74282:      * @return bool|PEAR_Error
        !          74283:      */
        !          74284:     function initialize($param)
        !          74285:     {
        !          74286:         $origErr = $this->_fromFile($param);
        !          74287:         if ($this->_valid) {
        !          74288:             return true;
        !          74289:         }
        !          74290: 
        !          74291:         $options = $this->_downloader->getOptions();
        !          74292:         if (isset($options['offline'])) {
        !          74293:             if (PEAR::isError($origErr) && !isset($options['soft'])) {
        !          74294:                 foreach ($origErr->getUserInfo() as $userInfo) {
        !          74295:                     if (isset($userInfo['message'])) {
        !          74296:                         $this->_downloader->log(0, $userInfo['message']);
        !          74297:                     }
        !          74298:                 }
        !          74299: 
        !          74300:                 $this->_downloader->log(0, $origErr->getMessage());
        !          74301:             }
        !          74302: 
        !          74303:             return PEAR::raiseError('Cannot download non-local package "' . $param . '"');
        !          74304:         }
        !          74305: 
        !          74306:         $err = $this->_fromUrl($param);
        !          74307:         if (PEAR::isError($err) || !$this->_valid) {
        !          74308:             if ($this->_type == 'url') {
        !          74309:                 if (PEAR::isError($err) && !isset($options['soft'])) {
        !          74310:                     $this->_downloader->log(0, $err->getMessage());
        !          74311:                 }
        !          74312: 
        !          74313:                 return PEAR::raiseError("Invalid or missing remote package file");
        !          74314:             }
        !          74315: 
        !          74316:             $err = $this->_fromString($param);
        !          74317:             if (PEAR::isError($err) || !$this->_valid) {
        !          74318:                 if (PEAR::isError($err) && $err->getCode() == PEAR_DOWNLOADER_PACKAGE_STATE) {
        !          74319:                     return false; // instruct the downloader to silently skip
        !          74320:                 }
        !          74321: 
        !          74322:                 if (isset($this->_type) && $this->_type == 'local' && PEAR::isError($origErr)) {
        !          74323:                     if (is_array($origErr->getUserInfo())) {
        !          74324:                         foreach ($origErr->getUserInfo() as $err) {
        !          74325:                             if (is_array($err)) {
        !          74326:                                 $err = $err['message'];
        !          74327:                             }
        !          74328: 
        !          74329:                             if (!isset($options['soft'])) {
        !          74330:                                 $this->_downloader->log(0, $err);
        !          74331:                             }
        !          74332:                         }
        !          74333:                     }
        !          74334: 
        !          74335:                     if (!isset($options['soft'])) {
        !          74336:                         $this->_downloader->log(0, $origErr->getMessage());
        !          74337:                     }
        !          74338: 
        !          74339:                     if (is_array($param)) {
        !          74340:                         $param = $this->_registry->parsedPackageNameToString($param, true);
        !          74341:                     }
        !          74342: 
        !          74343:                     if (!isset($options['soft'])) {
        !          74344:                         $this->_downloader->log(2, "Cannot initialize '$param', invalid or missing package file");
        !          74345:                     }
        !          74346: 
        !          74347:                     // Passing no message back - already logged above
        !          74348:                     return PEAR::raiseError();
        !          74349:                 }
        !          74350: 
        !          74351:                 if (PEAR::isError($err) && !isset($options['soft'])) {
        !          74352:                     $this->_downloader->log(0, $err->getMessage());
        !          74353:                 }
        !          74354: 
        !          74355:                 if (is_array($param)) {
        !          74356:                     $param = $this->_registry->parsedPackageNameToString($param, true);
        !          74357:                 }
        !          74358: 
        !          74359:                 if (!isset($options['soft'])) {
        !          74360:                     $this->_downloader->log(2, "Cannot initialize '$param', invalid or missing package file");
        !          74361:                 }
        !          74362: 
        !          74363:                 // Passing no message back - already logged above
        !          74364:                 return PEAR::raiseError();
        !          74365:             }
        !          74366:         }
        !          74367: 
        !          74368:         return true;
        !          74369:     }
        !          74370: 
        !          74371:     /**
        !          74372:      * Retrieve any non-local packages
        !          74373:      * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|PEAR_Error
        !          74374:      */
        !          74375:     function &download()
        !          74376:     {
        !          74377:         if (isset($this->_packagefile)) {
        !          74378:             return $this->_packagefile;
        !          74379:         }
        !          74380: 
        !          74381:         if (isset($this->_downloadURL['url'])) {
        !          74382:             $this->_isvalid = false;
        !          74383:             $info = $this->getParsedPackage();
        !          74384:             foreach ($info as $i => $p) {
        !          74385:                 $info[$i] = strtolower($p);
        !          74386:             }
        !          74387: 
        !          74388:             $err = $this->_fromUrl($this->_downloadURL['url'],
        !          74389:                 $this->_registry->parsedPackageNameToString($this->_parsedname, true));
        !          74390:             $newinfo = $this->getParsedPackage();
        !          74391:             foreach ($newinfo as $i => $p) {
        !          74392:                 $newinfo[$i] = strtolower($p);
        !          74393:             }
        !          74394: 
        !          74395:             if ($info != $newinfo) {
        !          74396:                 do {
        !          74397:                     if ($info['channel'] == 'pecl.php.net' && $newinfo['channel'] == 'pear.php.net') {
        !          74398:                         $info['channel'] = 'pear.php.net';
        !          74399:                         if ($info == $newinfo) {
        !          74400:                             // skip the channel check if a pecl package says it's a PEAR package
        !          74401:                             break;
        !          74402:                         }
        !          74403:                     }
        !          74404:                     if ($info['channel'] == 'pear.php.net' && $newinfo['channel'] == 'pecl.php.net') {
        !          74405:                         $info['channel'] = 'pecl.php.net';
        !          74406:                         if ($info == $newinfo) {
        !          74407:                             // skip the channel check if a pecl package says it's a PEAR package
        !          74408:                             break;
        !          74409:                         }
        !          74410:                     }
        !          74411: 
        !          74412:                     return PEAR::raiseError('CRITICAL ERROR: We are ' .
        !          74413:                         $this->_registry->parsedPackageNameToString($info) . ', but the file ' .
        !          74414:                         'downloaded claims to be ' .
        !          74415:                         $this->_registry->parsedPackageNameToString($this->getParsedPackage()));
        !          74416:                 } while (false);
        !          74417:             }
        !          74418: 
        !          74419:             if (PEAR::isError($err) || !$this->_valid) {
        !          74420:                 return $err;
        !          74421:             }
        !          74422:         }
        !          74423: 
        !          74424:         $this->_type = 'local';
        !          74425:         return $this->_packagefile;
        !          74426:     }
        !          74427: 
        !          74428:     function &getPackageFile()
        !          74429:     {
        !          74430:         return $this->_packagefile;
        !          74431:     }
1.1       misho    74432: 
1.1.1.2 ! misho    74433:     function &getDownloader()
        !          74434:     {
        !          74435:         return $this->_downloader;
        !          74436:     }
        !          74437: 
        !          74438:     function getType()
        !          74439:     {
        !          74440:         return $this->_type;
        !          74441:     }
1.1       misho    74442: 
                   74443:     /**
1.1.1.2 ! misho    74444:      * Like {@link initialize()}, but operates on a dependency
1.1       misho    74445:      */
1.1.1.2 ! misho    74446:     function fromDepURL($dep)
1.1       misho    74447:     {
1.1.1.2 ! misho    74448:         $this->_downloadURL = $dep;
        !          74449:         if (isset($dep['uri'])) {
        !          74450:             $options = $this->_downloader->getOptions();
        !          74451:             if (!extension_loaded("zlib") || isset($options['nocompress'])) {
        !          74452:                 $ext = '.tar';
        !          74453:             } else {
        !          74454:                 $ext = '.tgz';
        !          74455:             }
        !          74456: 
        !          74457:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          74458:             $err = $this->_fromUrl($dep['uri'] . $ext);
        !          74459:             PEAR::popErrorHandling();
        !          74460:             if (PEAR::isError($err)) {
        !          74461:                 if (!isset($options['soft'])) {
        !          74462:                     $this->_downloader->log(0, $err->getMessage());
        !          74463:                 }
        !          74464: 
        !          74465:                 return PEAR::raiseError('Invalid uri dependency "' . $dep['uri'] . $ext . '", ' .
        !          74466:                     'cannot download');
        !          74467:             }
        !          74468:         } else {
        !          74469:             $this->_parsedname =
        !          74470:                 array(
        !          74471:                     'package' => $dep['info']->getPackage(),
        !          74472:                     'channel' => $dep['info']->getChannel(),
        !          74473:                     'version' => $dep['version']
        !          74474:                 );
        !          74475:             if (!isset($dep['nodefault'])) {
        !          74476:                 $this->_parsedname['group'] = 'default'; // download the default dependency group
        !          74477:                 $this->_explicitGroup = false;
1.1       misho    74478:             }
1.1.1.2 ! misho    74479: 
        !          74480:             $this->_rawpackagefile = $dep['raw'];
1.1       misho    74481:         }
1.1.1.2 ! misho    74482:     }
1.1       misho    74483: 
1.1.1.2 ! misho    74484:     function detectDependencies($params)
        !          74485:     {
        !          74486:         $options = $this->_downloader->getOptions();
        !          74487:         if (isset($options['downloadonly'])) {
        !          74488:             return;
        !          74489:         }
        !          74490: 
        !          74491:         if (isset($options['offline'])) {
        !          74492:             $this->_downloader->log(3, 'Skipping dependency download check, --offline specified');
        !          74493:             return;
        !          74494:         }
        !          74495: 
        !          74496:         $pname = $this->getParsedPackage();
        !          74497:         if (!$pname) {
        !          74498:             return;
        !          74499:         }
        !          74500: 
        !          74501:         $deps = $this->getDeps();
        !          74502:         if (!$deps) {
        !          74503:             return;
        !          74504:         }
        !          74505: 
        !          74506:         if (isset($deps['required'])) { // package.xml 2.0
        !          74507:             return $this->_detect2($deps, $pname, $options, $params);
        !          74508:         }
        !          74509: 
        !          74510:         return $this->_detect1($deps, $pname, $options, $params);
        !          74511:     }
        !          74512: 
        !          74513:     function setValidated()
        !          74514:     {
        !          74515:         $this->_validated = true;
        !          74516:     }
        !          74517: 
        !          74518:     function alreadyValidated()
        !          74519:     {
        !          74520:         return $this->_validated;
1.1       misho    74521:     }
                   74522: 
                   74523:     /**
1.1.1.2 ! misho    74524:      * Remove packages to be downloaded that are already installed
        !          74525:      * @param array of PEAR_Downloader_Package objects
        !          74526:      * @static
1.1       misho    74527:      */
1.1.1.2 ! misho    74528:     function removeInstalled(&$params)
1.1       misho    74529:     {
1.1.1.2 ! misho    74530:         if (!isset($params[0])) {
        !          74531:             return;
1.1       misho    74532:         }
                   74533: 
1.1.1.2 ! misho    74534:         $options = $params[0]->_downloader->getOptions();
        !          74535:         if (!isset($options['downloadonly'])) {
        !          74536:             foreach ($params as $i => $param) {
        !          74537:                 $package = $param->getPackage();
        !          74538:                 $channel = $param->getChannel();
        !          74539:                 // remove self if already installed with this version
        !          74540:                 // this does not need any pecl magic - we only remove exact matches
        !          74541:                 if ($param->_installRegistry->packageExists($package, $channel)) {
        !          74542:                     $packageVersion = $param->_installRegistry->packageInfo($package, 'version', $channel);
        !          74543:                     if (version_compare($packageVersion, $param->getVersion(), '==')) {
        !          74544:                         if (!isset($options['force'])) {
        !          74545:                             $info = $param->getParsedPackage();
        !          74546:                             unset($info['version']);
        !          74547:                             unset($info['state']);
        !          74548:                             if (!isset($options['soft'])) {
        !          74549:                                 $param->_downloader->log(1, 'Skipping package "' .
        !          74550:                                     $param->getShortName() .
        !          74551:                                     '", already installed as version ' . $packageVersion);
        !          74552:                             }
        !          74553:                             $params[$i] = false;
        !          74554:                         }
        !          74555:                     } elseif (!isset($options['force']) && !isset($options['upgrade']) &&
        !          74556:                           !isset($options['soft'])) {
        !          74557:                         $info = $param->getParsedPackage();
        !          74558:                         $param->_downloader->log(1, 'Skipping package "' .
        !          74559:                             $param->getShortName() .
        !          74560:                             '", already installed as version ' . $packageVersion);
        !          74561:                         $params[$i] = false;
        !          74562:                     }
        !          74563:                 }
        !          74564:             }
1.1       misho    74565:         }
                   74566: 
1.1.1.2 ! misho    74567:         PEAR_Downloader_Package::removeDuplicates($params);
1.1       misho    74568:     }
                   74569: 
1.1.1.2 ! misho    74570:     function _detect2($deps, $pname, $options, $params)
1.1       misho    74571:     {
1.1.1.2 ! misho    74572:         $this->_downloadDeps = array();
        !          74573:         $groupnotfound = false;
        !          74574:         foreach (array('package', 'subpackage') as $packagetype) {
        !          74575:             // get required dependency group
        !          74576:             if (isset($deps['required'][$packagetype])) {
        !          74577:                 if (isset($deps['required'][$packagetype][0])) {
        !          74578:                     foreach ($deps['required'][$packagetype] as $dep) {
        !          74579:                         if (isset($dep['conflicts'])) {
        !          74580:                             // skip any package that this package conflicts with
        !          74581:                             continue;
        !          74582:                         }
        !          74583:                         $ret = $this->_detect2Dep($dep, $pname, 'required', $params);
        !          74584:                         if (is_array($ret)) {
        !          74585:                             $this->_downloadDeps[] = $ret;
        !          74586:                         } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
        !          74587:                             $this->_downloader->log(0, $ret->getMessage());
        !          74588:                         }
        !          74589:                     }
        !          74590:                 } else {
        !          74591:                     $dep = $deps['required'][$packagetype];
        !          74592:                     if (!isset($dep['conflicts'])) {
        !          74593:                         // skip any package that this package conflicts with
        !          74594:                         $ret = $this->_detect2Dep($dep, $pname, 'required', $params);
        !          74595:                         if (is_array($ret)) {
        !          74596:                             $this->_downloadDeps[] = $ret;
        !          74597:                         } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
        !          74598:                             $this->_downloader->log(0, $ret->getMessage());
        !          74599:                         }
1.1       misho    74600:                     }
1.1.1.2 ! misho    74601:                 }
        !          74602:             }
1.1       misho    74603: 
1.1.1.2 ! misho    74604:             // get optional dependency group, if any
        !          74605:             if (isset($deps['optional'][$packagetype])) {
        !          74606:                 $skipnames = array();
        !          74607:                 if (!isset($deps['optional'][$packagetype][0])) {
        !          74608:                     $deps['optional'][$packagetype] = array($deps['optional'][$packagetype]);
        !          74609:                 }
        !          74610: 
        !          74611:                 foreach ($deps['optional'][$packagetype] as $dep) {
        !          74612:                     $skip = false;
        !          74613:                     if (!isset($options['alldeps'])) {
        !          74614:                         $dep['package'] = $dep['name'];
        !          74615:                         if (!isset($options['soft'])) {
        !          74616:                             $this->_downloader->log(3, 'Notice: package "' .
        !          74617:                               $this->_registry->parsedPackageNameToString($this->getParsedPackage(),
        !          74618:                                     true) . '" optional dependency "' .
        !          74619:                                 $this->_registry->parsedPackageNameToString(array('package' =>
        !          74620:                                     $dep['name'], 'channel' => 'pear.php.net'), true) .
        !          74621:                                 '" will not be automatically downloaded');
        !          74622:                         }
        !          74623:                         $skipnames[] = $this->_registry->parsedPackageNameToString($dep, true);
        !          74624:                         $skip = true;
        !          74625:                         unset($dep['package']);
        !          74626:                     }
        !          74627: 
        !          74628:                     $ret = $this->_detect2Dep($dep, $pname, 'optional', $params);
        !          74629:                     if (PEAR::isError($ret) && !isset($options['soft'])) {
        !          74630:                         $this->_downloader->log(0, $ret->getMessage());
        !          74631:                     }
        !          74632: 
        !          74633:                     if (!$ret) {
        !          74634:                         $dep['package'] = $dep['name'];
        !          74635:                         $skip = count($skipnames) ?
        !          74636:                             $skipnames[count($skipnames) - 1] : '';
        !          74637:                         if ($skip ==
        !          74638:                               $this->_registry->parsedPackageNameToString($dep, true)) {
        !          74639:                             array_pop($skipnames);
        !          74640:                         }
        !          74641:                     }
        !          74642: 
        !          74643:                     if (!$skip && is_array($ret)) {
        !          74644:                         $this->_downloadDeps[] = $ret;
        !          74645:                     }
        !          74646:                 }
        !          74647: 
        !          74648:                 if (count($skipnames)) {
        !          74649:                     if (!isset($options['soft'])) {
        !          74650:                         $this->_downloader->log(1, 'Did not download optional dependencies: ' .
        !          74651:                             implode(', ', $skipnames) .
        !          74652:                             ', use --alldeps to download automatically');
        !          74653:                     }
1.1       misho    74654:                 }
                   74655:             }
                   74656: 
1.1.1.2 ! misho    74657:             // get requested dependency group, if any
        !          74658:             $groupname = $this->getGroup();
        !          74659:             $explicit  = $this->_explicitGroup;
        !          74660:             if (!$groupname) {
        !          74661:                 if (!$this->canDefault()) {
        !          74662:                     continue;
        !          74663:                 }
1.1       misho    74664: 
1.1.1.2 ! misho    74665:                 $groupname = 'default'; // try the default dependency group
        !          74666:             }
1.1       misho    74667: 
1.1.1.2 ! misho    74668:             if ($groupnotfound) {
        !          74669:                 continue;
        !          74670:             }
1.1       misho    74671: 
1.1.1.2 ! misho    74672:             if (isset($deps['group'])) {
        !          74673:                 if (isset($deps['group']['attribs'])) {
        !          74674:                     if (strtolower($deps['group']['attribs']['name']) == strtolower($groupname)) {
        !          74675:                         $group = $deps['group'];
        !          74676:                     } elseif ($explicit) {
        !          74677:                         if (!isset($options['soft'])) {
        !          74678:                             $this->_downloader->log(0, 'Warning: package "' .
        !          74679:                                 $this->_registry->parsedPackageNameToString($pname, true) .
        !          74680:                                 '" has no dependency ' . 'group named "' . $groupname . '"');
        !          74681:                         }
        !          74682: 
        !          74683:                         $groupnotfound = true;
        !          74684:                         continue;
        !          74685:                     }
        !          74686:                 } else {
        !          74687:                     $found = false;
        !          74688:                     foreach ($deps['group'] as $group) {
        !          74689:                         if (strtolower($group['attribs']['name']) == strtolower($groupname)) {
        !          74690:                             $found = true;
        !          74691:                             break;
        !          74692:                         }
        !          74693:                     }
        !          74694: 
        !          74695:                     if (!$found) {
        !          74696:                         if ($explicit) {
        !          74697:                             if (!isset($options['soft'])) {
        !          74698:                                 $this->_downloader->log(0, 'Warning: package "' .
        !          74699:                                     $this->_registry->parsedPackageNameToString($pname, true) .
        !          74700:                                     '" has no dependency ' . 'group named "' . $groupname . '"');
        !          74701:                             }
        !          74702:                         }
        !          74703: 
        !          74704:                         $groupnotfound = true;
        !          74705:                         continue;
        !          74706:                     }
        !          74707:                 }
        !          74708:             }
        !          74709: 
        !          74710:             if (isset($group) && isset($group[$packagetype])) {
        !          74711:                 if (isset($group[$packagetype][0])) {
        !          74712:                     foreach ($group[$packagetype] as $dep) {
        !          74713:                         $ret = $this->_detect2Dep($dep, $pname, 'dependency group "' .
        !          74714:                             $group['attribs']['name'] . '"', $params);
        !          74715:                         if (is_array($ret)) {
        !          74716:                             $this->_downloadDeps[] = $ret;
        !          74717:                         } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
        !          74718:                             $this->_downloader->log(0, $ret->getMessage());
        !          74719:                         }
        !          74720:                     }
        !          74721:                 } else {
        !          74722:                     $ret = $this->_detect2Dep($group[$packagetype], $pname,
        !          74723:                         'dependency group "' .
        !          74724:                         $group['attribs']['name'] . '"', $params);
        !          74725:                     if (is_array($ret)) {
        !          74726:                         $this->_downloadDeps[] = $ret;
        !          74727:                     } elseif (PEAR::isError($ret) && !isset($options['soft'])) {
        !          74728:                         $this->_downloader->log(0, $ret->getMessage());
        !          74729:                     }
        !          74730:                 }
        !          74731:             }
        !          74732:         }
        !          74733:     }
        !          74734: 
        !          74735:     function _detect2Dep($dep, $pname, $group, $params)
1.1       misho    74736:     {
1.1.1.2 ! misho    74737:         if (isset($dep['conflicts'])) {
        !          74738:             return true;
1.1       misho    74739:         }
                   74740: 
1.1.1.2 ! misho    74741:         $options = $this->_downloader->getOptions();
        !          74742:         if (isset($dep['uri'])) {
        !          74743:             return array('uri' => $dep['uri'], 'dep' => $dep);;
1.1       misho    74744:         }
                   74745: 
1.1.1.2 ! misho    74746:         $testdep = $dep;
        !          74747:         $testdep['package'] = $dep['name'];
        !          74748:         if (PEAR_Downloader_Package::willDownload($testdep, $params)) {
        !          74749:             $dep['package'] = $dep['name'];
        !          74750:             if (!isset($options['soft'])) {
        !          74751:                 $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group .
        !          74752:                     ' dependency "' .
        !          74753:                     $this->_registry->parsedPackageNameToString($dep, true) .
        !          74754:                     '", will be installed');
        !          74755:             }
        !          74756:             return false;
1.1       misho    74757:         }
                   74758: 
1.1.1.2 ! misho    74759:         $options = $this->_downloader->getOptions();
        !          74760:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          74761:         if ($this->_explicitState) {
        !          74762:             $pname['state'] = $this->_explicitState;
1.1       misho    74763:         }
                   74764: 
1.1.1.2 ! misho    74765:         $url = $this->_downloader->_getDepPackageDownloadUrl($dep, $pname);
        !          74766:         if (PEAR::isError($url)) {
        !          74767:             PEAR::popErrorHandling();
        !          74768:             return $url;
1.1       misho    74769:         }
                   74770: 
1.1.1.2 ! misho    74771:         $dep['package'] = $dep['name'];
        !          74772:         $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params, $group == 'optional' &&
        !          74773:             !isset($options['alldeps']), true);
        !          74774:         PEAR::popErrorHandling();
        !          74775:         if (PEAR::isError($ret)) {
        !          74776:             if (!isset($options['soft'])) {
        !          74777:                 $this->_downloader->log(0, $ret->getMessage());
        !          74778:             }
1.1       misho    74779: 
1.1.1.2 ! misho    74780:             return false;
        !          74781:         }
        !          74782: 
        !          74783:         // check to see if a dep is already installed and is the same or newer
        !          74784:         if (!isset($dep['min']) && !isset($dep['max']) && !isset($dep['recommended'])) {
        !          74785:             $oper = 'has';
1.1       misho    74786:         } else {
1.1.1.2 ! misho    74787:             $oper = 'gt';
1.1       misho    74788:         }
                   74789: 
1.1.1.2 ! misho    74790:         // do not try to move this before getDepPackageDownloadURL
        !          74791:         // we can't determine whether upgrade is necessary until we know what
        !          74792:         // version would be downloaded
        !          74793:         if (!isset($options['force']) && $this->isInstalled($ret, $oper)) {
        !          74794:             $version = $this->_installRegistry->packageInfo($dep['name'], 'version', $dep['channel']);
        !          74795:             $dep['package'] = $dep['name'];
        !          74796:             if (!isset($options['soft'])) {
        !          74797:                 $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group .
        !          74798:                     ' dependency "' .
        !          74799:                 $this->_registry->parsedPackageNameToString($dep, true) .
        !          74800:                     '" version ' . $url['version'] . ', already installed as version ' .
        !          74801:                     $version);
        !          74802:             }
        !          74803: 
1.1       misho    74804:             return false;
                   74805:         }
                   74806: 
1.1.1.2 ! misho    74807:         if (isset($dep['nodefault'])) {
        !          74808:             $ret['nodefault'] = true;
        !          74809:         }
        !          74810: 
        !          74811:         return $ret;
        !          74812:     }
        !          74813: 
        !          74814:     function _detect1($deps, $pname, $options, $params)
        !          74815:     {
        !          74816:         $this->_downloadDeps = array();
        !          74817:         $skipnames = array();
        !          74818:         foreach ($deps as $dep) {
        !          74819:             $nodownload = false;
        !          74820:             if (isset ($dep['type']) && $dep['type'] === 'pkg') {
        !          74821:                 $dep['channel'] = 'pear.php.net';
        !          74822:                 $dep['package'] = $dep['name'];
        !          74823:                 switch ($dep['rel']) {
        !          74824:                     case 'not' :
        !          74825:                         continue 2;
        !          74826:                     case 'ge' :
        !          74827:                     case 'eq' :
        !          74828:                     case 'gt' :
        !          74829:                     case 'has' :
        !          74830:                         $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
        !          74831:                             'required' :
        !          74832:                             'optional';
        !          74833:                         if (PEAR_Downloader_Package::willDownload($dep, $params)) {
        !          74834:                             $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group
        !          74835:                                 . ' dependency "' .
        !          74836:                                 $this->_registry->parsedPackageNameToString($dep, true) .
        !          74837:                                 '", will be installed');
        !          74838:                             continue 2;
        !          74839:                         }
        !          74840:                         $fakedp = new PEAR_PackageFile_v1;
        !          74841:                         $fakedp->setPackage($dep['name']);
        !          74842:                         // skip internet check if we are not upgrading (bug #5810)
        !          74843:                         if (!isset($options['upgrade']) && $this->isInstalled(
        !          74844:                               $fakedp, $dep['rel'])) {
        !          74845:                             $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group
        !          74846:                                 . ' dependency "' .
        !          74847:                                 $this->_registry->parsedPackageNameToString($dep, true) .
        !          74848:                                 '", is already installed');
        !          74849:                             continue 2;
        !          74850:                         }
        !          74851:                 }
        !          74852: 
        !          74853:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          74854:                 if ($this->_explicitState) {
        !          74855:                     $pname['state'] = $this->_explicitState;
        !          74856:                 }
        !          74857: 
        !          74858:                 $url = $this->_downloader->_getDepPackageDownloadUrl($dep, $pname);
        !          74859:                 $chan = 'pear.php.net';
        !          74860:                 if (PEAR::isError($url)) {
        !          74861:                     // check to see if this is a pecl package that has jumped
        !          74862:                     // from pear.php.net to pecl.php.net channel
        !          74863:                     if (!class_exists('PEAR_Dependency2')) {
        !          74864:                         require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Dependency2.php';
        !          74865:                     }
        !          74866: 
        !          74867:                     $newdep = PEAR_Dependency2::normalizeDep($dep);
        !          74868:                     $newdep = $newdep[0];
        !          74869:                     $newdep['channel'] = 'pecl.php.net';
        !          74870:                     $chan = 'pecl.php.net';
        !          74871:                     $url = $this->_downloader->_getDepPackageDownloadUrl($newdep, $pname);
        !          74872:                     $obj = &$this->_installRegistry->getPackage($dep['name']);
        !          74873:                     if (PEAR::isError($url)) {
        !          74874:                         PEAR::popErrorHandling();
        !          74875:                         if ($obj !== null && $this->isInstalled($obj, $dep['rel'])) {
        !          74876:                             $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
        !          74877:                                 'required' :
        !          74878:                                 'optional';
        !          74879:                             $dep['package'] = $dep['name'];
        !          74880:                             if (!isset($options['soft'])) {
        !          74881:                                 $this->_downloader->log(3, $this->getShortName() .
        !          74882:                                     ': Skipping ' . $group . ' dependency "' .
        !          74883:                                     $this->_registry->parsedPackageNameToString($dep, true) .
        !          74884:                                     '", already installed as version ' . $obj->getVersion());
        !          74885:                             }
        !          74886:                             $skip = count($skipnames) ?
        !          74887:                                 $skipnames[count($skipnames) - 1] : '';
        !          74888:                             if ($skip ==
        !          74889:                                   $this->_registry->parsedPackageNameToString($dep, true)) {
        !          74890:                                 array_pop($skipnames);
        !          74891:                             }
        !          74892:                             continue;
        !          74893:                         } else {
        !          74894:                             if (isset($dep['optional']) && $dep['optional'] == 'yes') {
        !          74895:                                 $this->_downloader->log(2, $this->getShortName() .
        !          74896:                                     ': Skipping optional dependency "' .
        !          74897:                                     $this->_registry->parsedPackageNameToString($dep, true) .
        !          74898:                                     '", no releases exist');
        !          74899:                                 continue;
        !          74900:                             } else {
        !          74901:                                 return $url;
        !          74902:                             }
        !          74903:                         }
1.1       misho    74904:                     }
1.1.1.2 ! misho    74905:                 }
1.1       misho    74906: 
1.1.1.2 ! misho    74907:                 PEAR::popErrorHandling();
        !          74908:                 if (!isset($options['alldeps'])) {
        !          74909:                     if (isset($dep['optional']) && $dep['optional'] == 'yes') {
        !          74910:                         if (!isset($options['soft'])) {
        !          74911:                             $this->_downloader->log(3, 'Notice: package "' .
        !          74912:                                 $this->getShortName() .
        !          74913:                                 '" optional dependency "' .
        !          74914:                                 $this->_registry->parsedPackageNameToString(
        !          74915:                                     array('channel' => $chan, 'package' =>
        !          74916:                                     $dep['name']), true) .
        !          74917:                                 '" will not be automatically downloaded');
        !          74918:                         }
        !          74919:                         $skipnames[] = $this->_registry->parsedPackageNameToString(
        !          74920:                                 array('channel' => $chan, 'package' =>
        !          74921:                                 $dep['name']), true);
        !          74922:                         $nodownload = true;
1.1       misho    74923:                     }
                   74924:                 }
                   74925: 
1.1.1.2 ! misho    74926:                 if (!isset($options['alldeps']) && !isset($options['onlyreqdeps'])) {
        !          74927:                     if (!isset($dep['optional']) || $dep['optional'] == 'no') {
        !          74928:                         if (!isset($options['soft'])) {
        !          74929:                             $this->_downloader->log(3, 'Notice: package "' .
        !          74930:                                 $this->getShortName() .
        !          74931:                                 '" required dependency "' .
        !          74932:                                 $this->_registry->parsedPackageNameToString(
        !          74933:                                     array('channel' => $chan, 'package' =>
        !          74934:                                     $dep['name']), true) .
        !          74935:                                 '" will not be automatically downloaded');
        !          74936:                         }
        !          74937:                         $skipnames[] = $this->_registry->parsedPackageNameToString(
        !          74938:                                 array('channel' => $chan, 'package' =>
        !          74939:                                 $dep['name']), true);
        !          74940:                         $nodownload = true;
        !          74941:                     }
        !          74942:                 }
1.1       misho    74943: 
1.1.1.2 ! misho    74944:                 // check to see if a dep is already installed
        !          74945:                 // do not try to move this before getDepPackageDownloadURL
        !          74946:                 // we can't determine whether upgrade is necessary until we know what
        !          74947:                 // version would be downloaded
        !          74948:                 if (!isset($options['force']) && $this->isInstalled(
        !          74949:                         $url, $dep['rel'])) {
        !          74950:                     $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
        !          74951:                         'required' :
        !          74952:                         'optional';
        !          74953:                     $dep['package'] = $dep['name'];
        !          74954:                     if (isset($newdep)) {
        !          74955:                         $version = $this->_installRegistry->packageInfo($newdep['name'], 'version', $newdep['channel']);
        !          74956:                     } else {
        !          74957:                         $version = $this->_installRegistry->packageInfo($dep['name'], 'version');
        !          74958:                     }
1.1       misho    74959: 
1.1.1.2 ! misho    74960:                     $dep['version'] = $url['version'];
        !          74961:                     if (!isset($options['soft'])) {
        !          74962:                         $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group .
        !          74963:                             ' dependency "' .
        !          74964:                             $this->_registry->parsedPackageNameToString($dep, true) .
        !          74965:                             '", already installed as version ' . $version);
        !          74966:                     }
1.1       misho    74967: 
1.1.1.2 ! misho    74968:                     $skip = count($skipnames) ?
        !          74969:                         $skipnames[count($skipnames) - 1] : '';
        !          74970:                     if ($skip ==
        !          74971:                           $this->_registry->parsedPackageNameToString($dep, true)) {
        !          74972:                         array_pop($skipnames);
        !          74973:                     }
1.1       misho    74974: 
1.1.1.2 ! misho    74975:                     continue;
        !          74976:                 }
1.1       misho    74977: 
1.1.1.2 ! misho    74978:                 if ($nodownload) {
        !          74979:                     continue;
        !          74980:                 }
1.1       misho    74981: 
1.1.1.2 ! misho    74982:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          74983:                 if (isset($newdep)) {
        !          74984:                     $dep = $newdep;
        !          74985:                 }
1.1       misho    74986: 
1.1.1.2 ! misho    74987:                 $dep['package'] = $dep['name'];
        !          74988:                 $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params,
        !          74989:                     isset($dep['optional']) && $dep['optional'] == 'yes' &&
        !          74990:                     !isset($options['alldeps']), true);
        !          74991:                 PEAR::popErrorHandling();
        !          74992:                 if (PEAR::isError($ret)) {
        !          74993:                     if (!isset($options['soft'])) {
        !          74994:                         $this->_downloader->log(0, $ret->getMessage());
1.1       misho    74995:                     }
1.1.1.2 ! misho    74996:                     continue;
1.1       misho    74997:                 }
                   74998: 
1.1.1.2 ! misho    74999:                 $this->_downloadDeps[] = $ret;
1.1       misho    75000:             }
                   75001:         }
                   75002: 
1.1.1.2 ! misho    75003:         if (count($skipnames)) {
        !          75004:             if (!isset($options['soft'])) {
        !          75005:                 $this->_downloader->log(1, 'Did not download dependencies: ' .
        !          75006:                     implode(', ', $skipnames) .
        !          75007:                     ', use --alldeps or --onlyreqdeps to download automatically');
1.1       misho    75008:             }
                   75009:         }
                   75010:     }
                   75011: 
1.1.1.2 ! misho    75012:     function setDownloadURL($pkg)
1.1       misho    75013:     {
1.1.1.2 ! misho    75014:         $this->_downloadURL = $pkg;
1.1       misho    75015:     }
                   75016: 
                   75017:     /**
1.1.1.2 ! misho    75018:      * Set the package.xml object for this downloaded package
1.1       misho    75019:      *
1.1.1.2 ! misho    75020:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 $pkg
1.1       misho    75021:      */
1.1.1.2 ! misho    75022:     function setPackageFile(&$pkg)
1.1       misho    75023:     {
1.1.1.2 ! misho    75024:         $this->_packagefile = &$pkg;
        !          75025:     }
1.1       misho    75026: 
1.1.1.2 ! misho    75027:     function getShortName()
        !          75028:     {
        !          75029:         return $this->_registry->parsedPackageNameToString(array('channel' => $this->getChannel(),
        !          75030:             'package' => $this->getPackage()), true);
        !          75031:     }
1.1       misho    75032: 
1.1.1.2 ! misho    75033:     function getParsedPackage()
        !          75034:     {
        !          75035:         if (isset($this->_packagefile) || isset($this->_parsedname)) {
        !          75036:             return array('channel' => $this->getChannel(),
        !          75037:                 'package' => $this->getPackage(),
        !          75038:                 'version' => $this->getVersion());
1.1       misho    75039:         }
                   75040: 
1.1.1.2 ! misho    75041:         return false;
1.1       misho    75042:     }
                   75043: 
1.1.1.2 ! misho    75044:     function getDownloadURL()
1.1       misho    75045:     {
1.1.1.2 ! misho    75046:         return $this->_downloadURL;
        !          75047:     }
1.1       misho    75048: 
1.1.1.2 ! misho    75049:     function canDefault()
        !          75050:     {
        !          75051:         if (isset($this->_downloadURL) && isset($this->_downloadURL['nodefault'])) {
        !          75052:             return false;
1.1       misho    75053:         }
                   75054: 
1.1.1.2 ! misho    75055:         return true;
        !          75056:     }
1.1       misho    75057: 
1.1.1.2 ! misho    75058:     function getPackage()
        !          75059:     {
        !          75060:         if (isset($this->_packagefile)) {
        !          75061:             return $this->_packagefile->getPackage();
        !          75062:         } elseif (isset($this->_downloadURL['info'])) {
        !          75063:             return $this->_downloadURL['info']->getPackage();
1.1       misho    75064:         }
                   75065: 
1.1.1.2 ! misho    75066:         return false;
1.1       misho    75067:     }
                   75068: 
                   75069:     /**
1.1.1.2 ! misho    75070:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
1.1       misho    75071:      */
1.1.1.2 ! misho    75072:     function isSubpackage(&$pf)
1.1       misho    75073:     {
1.1.1.2 ! misho    75074:         if (isset($this->_packagefile)) {
        !          75075:             return $this->_packagefile->isSubpackage($pf);
        !          75076:         } elseif (isset($this->_downloadURL['info'])) {
        !          75077:             return $this->_downloadURL['info']->isSubpackage($pf);
1.1       misho    75078:         }
                   75079: 
1.1.1.2 ! misho    75080:         return false;
        !          75081:     }
1.1       misho    75082: 
1.1.1.2 ! misho    75083:     function getPackageType()
        !          75084:     {
        !          75085:         if (isset($this->_packagefile)) {
        !          75086:             return $this->_packagefile->getPackageType();
        !          75087:         } elseif (isset($this->_downloadURL['info'])) {
        !          75088:             return $this->_downloadURL['info']->getPackageType();
1.1       misho    75089:         }
                   75090: 
1.1.1.2 ! misho    75091:         return false;
        !          75092:     }
1.1       misho    75093: 
1.1.1.2 ! misho    75094:     function isBundle()
        !          75095:     {
        !          75096:         if (isset($this->_packagefile)) {
        !          75097:             return $this->_packagefile->getPackageType() == 'bundle';
1.1       misho    75098:         }
                   75099: 
1.1.1.2 ! misho    75100:         return false;
        !          75101:     }
1.1       misho    75102: 
1.1.1.2 ! misho    75103:     function getPackageXmlVersion()
        !          75104:     {
        !          75105:         if (isset($this->_packagefile)) {
        !          75106:             return $this->_packagefile->getPackagexmlVersion();
        !          75107:         } elseif (isset($this->_downloadURL['info'])) {
        !          75108:             return $this->_downloadURL['info']->getPackagexmlVersion();
1.1       misho    75109:         }
                   75110: 
1.1.1.2 ! misho    75111:         return '1.0';
1.1       misho    75112:     }
                   75113: 
1.1.1.2 ! misho    75114:     function getChannel()
1.1       misho    75115:     {
1.1.1.2 ! misho    75116:         if (isset($this->_packagefile)) {
        !          75117:             return $this->_packagefile->getChannel();
        !          75118:         } elseif (isset($this->_downloadURL['info'])) {
        !          75119:             return $this->_downloadURL['info']->getChannel();
1.1       misho    75120:         }
1.1.1.2 ! misho    75121: 
        !          75122:         return false;
1.1       misho    75123:     }
                   75124: 
1.1.1.2 ! misho    75125:     function getURI()
1.1       misho    75126:     {
1.1.1.2 ! misho    75127:         if (isset($this->_packagefile)) {
        !          75128:             return $this->_packagefile->getURI();
        !          75129:         } elseif (isset($this->_downloadURL['info'])) {
        !          75130:             return $this->_downloadURL['info']->getURI();
1.1       misho    75131:         }
                   75132: 
1.1.1.2 ! misho    75133:         return false;
        !          75134:     }
1.1       misho    75135: 
1.1.1.2 ! misho    75136:     function getVersion()
        !          75137:     {
        !          75138:         if (isset($this->_packagefile)) {
        !          75139:             return $this->_packagefile->getVersion();
        !          75140:         } elseif (isset($this->_downloadURL['version'])) {
        !          75141:             return $this->_downloadURL['version'];
1.1       misho    75142:         }
                   75143: 
1.1.1.2 ! misho    75144:         return false;
1.1       misho    75145:     }
                   75146: 
1.1.1.2 ! misho    75147:     function isCompatible($pf)
1.1       misho    75148:     {
1.1.1.2 ! misho    75149:         if (isset($this->_packagefile)) {
        !          75150:             return $this->_packagefile->isCompatible($pf);
        !          75151:         } elseif (isset($this->_downloadURL['info'])) {
        !          75152:             return $this->_downloadURL['info']->isCompatible($pf);
1.1       misho    75153:         }
                   75154: 
                   75155:         return true;
                   75156:     }
                   75157: 
1.1.1.2 ! misho    75158:     function setGroup($group)
1.1       misho    75159:     {
1.1.1.2 ! misho    75160:         $this->_parsedname['group'] = $group;
        !          75161:     }
1.1       misho    75162: 
1.1.1.2 ! misho    75163:     function getGroup()
        !          75164:     {
        !          75165:         if (isset($this->_parsedname['group'])) {
        !          75166:             return $this->_parsedname['group'];
1.1       misho    75167:         }
                   75168: 
1.1.1.2 ! misho    75169:         return '';
        !          75170:     }
1.1       misho    75171: 
1.1.1.2 ! misho    75172:     function isExtension($name)
        !          75173:     {
        !          75174:         if (isset($this->_packagefile)) {
        !          75175:             return $this->_packagefile->isExtension($name);
        !          75176:         } elseif (isset($this->_downloadURL['info'])) {
        !          75177:             if ($this->_downloadURL['info']->getPackagexmlVersion() == '2.0') {
        !          75178:                 return $this->_downloadURL['info']->getProvidesExtension() == $name;
        !          75179:             }
1.1       misho    75180: 
1.1.1.2 ! misho    75181:             return false;
1.1       misho    75182:         }
                   75183: 
1.1.1.2 ! misho    75184:         return false;
        !          75185:     }
1.1       misho    75186: 
1.1.1.2 ! misho    75187:     function getDeps()
        !          75188:     {
        !          75189:         if (isset($this->_packagefile)) {
        !          75190:             $ver = $this->_packagefile->getPackagexmlVersion();
        !          75191:             if (version_compare($ver, '2.0', '>=')) {
        !          75192:                 return $this->_packagefile->getDeps(true);
1.1       misho    75193:             }
                   75194: 
1.1.1.2 ! misho    75195:             return $this->_packagefile->getDeps();
        !          75196:         } elseif (isset($this->_downloadURL['info'])) {
        !          75197:             $ver = $this->_downloadURL['info']->getPackagexmlVersion();
        !          75198:             if (version_compare($ver, '2.0', '>=')) {
        !          75199:                 return $this->_downloadURL['info']->getDeps(true);
1.1       misho    75200:             }
                   75201: 
1.1.1.2 ! misho    75202:             return $this->_downloadURL['info']->getDeps();
1.1       misho    75203:         }
                   75204: 
1.1.1.2 ! misho    75205:         return array();
        !          75206:     }
1.1       misho    75207: 
1.1.1.2 ! misho    75208:     /**
        !          75209:      * @param array Parsed array from {@link PEAR_Registry::parsePackageName()} or a dependency
        !          75210:      *                     returned from getDepDownloadURL()
        !          75211:      */
        !          75212:     function isEqual($param)
        !          75213:     {
        !          75214:         if (is_object($param)) {
        !          75215:             $channel = $param->getChannel();
        !          75216:             $package = $param->getPackage();
        !          75217:             if ($param->getURI()) {
        !          75218:                 $param = array(
        !          75219:                     'channel' => $param->getChannel(),
        !          75220:                     'package' => $param->getPackage(),
        !          75221:                     'version' => $param->getVersion(),
        !          75222:                     'uri' => $param->getURI(),
        !          75223:                 );
        !          75224:             } else {
        !          75225:                 $param = array(
        !          75226:                     'channel' => $param->getChannel(),
        !          75227:                     'package' => $param->getPackage(),
        !          75228:                     'version' => $param->getVersion(),
        !          75229:                 );
1.1       misho    75230:             }
1.1.1.2 ! misho    75231:         } else {
        !          75232:             if (isset($param['uri'])) {
        !          75233:                 if ($this->getChannel() != '__uri') {
        !          75234:                     return false;
        !          75235:                 }
        !          75236:                 return $param['uri'] == $this->getURI();
1.1       misho    75237:             }
                   75238: 
1.1.1.2 ! misho    75239:             $package = isset($param['package']) ? $param['package'] : $param['info']->getPackage();
        !          75240:             $channel = isset($param['channel']) ? $param['channel'] : $param['info']->getChannel();
        !          75241:             if (isset($param['rel'])) {
        !          75242:                 if (!class_exists('PEAR_Dependency2')) {
        !          75243:                     require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Dependency2.php';
        !          75244:                 }
        !          75245: 
        !          75246:                 $newdep = PEAR_Dependency2::normalizeDep($param);
        !          75247:                 $newdep = $newdep[0];
        !          75248:             } elseif (isset($param['min'])) {
        !          75249:                 $newdep = $param;
1.1       misho    75250:             }
                   75251:         }
                   75252: 
1.1.1.2 ! misho    75253:         if (isset($newdep)) {
        !          75254:             if (!isset($newdep['min'])) {
        !          75255:                 $newdep['min'] = '0';
1.1       misho    75256:             }
                   75257: 
1.1.1.2 ! misho    75258:             if (!isset($newdep['max'])) {
        !          75259:                 $newdep['max'] = '100000000000000000000';
        !          75260:             }
1.1       misho    75261: 
1.1.1.2 ! misho    75262:             // use magic to support pecl packages suddenly jumping to the pecl channel
        !          75263:             // we need to support both dependency possibilities
        !          75264:             if ($channel == 'pear.php.net' && $this->getChannel() == 'pecl.php.net') {
        !          75265:                 if ($package == $this->getPackage()) {
        !          75266:                     $channel = 'pecl.php.net';
1.1       misho    75267:                 }
1.1.1.2 ! misho    75268:             }
        !          75269:             if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') {
        !          75270:                 if ($package == $this->getPackage()) {
        !          75271:                     $channel = 'pear.php.net';
1.1       misho    75272:                 }
                   75273:             }
1.1.1.2 ! misho    75274: 
        !          75275:             return (strtolower($package) == strtolower($this->getPackage()) &&
        !          75276:                 $channel == $this->getChannel() &&
        !          75277:                 version_compare($newdep['min'], $this->getVersion(), '<=') &&
        !          75278:                 version_compare($newdep['max'], $this->getVersion(), '>='));
1.1       misho    75279:         }
                   75280: 
1.1.1.2 ! misho    75281:         // use magic to support pecl packages suddenly jumping to the pecl channel
        !          75282:         if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') {
        !          75283:             if (strtolower($package) == strtolower($this->getPackage())) {
        !          75284:                 $channel = 'pear.php.net';
1.1       misho    75285:             }
                   75286:         }
1.1.1.2 ! misho    75287: 
        !          75288:         if (isset($param['version'])) {
        !          75289:             return (strtolower($package) == strtolower($this->getPackage()) &&
        !          75290:                 $channel == $this->getChannel() &&
        !          75291:                 $param['version'] == $this->getVersion());
        !          75292:         }
        !          75293: 
        !          75294:         return strtolower($package) == strtolower($this->getPackage()) &&
        !          75295:             $channel == $this->getChannel();
1.1       misho    75296:     }
                   75297: 
1.1.1.2 ! misho    75298:     function isInstalled($dep, $oper = '==')
1.1       misho    75299:     {
1.1.1.2 ! misho    75300:         if (!$dep) {
        !          75301:             return false;
1.1       misho    75302:         }
                   75303: 
1.1.1.2 ! misho    75304:         if ($oper != 'ge' && $oper != 'gt' && $oper != 'has' && $oper != '==') {
        !          75305:             return false;
        !          75306:         }
1.1       misho    75307: 
1.1.1.2 ! misho    75308:         if (is_object($dep)) {
        !          75309:             $package = $dep->getPackage();
        !          75310:             $channel = $dep->getChannel();
        !          75311:             if ($dep->getURI()) {
        !          75312:                 $dep = array(
        !          75313:                     'uri' => $dep->getURI(),
        !          75314:                     'version' => $dep->getVersion(),
        !          75315:                 );
        !          75316:             } else {
        !          75317:                 $dep = array(
        !          75318:                     'version' => $dep->getVersion(),
        !          75319:                 );
        !          75320:             }
        !          75321:         } else {
        !          75322:             if (isset($dep['uri'])) {
        !          75323:                 $channel = '__uri';
        !          75324:                 $package = $dep['dep']['name'];
        !          75325:             } else {
        !          75326:                 $channel = $dep['info']->getChannel();
        !          75327:                 $package = $dep['info']->getPackage();
        !          75328:             }
1.1       misho    75329:         }
                   75330: 
1.1.1.2 ! misho    75331:         $options = $this->_downloader->getOptions();
        !          75332:         $test    = $this->_installRegistry->packageExists($package, $channel);
        !          75333:         if (!$test && $channel == 'pecl.php.net') {
        !          75334:             // do magic to allow upgrading from old pecl packages to new ones
        !          75335:             $test = $this->_installRegistry->packageExists($package, 'pear.php.net');
        !          75336:             $channel = 'pear.php.net';
1.1       misho    75337:         }
                   75338: 
1.1.1.2 ! misho    75339:         if ($test) {
        !          75340:             if (isset($dep['uri'])) {
        !          75341:                 if ($this->_installRegistry->packageInfo($package, 'uri', '__uri') == $dep['uri']) {
        !          75342:                     return true;
1.1       misho    75343:                 }
                   75344:             }
1.1.1.2 ! misho    75345: 
        !          75346:             if (isset($options['upgrade'])) {
        !          75347:                 $packageVersion = $this->_installRegistry->packageInfo($package, 'version', $channel);
        !          75348:                 if (version_compare($packageVersion, $dep['version'], '>=')) {
        !          75349:                     return true;
        !          75350:                 }
        !          75351: 
        !          75352:                 return false;
1.1       misho    75353:             }
                   75354: 
1.1.1.2 ! misho    75355:             return true;
        !          75356:         }
        !          75357: 
        !          75358:         return false;
        !          75359:     }
        !          75360: 
        !          75361:     /**
        !          75362:      * Detect duplicate package names with differing versions
        !          75363:      *
        !          75364:      * If a user requests to install Date 1.4.6 and Date 1.4.7,
        !          75365:      * for instance, this is a logic error.  This method
        !          75366:      * detects this situation.
        !          75367:      *
        !          75368:      * @param array $params array of PEAR_Downloader_Package objects
        !          75369:      * @param array $errorparams empty array
        !          75370:      * @return array array of stupid duplicated packages in PEAR_Downloader_Package obejcts
        !          75371:      */
        !          75372:     function detectStupidDuplicates($params, &$errorparams)
        !          75373:     {
        !          75374:         $existing = array();
        !          75375:         foreach ($params as $i => $param) {
        !          75376:             $package = $param->getPackage();
        !          75377:             $channel = $param->getChannel();
        !          75378:             $group   = $param->getGroup();
        !          75379:             if (!isset($existing[$channel . '/' . $package])) {
        !          75380:                 $existing[$channel . '/' . $package] = array();
1.1       misho    75381:             }
                   75382: 
1.1.1.2 ! misho    75383:             if (!isset($existing[$channel . '/' . $package][$group])) {
        !          75384:                 $existing[$channel . '/' . $package][$group] = array();
1.1       misho    75385:             }
                   75386: 
1.1.1.2 ! misho    75387:             $existing[$channel . '/' . $package][$group][] = $i;
1.1       misho    75388:         }
                   75389: 
1.1.1.2 ! misho    75390:         $indices = array();
        !          75391:         foreach ($existing as $package => $groups) {
        !          75392:             foreach ($groups as $group => $dupes) {
        !          75393:                 if (count($dupes) > 1) {
        !          75394:                     $indices = $indices + $dupes;
        !          75395:                 }
        !          75396:             }
1.1       misho    75397:         }
                   75398: 
1.1.1.2 ! misho    75399:         $indices = array_unique($indices);
        !          75400:         foreach ($indices as $index) {
        !          75401:             $errorparams[] = $params[$index];
        !          75402:         }
1.1       misho    75403: 
1.1.1.2 ! misho    75404:         return count($errorparams);
        !          75405:     }
1.1       misho    75406: 
                   75407:     /**
1.1.1.2 ! misho    75408:      * @param array
        !          75409:      * @param bool ignore install groups - for final removal of dupe packages
        !          75410:      * @static
1.1       misho    75411:      */
1.1.1.2 ! misho    75412:     function removeDuplicates(&$params, $ignoreGroups = false)
        !          75413:     {
        !          75414:         $pnames = array();
        !          75415:         foreach ($params as $i => $param) {
        !          75416:             if (!$param) {
        !          75417:                 continue;
        !          75418:             }
1.1       misho    75419: 
1.1.1.2 ! misho    75420:             if ($param->getPackage()) {
        !          75421:                 $group = $ignoreGroups ? '' : $param->getGroup();
        !          75422:                 $pnames[$i] = $param->getChannel() . '/' .
        !          75423:                     $param->getPackage() . '-' . $param->getVersion() . '#' . $group;
        !          75424:             }
        !          75425:         }
1.1       misho    75426: 
1.1.1.2 ! misho    75427:         $pnames = array_unique($pnames);
        !          75428:         $unset  = array_diff(array_keys($params), array_keys($pnames));
        !          75429:         $testp  = array_flip($pnames);
        !          75430:         foreach ($params as $i => $param) {
        !          75431:             if (!$param) {
        !          75432:                 $unset[] = $i;
        !          75433:                 continue;
        !          75434:             }
1.1       misho    75435: 
1.1.1.2 ! misho    75436:             if (!is_a($param, 'PEAR_Downloader_Package')) {
        !          75437:                 $unset[] = $i;
        !          75438:                 continue;
        !          75439:             }
1.1       misho    75440: 
1.1.1.2 ! misho    75441:             $group = $ignoreGroups ? '' : $param->getGroup();
        !          75442:             if (!isset($testp[$param->getChannel() . '/' . $param->getPackage() . '-' .
        !          75443:                   $param->getVersion() . '#' . $group])) {
        !          75444:                 $unset[] = $i;
        !          75445:             }
        !          75446:         }
1.1       misho    75447: 
1.1.1.2 ! misho    75448:         foreach ($unset as $i) {
        !          75449:             unset($params[$i]);
        !          75450:         }
1.1       misho    75451: 
1.1.1.2 ! misho    75452:         $ret = array();
        !          75453:         foreach ($params as $i => $param) {
        !          75454:             $ret[] = &$params[$i];
        !          75455:         }
1.1       misho    75456: 
1.1.1.2 ! misho    75457:         $params = array();
        !          75458:         foreach ($ret as $i => $param) {
        !          75459:             $params[] = &$ret[$i];
        !          75460:         }
        !          75461:     }
1.1       misho    75462: 
1.1.1.2 ! misho    75463:     function explicitState()
        !          75464:     {
        !          75465:         return $this->_explicitState;
        !          75466:     }
1.1       misho    75467: 
1.1.1.2 ! misho    75468:     function setExplicitState($s)
        !          75469:     {
        !          75470:         $this->_explicitState = $s;
        !          75471:     }
1.1       misho    75472: 
                   75473:     /**
1.1.1.2 ! misho    75474:      * @static
1.1       misho    75475:      */
1.1.1.2 ! misho    75476:     function mergeDependencies(&$params)
1.1       misho    75477:     {
1.1.1.2 ! misho    75478:         $bundles = $newparams = array();
        !          75479:         foreach ($params as $i => $param) {
        !          75480:             if (!$param->isBundle()) {
        !          75481:                 continue;
        !          75482:             }
1.1       misho    75483: 
1.1.1.2 ! misho    75484:             $bundles[] = $i;
        !          75485:             $pf = &$param->getPackageFile();
        !          75486:             $newdeps = array();
        !          75487:             $contents = $pf->getBundledPackages();
        !          75488:             if (!is_array($contents)) {
        !          75489:                 $contents = array($contents);
        !          75490:             }
        !          75491: 
        !          75492:             foreach ($contents as $file) {
        !          75493:                 $filecontents = $pf->getFileContents($file);
        !          75494:                 $dl = &$param->getDownloader();
        !          75495:                 $options = $dl->getOptions();
        !          75496:                 if (PEAR::isError($dir = $dl->getDownloadDir())) {
        !          75497:                     return $dir;
        !          75498:                 }
        !          75499: 
        !          75500:                 $fp = @fopen($dir . DIRECTORY_SEPARATOR . $file, 'wb');
        !          75501:                 if (!$fp) {
        !          75502:                     continue;
        !          75503:                 }
        !          75504: 
        !          75505:                 // FIXME do symlink check
        !          75506: 
        !          75507:                 fwrite($fp, $filecontents, strlen($filecontents));
        !          75508:                 fclose($fp);
        !          75509:                 if ($s = $params[$i]->explicitState()) {
        !          75510:                     $obj->setExplicitState($s);
        !          75511:                 }
1.1       misho    75512: 
1.1.1.2 ! misho    75513:                 $obj = &new PEAR_Downloader_Package($params[$i]->getDownloader());
        !          75514:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          75515:                 if (PEAR::isError($dir = $dl->getDownloadDir())) {
        !          75516:                     PEAR::popErrorHandling();
        !          75517:                     return $dir;
        !          75518:                 }
        !          75519: 
        !          75520:                 $e = $obj->_fromFile($a = $dir . DIRECTORY_SEPARATOR . $file);
        !          75521:                 PEAR::popErrorHandling();
        !          75522:                 if (PEAR::isError($e)) {
        !          75523:                     if (!isset($options['soft'])) {
        !          75524:                         $dl->log(0, $e->getMessage());
        !          75525:                     }
1.1       misho    75526:                     continue;
                   75527:                 }
1.1.1.2 ! misho    75528: 
        !          75529:                 $j = &$obj;
        !          75530:                 if (!PEAR_Downloader_Package::willDownload($j,
        !          75531:                       array_merge($params, $newparams)) && !$param->isInstalled($j)) {
        !          75532:                     $newparams[] = &$j;
        !          75533:                 }
1.1       misho    75534:             }
                   75535:         }
                   75536: 
1.1.1.2 ! misho    75537:         foreach ($bundles as $i) {
        !          75538:             unset($params[$i]); // remove bundles - only their contents matter for installation
1.1       misho    75539:         }
                   75540: 
1.1.1.2 ! misho    75541:         PEAR_Downloader_Package::removeDuplicates($params); // strip any unset indices
        !          75542:         if (count($newparams)) { // add in bundled packages for install
        !          75543:             foreach ($newparams as $i => $unused) {
        !          75544:                 $params[] = &$newparams[$i];
1.1       misho    75545:             }
1.1.1.2 ! misho    75546:             $newparams = array();
1.1       misho    75547:         }
                   75548: 
1.1.1.2 ! misho    75549:         foreach ($params as $i => $param) {
        !          75550:             $newdeps = array();
        !          75551:             foreach ($param->_downloadDeps as $dep) {
        !          75552:                 $merge = array_merge($params, $newparams);
        !          75553:                 if (!PEAR_Downloader_Package::willDownload($dep, $merge)
        !          75554:                     && !$param->isInstalled($dep)
        !          75555:                 ) {
        !          75556:                     $newdeps[] = $dep;
        !          75557:                 } else {
        !          75558:                     //var_dump($dep);
        !          75559:                     // detect versioning conflicts here
        !          75560:                 }
        !          75561:             }
1.1       misho    75562: 
1.1.1.2 ! misho    75563:             // convert the dependencies into PEAR_Downloader_Package objects for the next time around
        !          75564:             $params[$i]->_downloadDeps = array();
        !          75565:             foreach ($newdeps as $dep) {
        !          75566:                 $obj = &new PEAR_Downloader_Package($params[$i]->getDownloader());
        !          75567:                 if ($s = $params[$i]->explicitState()) {
        !          75568:                     $obj->setExplicitState($s);
1.1       misho    75569:                 }
                   75570: 
1.1.1.2 ! misho    75571:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          75572:                 $e = $obj->fromDepURL($dep);
        !          75573:                 PEAR::popErrorHandling();
        !          75574:                 if (PEAR::isError($e)) {
        !          75575:                     if (!isset($options['soft'])) {
        !          75576:                         $obj->_downloader->log(0, $e->getMessage());
        !          75577:                     }
        !          75578:                     continue;
        !          75579:                 }
        !          75580: 
        !          75581:                 $e = $obj->detectDependencies($params);
        !          75582:                 if (PEAR::isError($e)) {
        !          75583:                     if (!isset($options['soft'])) {
        !          75584:                         $obj->_downloader->log(0, $e->getMessage());
        !          75585:                     }
        !          75586:                 }
        !          75587: 
        !          75588:                 $j = &$obj;
        !          75589:                 $newparams[] = &$j;
1.1       misho    75590:             }
1.1.1.2 ! misho    75591:         }
1.1       misho    75592: 
1.1.1.2 ! misho    75593:         if (count($newparams)) {
        !          75594:             foreach ($newparams as $i => $unused) {
        !          75595:                 $params[] = &$newparams[$i];
        !          75596:             }
1.1       misho    75597:             return true;
                   75598:         }
                   75599: 
                   75600:         return false;
                   75601:     }
                   75602: 
1.1.1.2 ! misho    75603: 
1.1       misho    75604:     /**
1.1.1.2 ! misho    75605:      * @static
1.1       misho    75606:      */
1.1.1.2 ! misho    75607:     function willDownload($param, $params)
1.1       misho    75608:     {
1.1.1.2 ! misho    75609:         if (!is_array($params)) {
        !          75610:             return false;
1.1       misho    75611:         }
1.1.1.2 ! misho    75612: 
        !          75613:         foreach ($params as $obj) {
        !          75614:             if ($obj->isEqual($param)) {
        !          75615:                 return true;
        !          75616:             }
        !          75617:         }
        !          75618: 
        !          75619:         return false;
1.1       misho    75620:     }
                   75621: 
                   75622:     /**
                   75623:      * For simpler unit-testing
                   75624:      * @param PEAR_Config
                   75625:      * @param int
1.1.1.2 ! misho    75626:      * @param string
1.1       misho    75627:      */
1.1.1.2 ! misho    75628:     function &getPackagefileObject(&$c, $d)
1.1       misho    75629:     {
1.1.1.2 ! misho    75630:         $a = &new PEAR_PackageFile($c, $d);
        !          75631:         return $a;
1.1       misho    75632:     }
                   75633: 
1.1.1.2 ! misho    75634:     /**
        !          75635:      * This will retrieve from a local file if possible, and parse out
        !          75636:      * a group name as well.  The original parameter will be modified to reflect this.
        !          75637:      * @param string|array can be a parsed package name as well
        !          75638:      * @access private
        !          75639:      */
        !          75640:     function _fromFile(&$param)
1.1       misho    75641:     {
1.1.1.2 ! misho    75642:         $saveparam = $param;
        !          75643:         if (is_string($param)) {
        !          75644:             if (!@file_exists($param)) {
        !          75645:                 $test = explode('#', $param);
        !          75646:                 $group = array_pop($test);
        !          75647:                 if (@file_exists(implode('#', $test))) {
        !          75648:                     $this->setGroup($group);
        !          75649:                     $param = implode('#', $test);
        !          75650:                     $this->_explicitGroup = true;
        !          75651:                 }
        !          75652:             }
1.1       misho    75653: 
1.1.1.2 ! misho    75654:             if (@is_file($param)) {
        !          75655:                 $this->_type = 'local';
        !          75656:                 $options = $this->_downloader->getOptions();
        !          75657:                 $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->_debug);
        !          75658:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          75659:                 $pf = &$pkg->fromAnyFile($param, PEAR_VALIDATE_INSTALLING);
        !          75660:                 PEAR::popErrorHandling();
        !          75661:                 if (PEAR::isError($pf)) {
        !          75662:                     $this->_valid = false;
        !          75663:                     $param = $saveparam;
        !          75664:                     return $pf;
        !          75665:                 }
        !          75666:                 $this->_packagefile = &$pf;
        !          75667:                 if (!$this->getGroup()) {
        !          75668:                     $this->setGroup('default'); // install the default dependency group
        !          75669:                 }
        !          75670:                 return $this->_valid = true;
        !          75671:             }
1.1       misho    75672:         }
1.1.1.2 ! misho    75673:         $param = $saveparam;
        !          75674:         return $this->_valid = false;
        !          75675:     }
1.1       misho    75676: 
1.1.1.2 ! misho    75677:     function _fromUrl($param, $saveparam = '')
        !          75678:     {
        !          75679:         if (!is_array($param) && (preg_match('#^(http|https|ftp)://#', $param))) {
        !          75680:             $options = $this->_downloader->getOptions();
        !          75681:             $this->_type = 'url';
        !          75682:             $callback = $this->_downloader->ui ?
        !          75683:                 array(&$this->_downloader, '_downloadCallback') : null;
        !          75684:             $this->_downloader->pushErrorHandling(PEAR_ERROR_RETURN);
        !          75685:             if (PEAR::isError($dir = $this->_downloader->getDownloadDir())) {
        !          75686:                 $this->_downloader->popErrorHandling();
        !          75687:                 return $dir;
1.1       misho    75688:             }
                   75689: 
1.1.1.2 ! misho    75690:             $this->_downloader->log(3, 'Downloading "' . $param . '"');
        !          75691:             $file = $this->_downloader->downloadHttp($param, $this->_downloader->ui,
        !          75692:                 $dir, $callback, null, false, $this->getChannel());
        !          75693:             $this->_downloader->popErrorHandling();
        !          75694:             if (PEAR::isError($file)) {
        !          75695:                 if (!empty($saveparam)) {
        !          75696:                     $saveparam = ", cannot download \"$saveparam\"";
1.1       misho    75697:                 }
1.1.1.2 ! misho    75698:                 $err = PEAR::raiseError('Could not download from "' . $param .
        !          75699:                     '"' . $saveparam . ' (' . $file->getMessage() . ')');
        !          75700:                     return $err;
        !          75701:             }
1.1       misho    75702: 
1.1.1.2 ! misho    75703:             if ($this->_rawpackagefile) {
        !          75704:                 require_once 'phar://install-pear-nozlib.phar/' . 'Archive/Tar.php';
        !          75705:                 $tar = &new Archive_Tar($file);
        !          75706:                 $packagexml = $tar->extractInString('package2.xml');
        !          75707:                 if (!$packagexml) {
        !          75708:                     $packagexml = $tar->extractInString('package.xml');
1.1       misho    75709:                 }
                   75710: 
1.1.1.2 ! misho    75711:                 if (str_replace(array("\n", "\r"), array('',''), $packagexml) !=
        !          75712:                       str_replace(array("\n", "\r"), array('',''), $this->_rawpackagefile)) {
        !          75713:                     if ($this->getChannel() != 'pear.php.net') {
        !          75714:                         return PEAR::raiseError('CRITICAL ERROR: package.xml downloaded does ' .
        !          75715:                             'not match value returned from xml-rpc');
1.1       misho    75716:                     }
                   75717: 
1.1.1.2 ! misho    75718:                     // be more lax for the existing PEAR packages that have not-ok
        !          75719:                     // characters in their package.xml
        !          75720:                     $this->_downloader->log(0, 'CRITICAL WARNING: The "' .
        !          75721:                         $this->getPackage() . '" package has invalid characters in its ' .
        !          75722:                         'package.xml.  The next version of PEAR may not be able to install ' .
        !          75723:                         'this package for security reasons.  Please open a bug report at ' .
        !          75724:                         'http://pear.php.net/package/' . $this->getPackage() . '/bugs');
1.1       misho    75725:                 }
                   75726:             }
                   75727: 
1.1.1.2 ! misho    75728:             // whew, download worked!
        !          75729:             $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->debug);
1.1       misho    75730: 
1.1.1.2 ! misho    75731:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          75732:             $pf = &$pkg->fromAnyFile($file, PEAR_VALIDATE_INSTALLING);
        !          75733:             PEAR::popErrorHandling();
        !          75734:             if (PEAR::isError($pf)) {
        !          75735:                 if (is_array($pf->getUserInfo())) {
        !          75736:                     foreach ($pf->getUserInfo() as $err) {
        !          75737:                         if (is_array($err)) {
        !          75738:                             $err = $err['message'];
        !          75739:                         }
        !          75740: 
        !          75741:                         if (!isset($options['soft'])) {
        !          75742:                             $this->_downloader->log(0, "Validation Error: $err");
1.1       misho    75743:                         }
                   75744:                     }
                   75745:                 }
                   75746: 
1.1.1.2 ! misho    75747:                 if (!isset($options['soft'])) {
        !          75748:                     $this->_downloader->log(0, $pf->getMessage());
1.1       misho    75749:                 }
                   75750: 
1.1.1.2 ! misho    75751:                 ///FIXME need to pass back some error code that we can use to match with to cancel all further operations
        !          75752:                 /// At least stop all deps of this package from being installed
        !          75753:                 $out = $saveparam ? $saveparam : $param;
        !          75754:                 $err = PEAR::raiseError('Download of "' . $out . '" succeeded, but it is not a valid package archive');
        !          75755:                 $this->_valid = false;
        !          75756:                 return $err;
1.1       misho    75757:             }
                   75758: 
1.1.1.2 ! misho    75759:             $this->_packagefile = &$pf;
        !          75760:             $this->setGroup('default'); // install the default dependency group
        !          75761:             return $this->_valid = true;
1.1       misho    75762:         }
                   75763: 
1.1.1.2 ! misho    75764:         return $this->_valid = false;
1.1       misho    75765:     }
                   75766: 
                   75767:     /**
1.1.1.2 ! misho    75768:      *
        !          75769:      * @param string|array pass in an array of format
        !          75770:      *                     array(
        !          75771:      *                      'package' => 'pname',
        !          75772:      *                     ['channel' => 'channame',]
        !          75773:      *                     ['version' => 'version',]
        !          75774:      *                     ['state' => 'state',])
        !          75775:      *                     or a string of format [channame/]pname[-version|-state]
1.1       misho    75776:      */
1.1.1.2 ! misho    75777:     function _fromString($param)
1.1       misho    75778:     {
1.1.1.2 ! misho    75779:         $options = $this->_downloader->getOptions();
        !          75780:         $channel = $this->_config->get('default_channel');
        !          75781:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          75782:         $pname = $this->_registry->parsePackageName($param, $channel);
        !          75783:         PEAR::popErrorHandling();
        !          75784:         if (PEAR::isError($pname)) {
        !          75785:             if ($pname->getCode() == 'invalid') {
        !          75786:                 $this->_valid = false;
        !          75787:                 return false;
        !          75788:             }
1.1       misho    75789: 
1.1.1.2 ! misho    75790:             if ($pname->getCode() == 'channel') {
        !          75791:                 $parsed = $pname->getUserInfo();
        !          75792:                 if ($this->_downloader->discover($parsed['channel'])) {
        !          75793:                     if ($this->_config->get('auto_discover')) {
        !          75794:                         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          75795:                         $pname = $this->_registry->parsePackageName($param, $channel);
        !          75796:                         PEAR::popErrorHandling();
        !          75797:                     } else {
        !          75798:                         if (!isset($options['soft'])) {
        !          75799:                             $this->_downloader->log(0, 'Channel "' . $parsed['channel'] .
        !          75800:                                 '" is not initialized, use ' .
        !          75801:                                 '"pear channel-discover ' . $parsed['channel'] . '" to initialize' .
        !          75802:                                 'or pear config-set auto_discover 1');
        !          75803:                         }
1.1       misho    75804:                     }
                   75805:                 }
                   75806: 
1.1.1.2 ! misho    75807:                 if (PEAR::isError($pname)) {
        !          75808:                     if (!isset($options['soft'])) {
        !          75809:                         $this->_downloader->log(0, $pname->getMessage());
1.1       misho    75810:                     }
                   75811: 
1.1.1.2 ! misho    75812:                     if (is_array($param)) {
        !          75813:                         $param = $this->_registry->parsedPackageNameToString($param);
1.1       misho    75814:                     }
                   75815: 
1.1.1.2 ! misho    75816:                     $err = PEAR::raiseError('invalid package name/package file "' . $param . '"');
        !          75817:                     $this->_valid = false;
        !          75818:                     return $err;
        !          75819:                 }
        !          75820:             } else {
        !          75821:                 if (!isset($options['soft'])) {
        !          75822:                     $this->_downloader->log(0, $pname->getMessage());
        !          75823:                 }
1.1       misho    75824: 
1.1.1.2 ! misho    75825:                 $err = PEAR::raiseError('invalid package name/package file "' . $param . '"');
        !          75826:                 $this->_valid = false;
        !          75827:                 return $err;
        !          75828:             }
        !          75829:         }
1.1       misho    75830: 
1.1.1.2 ! misho    75831:         if (!isset($this->_type)) {
        !          75832:             $this->_type = 'rest';
        !          75833:         }
1.1       misho    75834: 
1.1.1.2 ! misho    75835:         $this->_parsedname    = $pname;
        !          75836:         $this->_explicitState = isset($pname['state']) ? $pname['state'] : false;
        !          75837:         $this->_explicitGroup = isset($pname['group']) ? true : false;
1.1       misho    75838: 
1.1.1.2 ! misho    75839:         $info = $this->_downloader->_getPackageDownloadUrl($pname);
        !          75840:         if (PEAR::isError($info)) {
        !          75841:             if ($info->getCode() != -976 && $pname['channel'] == 'pear.php.net') {
        !          75842:                 // try pecl
        !          75843:                 $pname['channel'] = 'pecl.php.net';
        !          75844:                 if ($test = $this->_downloader->_getPackageDownloadUrl($pname)) {
        !          75845:                     if (!PEAR::isError($test)) {
        !          75846:                         $info = PEAR::raiseError($info->getMessage() . ' - package ' .
        !          75847:                             $this->_registry->parsedPackageNameToString($pname, true) .
        !          75848:                             ' can be installed with "pecl install ' . $pname['package'] .
        !          75849:                             '"');
1.1       misho    75850:                     } else {
1.1.1.2 ! misho    75851:                         $pname['channel'] = 'pear.php.net';
1.1       misho    75852:                     }
1.1.1.2 ! misho    75853:                 } else {
        !          75854:                     $pname['channel'] = 'pear.php.net';
1.1       misho    75855:                 }
                   75856:             }
1.1.1.2 ! misho    75857: 
        !          75858:             return $info;
1.1       misho    75859:         }
                   75860: 
1.1.1.2 ! misho    75861:         $this->_rawpackagefile = $info['raw'];
        !          75862:         $ret = $this->_analyzeDownloadURL($info, $param, $pname);
        !          75863:         if (PEAR::isError($ret)) {
        !          75864:             return $ret;
        !          75865:         }
        !          75866: 
        !          75867:         if ($ret) {
        !          75868:             $this->_downloadURL = $ret;
        !          75869:             return $this->_valid = (bool) $ret;
1.1       misho    75870:         }
                   75871:     }
                   75872: 
                   75873:     /**
1.1.1.2 ! misho    75874:      * @param array output of package.getDownloadURL
        !          75875:      * @param string|array|object information for detecting packages to be downloaded, and
        !          75876:      *                            for errors
        !          75877:      * @param array name information of the package
        !          75878:      * @param array|null packages to be downloaded
        !          75879:      * @param bool is this an optional dependency?
        !          75880:      * @param bool is this any kind of dependency?
1.1       misho    75881:      * @access private
                   75882:      */
1.1.1.2 ! misho    75883:     function _analyzeDownloadURL($info, $param, $pname, $params = null, $optional = false,
        !          75884:                                  $isdependency = false)
1.1       misho    75885:     {
1.1.1.2 ! misho    75886:         if (!is_string($param) && PEAR_Downloader_Package::willDownload($param, $params)) {
        !          75887:             return false;
1.1       misho    75888:         }
                   75889: 
1.1.1.2 ! misho    75890:         if ($info === false) {
        !          75891:             $saveparam = !is_string($param) ? ", cannot download \"$param\"" : '';
1.1       misho    75892: 
1.1.1.2 ! misho    75893:             // no releases exist
        !          75894:             return PEAR::raiseError('No releases for package "' .
        !          75895:                 $this->_registry->parsedPackageNameToString($pname, true) . '" exist' . $saveparam);
        !          75896:         }
        !          75897: 
        !          75898:         if (strtolower($info['info']->getChannel()) != strtolower($pname['channel'])) {
        !          75899:             $err = false;
        !          75900:             if ($pname['channel'] == 'pecl.php.net') {
        !          75901:                 if ($info['info']->getChannel() != 'pear.php.net') {
        !          75902:                     $err = true;
        !          75903:                 }
        !          75904:             } elseif ($info['info']->getChannel() == 'pecl.php.net') {
        !          75905:                 if ($pname['channel'] != 'pear.php.net') {
        !          75906:                     $err = true;
        !          75907:                 }
        !          75908:             } else {
        !          75909:                 $err = true;
1.1       misho    75910:             }
                   75911: 
1.1.1.2 ! misho    75912:             if ($err) {
        !          75913:                 return PEAR::raiseError('SECURITY ERROR: package in channel "' . $pname['channel'] .
        !          75914:                     '" retrieved another channel\'s name for download! ("' .
        !          75915:                     $info['info']->getChannel() . '")');
1.1       misho    75916:             }
                   75917:         }
                   75918: 
1.1.1.2 ! misho    75919:         $preferred_state = $this->_config->get('preferred_state');
        !          75920:         if (!isset($info['url'])) {
        !          75921:             $package_version = $this->_registry->packageInfo($info['info']->getPackage(),
        !          75922:             'version', $info['info']->getChannel());
        !          75923:             if ($this->isInstalled($info)) {
        !          75924:                 if ($isdependency && version_compare($info['version'], $package_version, '<=')) {
        !          75925:                     // ignore bogus errors of "failed to download dependency"
        !          75926:                     // if it is already installed and the one that would be
        !          75927:                     // downloaded is older or the same version (Bug #7219)
        !          75928:                     return false;
        !          75929:                 }
1.1       misho    75930:             }
                   75931: 
1.1.1.2 ! misho    75932:             if ($info['version'] === $package_version) {
        !          75933:                 if (!isset($options['soft'])) {
        !          75934:                     $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] .
        !          75935:                         '/' . $pname['package'] . '-' . $package_version. ', additionally the suggested version' .
        !          75936:                         ' (' . $package_version . ') is the same as the locally installed one.');
        !          75937:                 }
1.1       misho    75938: 
1.1.1.2 ! misho    75939:                 return false;
1.1       misho    75940:             }
                   75941: 
1.1.1.2 ! misho    75942:             if (version_compare($info['version'], $package_version, '<=')) {
        !          75943:                 if (!isset($options['soft'])) {
        !          75944:                     $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] .
        !          75945:                         '/' . $pname['package'] . '-' . $package_version . ', additionally the suggested version' .
        !          75946:                         ' (' . $info['version'] . ') is a lower version than the locally installed one (' . $package_version . ').');
        !          75947:                 }
1.1       misho    75948: 
1.1.1.2 ! misho    75949:                 return false;
        !          75950:             }
1.1       misho    75951: 
1.1.1.2 ! misho    75952:             $instead =  ', will instead download version ' . $info['version'] .
        !          75953:                         ', stability "' . $info['info']->getState() . '"';
        !          75954:             // releases exist, but we failed to get any
        !          75955:             if (isset($this->_downloader->_options['force'])) {
        !          75956:                 if (isset($pname['version'])) {
        !          75957:                     $vs = ', version "' . $pname['version'] . '"';
        !          75958:                 } elseif (isset($pname['state'])) {
        !          75959:                     $vs = ', stability "' . $pname['state'] . '"';
        !          75960:                 } elseif ($param == 'dependency') {
        !          75961:                     if (!class_exists('PEAR_Common')) {
        !          75962:                         require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
        !          75963:                     }
1.1       misho    75964: 
1.1.1.2 ! misho    75965:                     if (!in_array($info['info']->getState(),
        !          75966:                           PEAR_Common::betterStates($preferred_state, true))) {
        !          75967:                         if ($optional) {
        !          75968:                             // don't spit out confusing error message
        !          75969:                             return $this->_downloader->_getPackageDownloadUrl(
        !          75970:                                 array('package' => $pname['package'],
        !          75971:                                       'channel' => $pname['channel'],
        !          75972:                                       'version' => $info['version']));
        !          75973:                         }
        !          75974:                         $vs = ' within preferred state "' . $preferred_state .
        !          75975:                             '"';
        !          75976:                     } else {
        !          75977:                         if (!class_exists('PEAR_Dependency2')) {
        !          75978:                             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Dependency2.php';
        !          75979:                         }
1.1       misho    75980: 
1.1.1.2 ! misho    75981:                         if ($optional) {
        !          75982:                             // don't spit out confusing error message
        !          75983:                             return $this->_downloader->_getPackageDownloadUrl(
        !          75984:                                 array('package' => $pname['package'],
        !          75985:                                       'channel' => $pname['channel'],
        !          75986:                                       'version' => $info['version']));
        !          75987:                         }
        !          75988:                         $vs = PEAR_Dependency2::_getExtraString($pname);
        !          75989:                         $instead = '';
        !          75990:                     }
        !          75991:                 } else {
        !          75992:                     $vs = ' within preferred state "' . $preferred_state . '"';
1.1       misho    75993:                 }
                   75994: 
1.1.1.2 ! misho    75995:                 if (!isset($options['soft'])) {
        !          75996:                     $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] .
        !          75997:                         '/' . $pname['package'] . $vs . $instead);
        !          75998:                 }
1.1       misho    75999: 
1.1.1.2 ! misho    76000:                 // download the latest release
        !          76001:                 return $this->_downloader->_getPackageDownloadUrl(
        !          76002:                     array('package' => $pname['package'],
        !          76003:                           'channel' => $pname['channel'],
        !          76004:                           'version' => $info['version']));
        !          76005:             } else {
        !          76006:                 if (isset($info['php']) && $info['php']) {
        !          76007:                     $err = PEAR::raiseError('Failed to download ' .
        !          76008:                         $this->_registry->parsedPackageNameToString(
        !          76009:                             array('channel' => $pname['channel'],
        !          76010:                                   'package' => $pname['package']),
        !          76011:                                 true) .
        !          76012:                         ', latest release is version ' . $info['php']['v'] .
        !          76013:                         ', but it requires PHP version "' .
        !          76014:                         $info['php']['m'] . '", use "' .
        !          76015:                         $this->_registry->parsedPackageNameToString(
        !          76016:                             array('channel' => $pname['channel'], 'package' => $pname['package'],
        !          76017:                             'version' => $info['php']['v'])) . '" to install',
        !          76018:                             PEAR_DOWNLOADER_PACKAGE_PHPVERSION);
        !          76019:                     return $err;
        !          76020:                 }
1.1       misho    76021: 
1.1.1.2 ! misho    76022:                 // construct helpful error message
        !          76023:                 if (isset($pname['version'])) {
        !          76024:                     $vs = ', version "' . $pname['version'] . '"';
        !          76025:                 } elseif (isset($pname['state'])) {
        !          76026:                     $vs = ', stability "' . $pname['state'] . '"';
        !          76027:                 } elseif ($param == 'dependency') {
        !          76028:                     if (!class_exists('PEAR_Common')) {
        !          76029:                         require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
        !          76030:                     }
1.1       misho    76031: 
1.1.1.2 ! misho    76032:                     if (!in_array($info['info']->getState(),
        !          76033:                           PEAR_Common::betterStates($preferred_state, true))) {
        !          76034:                         if ($optional) {
        !          76035:                             // don't spit out confusing error message, and don't die on
        !          76036:                             // optional dep failure!
        !          76037:                             return $this->_downloader->_getPackageDownloadUrl(
        !          76038:                                 array('package' => $pname['package'],
        !          76039:                                       'channel' => $pname['channel'],
        !          76040:                                       'version' => $info['version']));
        !          76041:                         }
        !          76042:                         $vs = ' within preferred state "' . $preferred_state . '"';
        !          76043:                     } else {
        !          76044:                         if (!class_exists('PEAR_Dependency2')) {
        !          76045:                             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Dependency2.php';
        !          76046:                         }
        !          76047: 
        !          76048:                         if ($optional) {
        !          76049:                             // don't spit out confusing error message, and don't die on
        !          76050:                             // optional dep failure!
        !          76051:                             return $this->_downloader->_getPackageDownloadUrl(
        !          76052:                                 array('package' => $pname['package'],
        !          76053:                                       'channel' => $pname['channel'],
        !          76054:                                       'version' => $info['version']));
        !          76055:                         }
        !          76056:                         $vs = PEAR_Dependency2::_getExtraString($pname);
        !          76057:                     }
        !          76058:                 } else {
        !          76059:                     $vs = ' within preferred state "' . $this->_downloader->config->get('preferred_state') . '"';
        !          76060:                 }
        !          76061: 
        !          76062:                 $options = $this->_downloader->getOptions();
        !          76063:                 // this is only set by the "download-all" command
        !          76064:                 if (isset($options['ignorepreferred_state'])) {
        !          76065:                     $err = PEAR::raiseError(
        !          76066:                         'Failed to download ' . $this->_registry->parsedPackageNameToString(
        !          76067:                             array('channel' => $pname['channel'], 'package' => $pname['package']),
        !          76068:                                 true)
        !          76069:                          . $vs .
        !          76070:                         ', latest release is version ' . $info['version'] .
        !          76071:                         ', stability "' . $info['info']->getState() . '", use "' .
        !          76072:                         $this->_registry->parsedPackageNameToString(
        !          76073:                             array('channel' => $pname['channel'], 'package' => $pname['package'],
        !          76074:                             'version' => $info['version'])) . '" to install',
        !          76075:                             PEAR_DOWNLOADER_PACKAGE_STATE);
        !          76076:                     return $err;
        !          76077:                 }
        !          76078: 
        !          76079:                 // Checks if the user has a package installed already and checks the release against
        !          76080:                 // the state against the installed package, this allows upgrades for packages
        !          76081:                 // with lower stability than the preferred_state
        !          76082:                 $stability = $this->_registry->packageInfo($pname['package'], 'stability', $pname['channel']);
        !          76083:                 if (!$this->isInstalled($info)
        !          76084:                     || !in_array($info['info']->getState(), PEAR_Common::betterStates($stability['release'], true))
        !          76085:                 ) {
        !          76086:                     $err = PEAR::raiseError(
        !          76087:                         'Failed to download ' . $this->_registry->parsedPackageNameToString(
        !          76088:                             array('channel' => $pname['channel'], 'package' => $pname['package']),
        !          76089:                                 true)
        !          76090:                          . $vs .
        !          76091:                         ', latest release is version ' . $info['version'] .
        !          76092:                         ', stability "' . $info['info']->getState() . '", use "' .
        !          76093:                         $this->_registry->parsedPackageNameToString(
        !          76094:                             array('channel' => $pname['channel'], 'package' => $pname['package'],
        !          76095:                             'version' => $info['version'])) . '" to install');
        !          76096:                     return $err;
        !          76097:                 }
        !          76098:             }
1.1       misho    76099:         }
                   76100: 
1.1.1.2 ! misho    76101:         if (isset($info['deprecated']) && $info['deprecated']) {
        !          76102:             $this->_downloader->log(0,
        !          76103:                 'WARNING: "' .
        !          76104:                     $this->_registry->parsedPackageNameToString(
        !          76105:                             array('channel' => $info['info']->getChannel(),
        !          76106:                                   'package' => $info['info']->getPackage()), true) .
        !          76107:                 '" is deprecated in favor of "' .
        !          76108:                     $this->_registry->parsedPackageNameToString($info['deprecated'], true) .
        !          76109:                 '"');
1.1       misho    76110:         }
                   76111: 
1.1.1.2 ! misho    76112:         return $info;
        !          76113:     }
        !          76114: }<?php
        !          76115: /**
        !          76116:  * Error Stack Implementation
        !          76117:  * 
        !          76118:  * This is an incredibly simple implementation of a very complex error handling
        !          76119:  * facility.  It contains the ability
        !          76120:  * to track multiple errors from multiple packages simultaneously.  In addition,
        !          76121:  * it can track errors of many levels, save data along with the error, context
        !          76122:  * information such as the exact file, line number, class and function that
        !          76123:  * generated the error, and if necessary, it can raise a traditional PEAR_Error.
        !          76124:  * It has built-in support for PEAR::Log, to log errors as they occur
        !          76125:  * 
        !          76126:  * Since version 0.2alpha, it is also possible to selectively ignore errors,
        !          76127:  * through the use of an error callback, see {@link pushCallback()}
        !          76128:  * 
        !          76129:  * Since version 0.3alpha, it is possible to specify the exception class
        !          76130:  * returned from {@link push()}
        !          76131:  *
        !          76132:  * Since version PEAR1.3.2, ErrorStack no longer instantiates an exception class.  This can
        !          76133:  * still be done quite handily in an error callback or by manipulating the returned array
        !          76134:  * @category   Debugging
        !          76135:  * @package    PEAR_ErrorStack
        !          76136:  * @author     Greg Beaver <cellog@php.net>
        !          76137:  * @copyright  2004-2008 Greg Beaver
        !          76138:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          76139:  * @version    CVS: $Id: ErrorStack.php 313023 2011-07-06 19:17:11Z dufuz $
        !          76140:  * @link       http://pear.php.net/package/PEAR_ErrorStack
        !          76141:  */
1.1       misho    76142: 
1.1.1.2 ! misho    76143: /**
        !          76144:  * Singleton storage
        !          76145:  * 
        !          76146:  * Format:
        !          76147:  * <pre>
        !          76148:  * array(
        !          76149:  *  'package1' => PEAR_ErrorStack object,
        !          76150:  *  'package2' => PEAR_ErrorStack object,
        !          76151:  *  ...
        !          76152:  * )
        !          76153:  * </pre>
        !          76154:  * @access private
        !          76155:  * @global array $GLOBALS['_PEAR_ERRORSTACK_SINGLETON']
        !          76156:  */
        !          76157: $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] = array();
1.1       misho    76158: 
1.1.1.2 ! misho    76159: /**
        !          76160:  * Global error callback (default)
        !          76161:  * 
        !          76162:  * This is only used if set to non-false.  * is the default callback for
        !          76163:  * all packages, whereas specific packages may set a default callback
        !          76164:  * for all instances, regardless of whether they are a singleton or not.
        !          76165:  *
        !          76166:  * To exclude non-singletons, only set the local callback for the singleton
        !          76167:  * @see PEAR_ErrorStack::setDefaultCallback()
        !          76168:  * @access private
        !          76169:  * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']
        !          76170:  */
        !          76171: $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] = array(
        !          76172:     '*' => false,
        !          76173: );
1.1       misho    76174: 
1.1.1.2 ! misho    76175: /**
        !          76176:  * Global Log object (default)
        !          76177:  * 
        !          76178:  * This is only used if set to non-false.  Use to set a default log object for
        !          76179:  * all stacks, regardless of instantiation order or location
        !          76180:  * @see PEAR_ErrorStack::setDefaultLogger()
        !          76181:  * @access private
        !          76182:  * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']
        !          76183:  */
        !          76184: $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = false;
1.1       misho    76185: 
1.1.1.2 ! misho    76186: /**
        !          76187:  * Global Overriding Callback
        !          76188:  * 
        !          76189:  * This callback will override any error callbacks that specific loggers have set.
        !          76190:  * Use with EXTREME caution
        !          76191:  * @see PEAR_ErrorStack::staticPushCallback()
        !          76192:  * @access private
        !          76193:  * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']
        !          76194:  */
        !          76195: $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();
1.1       misho    76196: 
1.1.1.2 ! misho    76197: /**#@+
        !          76198:  * One of four possible return values from the error Callback
        !          76199:  * @see PEAR_ErrorStack::_errorCallback()
        !          76200:  */
        !          76201: /**
        !          76202:  * If this is returned, then the error will be both pushed onto the stack
        !          76203:  * and logged.
        !          76204:  */
        !          76205: define('PEAR_ERRORSTACK_PUSHANDLOG', 1);
        !          76206: /**
        !          76207:  * If this is returned, then the error will only be pushed onto the stack,
        !          76208:  * and not logged.
        !          76209:  */
        !          76210: define('PEAR_ERRORSTACK_PUSH', 2);
        !          76211: /**
        !          76212:  * If this is returned, then the error will only be logged, but not pushed
        !          76213:  * onto the error stack.
        !          76214:  */
        !          76215: define('PEAR_ERRORSTACK_LOG', 3);
        !          76216: /**
        !          76217:  * If this is returned, then the error is completely ignored.
        !          76218:  */
        !          76219: define('PEAR_ERRORSTACK_IGNORE', 4);
        !          76220: /**
        !          76221:  * If this is returned, then the error is logged and die() is called.
        !          76222:  */
        !          76223: define('PEAR_ERRORSTACK_DIE', 5);
        !          76224: /**#@-*/
1.1       misho    76225: 
1.1.1.2 ! misho    76226: /**
        !          76227:  * Error code for an attempt to instantiate a non-class as a PEAR_ErrorStack in
        !          76228:  * the singleton method.
        !          76229:  */
        !          76230: define('PEAR_ERRORSTACK_ERR_NONCLASS', 1);
1.1       misho    76231: 
1.1.1.2 ! misho    76232: /**
        !          76233:  * Error code for an attempt to pass an object into {@link PEAR_ErrorStack::getMessage()}
        !          76234:  * that has no __toString() method
        !          76235:  */
        !          76236: define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2);
        !          76237: /**
        !          76238:  * Error Stack Implementation
        !          76239:  *
        !          76240:  * Usage:
        !          76241:  * <code>
        !          76242:  * // global error stack
        !          76243:  * $global_stack = &PEAR_ErrorStack::singleton('MyPackage');
        !          76244:  * // local error stack
        !          76245:  * $local_stack = new PEAR_ErrorStack('MyPackage');
        !          76246:  * </code>
        !          76247:  * @author     Greg Beaver <cellog@php.net>
        !          76248:  * @version    1.9.4
        !          76249:  * @package    PEAR_ErrorStack
        !          76250:  * @category   Debugging
        !          76251:  * @copyright  2004-2008 Greg Beaver
        !          76252:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          76253:  * @version    CVS: $Id: ErrorStack.php 313023 2011-07-06 19:17:11Z dufuz $
        !          76254:  * @link       http://pear.php.net/package/PEAR_ErrorStack
        !          76255:  */
        !          76256: class PEAR_ErrorStack {
        !          76257:     /**
        !          76258:      * Errors are stored in the order that they are pushed on the stack.
        !          76259:      * @since 0.4alpha Errors are no longer organized by error level.
        !          76260:      * This renders pop() nearly unusable, and levels could be more easily
        !          76261:      * handled in a callback anyway
        !          76262:      * @var array
        !          76263:      * @access private
        !          76264:      */
        !          76265:     var $_errors = array();
1.1       misho    76266: 
1.1.1.2 ! misho    76267:     /**
        !          76268:      * Storage of errors by level.
        !          76269:      *
        !          76270:      * Allows easy retrieval and deletion of only errors from a particular level
        !          76271:      * @since PEAR 1.4.0dev
        !          76272:      * @var array
        !          76273:      * @access private
        !          76274:      */
        !          76275:     var $_errorsByLevel = array();
1.1       misho    76276: 
1.1.1.2 ! misho    76277:     /**
        !          76278:      * Package name this error stack represents
        !          76279:      * @var string
        !          76280:      * @access protected
        !          76281:      */
        !          76282:     var $_package;
        !          76283:     
        !          76284:     /**
        !          76285:      * Determines whether a PEAR_Error is thrown upon every error addition
        !          76286:      * @var boolean
        !          76287:      * @access private
        !          76288:      */
        !          76289:     var $_compat = false;
        !          76290:     
        !          76291:     /**
        !          76292:      * If set to a valid callback, this will be used to generate the error
        !          76293:      * message from the error code, otherwise the message passed in will be
        !          76294:      * used
        !          76295:      * @var false|string|array
        !          76296:      * @access private
        !          76297:      */
        !          76298:     var $_msgCallback = false;
        !          76299:     
        !          76300:     /**
        !          76301:      * If set to a valid callback, this will be used to generate the error
        !          76302:      * context for an error.  For PHP-related errors, this will be a file
        !          76303:      * and line number as retrieved from debug_backtrace(), but can be
        !          76304:      * customized for other purposes.  The error might actually be in a separate
        !          76305:      * configuration file, or in a database query.
        !          76306:      * @var false|string|array
        !          76307:      * @access protected
        !          76308:      */
        !          76309:     var $_contextCallback = false;
        !          76310:     
        !          76311:     /**
        !          76312:      * If set to a valid callback, this will be called every time an error
        !          76313:      * is pushed onto the stack.  The return value will be used to determine
        !          76314:      * whether to allow an error to be pushed or logged.
        !          76315:      * 
        !          76316:      * The return value must be one an PEAR_ERRORSTACK_* constant
        !          76317:      * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
        !          76318:      * @var false|string|array
        !          76319:      * @access protected
        !          76320:      */
        !          76321:     var $_errorCallback = array();
        !          76322:     
        !          76323:     /**
        !          76324:      * PEAR::Log object for logging errors
        !          76325:      * @var false|Log
        !          76326:      * @access protected
        !          76327:      */
        !          76328:     var $_logger = false;
        !          76329:     
        !          76330:     /**
        !          76331:      * Error messages - designed to be overridden
        !          76332:      * @var array
        !          76333:      * @abstract
        !          76334:      */
        !          76335:     var $_errorMsgs = array();
        !          76336:     
        !          76337:     /**
        !          76338:      * Set up a new error stack
        !          76339:      * 
        !          76340:      * @param string   $package name of the package this error stack represents
        !          76341:      * @param callback $msgCallback callback used for error message generation
        !          76342:      * @param callback $contextCallback callback used for context generation,
        !          76343:      *                 defaults to {@link getFileLine()}
        !          76344:      * @param boolean  $throwPEAR_Error
        !          76345:      */
        !          76346:     function PEAR_ErrorStack($package, $msgCallback = false, $contextCallback = false,
        !          76347:                          $throwPEAR_Error = false)
        !          76348:     {
        !          76349:         $this->_package = $package;
        !          76350:         $this->setMessageCallback($msgCallback);
        !          76351:         $this->setContextCallback($contextCallback);
        !          76352:         $this->_compat = $throwPEAR_Error;
        !          76353:     }
        !          76354:     
        !          76355:     /**
        !          76356:      * Return a single error stack for this package.
        !          76357:      * 
        !          76358:      * Note that all parameters are ignored if the stack for package $package
        !          76359:      * has already been instantiated
        !          76360:      * @param string   $package name of the package this error stack represents
        !          76361:      * @param callback $msgCallback callback used for error message generation
        !          76362:      * @param callback $contextCallback callback used for context generation,
        !          76363:      *                 defaults to {@link getFileLine()}
        !          76364:      * @param boolean  $throwPEAR_Error
        !          76365:      * @param string   $stackClass class to instantiate
        !          76366:      * @static
        !          76367:      * @return PEAR_ErrorStack
        !          76368:      */
        !          76369:     function &singleton($package, $msgCallback = false, $contextCallback = false,
        !          76370:                          $throwPEAR_Error = false, $stackClass = 'PEAR_ErrorStack')
        !          76371:     {
        !          76372:         if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
        !          76373:             return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
1.1       misho    76374:         }
1.1.1.2 ! misho    76375:         if (!class_exists($stackClass)) {
        !          76376:             if (function_exists('debug_backtrace')) {
        !          76377:                 $trace = debug_backtrace();
        !          76378:             }
        !          76379:             PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_NONCLASS,
        !          76380:                 'exception', array('stackclass' => $stackClass),
        !          76381:                 'stack class "%stackclass%" is not a valid class name (should be like PEAR_ErrorStack)',
        !          76382:                 false, $trace);
1.1       misho    76383:         }
1.1.1.2 ! misho    76384:         $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package] =
        !          76385:             new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error);
1.1       misho    76386: 
1.1.1.2 ! misho    76387:         return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
1.1       misho    76388:     }
                   76389: 
                   76390:     /**
1.1.1.2 ! misho    76391:      * Internal error handler for PEAR_ErrorStack class
        !          76392:      * 
        !          76393:      * Dies if the error is an exception (and would have died anyway)
1.1       misho    76394:      * @access private
                   76395:      */
1.1.1.2 ! misho    76396:     function _handleError($err)
1.1       misho    76397:     {
1.1.1.2 ! misho    76398:         if ($err['level'] == 'exception') {
        !          76399:             $message = $err['message'];
        !          76400:             if (isset($_SERVER['REQUEST_URI'])) {
        !          76401:                 echo '<br />';
1.1       misho    76402:             } else {
1.1.1.2 ! misho    76403:                 echo "\n";
1.1       misho    76404:             }
1.1.1.2 ! misho    76405:             var_dump($err['context']);
        !          76406:             die($message);
1.1       misho    76407:         }
1.1.1.2 ! misho    76408:     }
        !          76409:     
        !          76410:     /**
        !          76411:      * Set up a PEAR::Log object for all error stacks that don't have one
        !          76412:      * @param Log $log 
        !          76413:      * @static
        !          76414:      */
        !          76415:     function setDefaultLogger(&$log)
        !          76416:     {
        !          76417:         if (is_object($log) && method_exists($log, 'log') ) {
        !          76418:             $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
        !          76419:         } elseif (is_callable($log)) {
        !          76420:             $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
        !          76421:        }
        !          76422:     }
        !          76423:     
        !          76424:     /**
        !          76425:      * Set up a PEAR::Log object for this error stack
        !          76426:      * @param Log $log 
        !          76427:      */
        !          76428:     function setLogger(&$log)
        !          76429:     {
        !          76430:         if (is_object($log) && method_exists($log, 'log') ) {
        !          76431:             $this->_logger = &$log;
        !          76432:         } elseif (is_callable($log)) {
        !          76433:             $this->_logger = &$log;
1.1       misho    76434:         }
                   76435:     }
1.1.1.2 ! misho    76436:     
1.1       misho    76437:     /**
1.1.1.2 ! misho    76438:      * Set an error code => error message mapping callback
        !          76439:      * 
        !          76440:      * This method sets the callback that can be used to generate error
        !          76441:      * messages for any instance
        !          76442:      * @param array|string Callback function/method
1.1       misho    76443:      */
1.1.1.2 ! misho    76444:     function setMessageCallback($msgCallback)
1.1       misho    76445:     {
1.1.1.2 ! misho    76446:         if (!$msgCallback) {
        !          76447:             $this->_msgCallback = array(&$this, 'getErrorMessage');
1.1       misho    76448:         } else {
1.1.1.2 ! misho    76449:             if (is_callable($msgCallback)) {
        !          76450:                 $this->_msgCallback = $msgCallback;
1.1       misho    76451:             }
                   76452:         }
                   76453:     }
1.1.1.2 ! misho    76454:     
1.1       misho    76455:     /**
1.1.1.2 ! misho    76456:      * Get an error code => error message mapping callback
        !          76457:      * 
        !          76458:      * This method returns the current callback that can be used to generate error
        !          76459:      * messages
        !          76460:      * @return array|string|false Callback function/method or false if none
1.1       misho    76461:      */
1.1.1.2 ! misho    76462:     function getMessageCallback()
1.1       misho    76463:     {
1.1.1.2 ! misho    76464:         return $this->_msgCallback;
1.1       misho    76465:     }
1.1.1.2 ! misho    76466:     
        !          76467:     /**
        !          76468:      * Sets a default callback to be used by all error stacks
        !          76469:      * 
        !          76470:      * This method sets the callback that can be used to generate error
        !          76471:      * messages for a singleton
        !          76472:      * @param array|string Callback function/method
        !          76473:      * @param string Package name, or false for all packages
        !          76474:      * @static
        !          76475:      */
        !          76476:     function setDefaultCallback($callback = false, $package = false)
1.1       misho    76477:     {
1.1.1.2 ! misho    76478:         if (!is_callable($callback)) {
        !          76479:             $callback = false;
1.1       misho    76480:         }
1.1.1.2 ! misho    76481:         $package = $package ? $package : '*';
        !          76482:         $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$package] = $callback;
1.1       misho    76483:     }
1.1.1.2 ! misho    76484:     
        !          76485:     /**
        !          76486:      * Set a callback that generates context information (location of error) for an error stack
        !          76487:      * 
        !          76488:      * This method sets the callback that can be used to generate context
        !          76489:      * information for an error.  Passing in NULL will disable context generation
        !          76490:      * and remove the expensive call to debug_backtrace()
        !          76491:      * @param array|string|null Callback function/method
        !          76492:      */
        !          76493:     function setContextCallback($contextCallback)
1.1       misho    76494:     {
1.1.1.2 ! misho    76495:         if ($contextCallback === null) {
        !          76496:             return $this->_contextCallback = false;
        !          76497:         }
        !          76498:         if (!$contextCallback) {
        !          76499:             $this->_contextCallback = array(&$this, 'getFileLine');
        !          76500:         } else {
        !          76501:             if (is_callable($contextCallback)) {
        !          76502:                 $this->_contextCallback = $contextCallback;
1.1       misho    76503:             }
                   76504:         }
                   76505:     }
1.1.1.2 ! misho    76506:     
1.1       misho    76507:     /**
1.1.1.2 ! misho    76508:      * Set an error Callback
        !          76509:      * If set to a valid callback, this will be called every time an error
        !          76510:      * is pushed onto the stack.  The return value will be used to determine
        !          76511:      * whether to allow an error to be pushed or logged.
        !          76512:      * 
        !          76513:      * The return value must be one of the ERRORSTACK_* constants.
        !          76514:      * 
        !          76515:      * This functionality can be used to emulate PEAR's pushErrorHandling, and
        !          76516:      * the PEAR_ERROR_CALLBACK mode, without affecting the integrity of
        !          76517:      * the error stack or logging
        !          76518:      * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
        !          76519:      * @see popCallback()
        !          76520:      * @param string|array $cb
1.1       misho    76521:      */
1.1.1.2 ! misho    76522:     function pushCallback($cb)
1.1       misho    76523:     {
1.1.1.2 ! misho    76524:         array_push($this->_errorCallback, $cb);
1.1       misho    76525:     }
1.1.1.2 ! misho    76526:     
        !          76527:     /**
        !          76528:      * Remove a callback from the error callback stack
        !          76529:      * @see pushCallback()
        !          76530:      * @return array|string|false
        !          76531:      */
        !          76532:     function popCallback()
1.1       misho    76533:     {
1.1.1.2 ! misho    76534:         if (!count($this->_errorCallback)) {
        !          76535:             return false;
1.1       misho    76536:         }
1.1.1.2 ! misho    76537:         return array_pop($this->_errorCallback);
1.1       misho    76538:     }
1.1.1.2 ! misho    76539:     
1.1       misho    76540:     /**
1.1.1.2 ! misho    76541:      * Set a temporary overriding error callback for every package error stack
1.1       misho    76542:      *
1.1.1.2 ! misho    76543:      * Use this to temporarily disable all existing callbacks (can be used
        !          76544:      * to emulate the @ operator, for instance)
        !          76545:      * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
        !          76546:      * @see staticPopCallback(), pushCallback()
        !          76547:      * @param string|array $cb
        !          76548:      * @static
1.1       misho    76549:      */
1.1.1.2 ! misho    76550:     function staticPushCallback($cb)
1.1       misho    76551:     {
1.1.1.2 ! misho    76552:         array_push($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'], $cb);
1.1       misho    76553:     }
1.1.1.2 ! misho    76554:     
1.1       misho    76555:     /**
1.1.1.2 ! misho    76556:      * Remove a temporary overriding error callback
        !          76557:      * @see staticPushCallback()
        !          76558:      * @return array|string|false
        !          76559:      * @static
1.1       misho    76560:      */
1.1.1.2 ! misho    76561:     function staticPopCallback()
1.1       misho    76562:     {
1.1.1.2 ! misho    76563:         $ret = array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']);
        !          76564:         if (!is_array($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'])) {
        !          76565:             $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();
1.1       misho    76566:         }
1.1.1.2 ! misho    76567:         return $ret;
1.1       misho    76568:     }
1.1.1.2 ! misho    76569:     
1.1       misho    76570:     /**
1.1.1.2 ! misho    76571:      * Add an error to the stack
        !          76572:      * 
        !          76573:      * If the message generator exists, it is called with 2 parameters.
        !          76574:      *  - the current Error Stack object
        !          76575:      *  - an array that is in the same format as an error.  Available indices
        !          76576:      *    are 'code', 'package', 'time', 'params', 'level', and 'context'
        !          76577:      * 
        !          76578:      * Next, if the error should contain context information, this is
        !          76579:      * handled by the context grabbing method.
        !          76580:      * Finally, the error is pushed onto the proper error stack
        !          76581:      * @param int    $code      Package-specific error code
        !          76582:      * @param string $level     Error level.  This is NOT spell-checked
        !          76583:      * @param array  $params    associative array of error parameters
        !          76584:      * @param string $msg       Error message, or a portion of it if the message
        !          76585:      *                          is to be generated
        !          76586:      * @param array  $repackage If this error re-packages an error pushed by
        !          76587:      *                          another package, place the array returned from
        !          76588:      *                          {@link pop()} in this parameter
        !          76589:      * @param array  $backtrace Protected parameter: use this to pass in the
        !          76590:      *                          {@link debug_backtrace()} that should be used
        !          76591:      *                          to find error context
        !          76592:      * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also
        !          76593:      * thrown.  If a PEAR_Error is returned, the userinfo
        !          76594:      * property is set to the following array:
        !          76595:      * 
        !          76596:      * <code>
        !          76597:      * array(
        !          76598:      *    'code' => $code,
        !          76599:      *    'params' => $params,
        !          76600:      *    'package' => $this->_package,
        !          76601:      *    'level' => $level,
        !          76602:      *    'time' => time(),
        !          76603:      *    'context' => $context,
        !          76604:      *    'message' => $msg,
        !          76605:      * //['repackage' => $err] repackaged error array/Exception class
        !          76606:      * );
        !          76607:      * </code>
        !          76608:      * 
        !          76609:      * Normally, the previous array is returned.
1.1       misho    76610:      */
1.1.1.2 ! misho    76611:     function push($code, $level = 'error', $params = array(), $msg = false,
        !          76612:                   $repackage = false, $backtrace = false)
1.1       misho    76613:     {
1.1.1.2 ! misho    76614:         $context = false;
        !          76615:         // grab error context
        !          76616:         if ($this->_contextCallback) {
        !          76617:             if (!$backtrace) {
        !          76618:                 $backtrace = debug_backtrace();
1.1       misho    76619:             }
1.1.1.2 ! misho    76620:             $context = call_user_func($this->_contextCallback, $code, $params, $backtrace);
1.1       misho    76621:         }
1.1.1.2 ! misho    76622:         
        !          76623:         // save error
        !          76624:         $time = explode(' ', microtime());
        !          76625:         $time = $time[1] + $time[0];
        !          76626:         $err = array(
        !          76627:                 'code' => $code,
        !          76628:                 'params' => $params,
        !          76629:                 'package' => $this->_package,
        !          76630:                 'level' => $level,
        !          76631:                 'time' => $time,
        !          76632:                 'context' => $context,
        !          76633:                 'message' => $msg,
        !          76634:                );
1.1       misho    76635: 
1.1.1.2 ! misho    76636:         if ($repackage) {
        !          76637:             $err['repackage'] = $repackage;
1.1       misho    76638:         }
                   76639: 
1.1.1.2 ! misho    76640:         // set up the error message, if necessary
        !          76641:         if ($this->_msgCallback) {
        !          76642:             $msg = call_user_func_array($this->_msgCallback,
        !          76643:                                         array(&$this, $err));
        !          76644:             $err['message'] = $msg;
        !          76645:         }        
        !          76646:         $push = $log = true;
        !          76647:         $die = false;
        !          76648:         // try the overriding callback first
        !          76649:         $callback = $this->staticPopCallback();
        !          76650:         if ($callback) {
        !          76651:             $this->staticPushCallback($callback);
1.1       misho    76652:         }
1.1.1.2 ! misho    76653:         if (!is_callable($callback)) {
        !          76654:             // try the local callback next
        !          76655:             $callback = $this->popCallback();
        !          76656:             if (is_callable($callback)) {
        !          76657:                 $this->pushCallback($callback);
        !          76658:             } else {
        !          76659:                 // try the default callback
        !          76660:                 $callback = isset($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package]) ?
        !          76661:                     $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package] :
        !          76662:                     $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']['*'];
1.1       misho    76663:             }
1.1.1.2 ! misho    76664:         }
        !          76665:         if (is_callable($callback)) {
        !          76666:             switch(call_user_func($callback, $err)){
        !          76667:                case PEAR_ERRORSTACK_IGNORE: 
        !          76668:                        return $err;
        !          76669:                        break;
        !          76670:                case PEAR_ERRORSTACK_PUSH: 
        !          76671:                        $log = false;
        !          76672:                        break;
        !          76673:                case PEAR_ERRORSTACK_LOG: 
        !          76674:                        $push = false;
        !          76675:                        break;
        !          76676:                case PEAR_ERRORSTACK_DIE: 
        !          76677:                        $die = true;
        !          76678:                        break;
        !          76679:                 // anything else returned has the same effect as pushandlog
        !          76680:             }
        !          76681:         }
        !          76682:         if ($push) {
        !          76683:             array_unshift($this->_errors, $err);
        !          76684:             if (!isset($this->_errorsByLevel[$err['level']])) {
        !          76685:                 $this->_errorsByLevel[$err['level']] = array();
        !          76686:             }
        !          76687:             $this->_errorsByLevel[$err['level']][] = &$this->_errors[0];
        !          76688:         }
        !          76689:         if ($log) {
        !          76690:             if ($this->_logger || $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']) {
        !          76691:                 $this->_log($err);
1.1       misho    76692:             }
                   76693:         }
1.1.1.2 ! misho    76694:         if ($die) {
        !          76695:             die();
        !          76696:         }
        !          76697:         if ($this->_compat && $push) {
        !          76698:             return $this->raiseError($msg, $code, null, null, $err);
        !          76699:         }
        !          76700:         return $err;
1.1       misho    76701:     }
1.1.1.2 ! misho    76702:     
1.1       misho    76703:     /**
1.1.1.2 ! misho    76704:      * Static version of {@link push()}
        !          76705:      * 
        !          76706:      * @param string $package   Package name this error belongs to
        !          76707:      * @param int    $code      Package-specific error code
        !          76708:      * @param string $level     Error level.  This is NOT spell-checked
        !          76709:      * @param array  $params    associative array of error parameters
        !          76710:      * @param string $msg       Error message, or a portion of it if the message
        !          76711:      *                          is to be generated
        !          76712:      * @param array  $repackage If this error re-packages an error pushed by
        !          76713:      *                          another package, place the array returned from
        !          76714:      *                          {@link pop()} in this parameter
        !          76715:      * @param array  $backtrace Protected parameter: use this to pass in the
        !          76716:      *                          {@link debug_backtrace()} that should be used
        !          76717:      *                          to find error context
        !          76718:      * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also
        !          76719:      *                          thrown.  see docs for {@link push()}
        !          76720:      * @static
1.1       misho    76721:      */
1.1.1.2 ! misho    76722:     function staticPush($package, $code, $level = 'error', $params = array(),
        !          76723:                         $msg = false, $repackage = false, $backtrace = false)
1.1       misho    76724:     {
1.1.1.2 ! misho    76725:         $s = &PEAR_ErrorStack::singleton($package);
        !          76726:         if ($s->_contextCallback) {
        !          76727:             if (!$backtrace) {
        !          76728:                 if (function_exists('debug_backtrace')) {
        !          76729:                     $backtrace = debug_backtrace();
1.1       misho    76730:                 }
                   76731:             }
                   76732:         }
1.1.1.2 ! misho    76733:         return $s->push($code, $level, $params, $msg, $repackage, $backtrace);
1.1       misho    76734:     }
1.1.1.2 ! misho    76735:     
        !          76736:     /**
        !          76737:      * Log an error using PEAR::Log
        !          76738:      * @param array $err Error array
        !          76739:      * @param array $levels Error level => Log constant map
        !          76740:      * @access protected
        !          76741:      */
        !          76742:     function _log($err)
1.1       misho    76743:     {
1.1.1.2 ! misho    76744:         if ($this->_logger) {
        !          76745:             $logger = &$this->_logger;
        !          76746:         } else {
        !          76747:             $logger = &$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'];
1.1       misho    76748:         }
1.1.1.2 ! misho    76749:         if (is_a($logger, 'Log')) {
        !          76750:             $levels = array(
        !          76751:                 'exception' => PEAR_LOG_CRIT,
        !          76752:                 'alert' => PEAR_LOG_ALERT,
        !          76753:                 'critical' => PEAR_LOG_CRIT,
        !          76754:                 'error' => PEAR_LOG_ERR,
        !          76755:                 'warning' => PEAR_LOG_WARNING,
        !          76756:                 'notice' => PEAR_LOG_NOTICE,
        !          76757:                 'info' => PEAR_LOG_INFO,
        !          76758:                 'debug' => PEAR_LOG_DEBUG);
        !          76759:             if (isset($levels[$err['level']])) {
        !          76760:                 $level = $levels[$err['level']];
        !          76761:             } else {
        !          76762:                 $level = PEAR_LOG_INFO;
1.1       misho    76763:             }
1.1.1.2 ! misho    76764:             $logger->log($err['message'], $level, $err);
        !          76765:         } else { // support non-standard logs
        !          76766:             call_user_func($logger, $err);
1.1       misho    76767:         }
                   76768:     }
                   76769: 
1.1.1.2 ! misho    76770:     
        !          76771:     /**
        !          76772:      * Pop an error off of the error stack
        !          76773:      * 
        !          76774:      * @return false|array
        !          76775:      * @since 0.4alpha it is no longer possible to specify a specific error
        !          76776:      * level to return - the last error pushed will be returned, instead
        !          76777:      */
        !          76778:     function pop()
1.1       misho    76779:     {
1.1.1.2 ! misho    76780:         $err = @array_shift($this->_errors);
        !          76781:         if (!is_null($err)) {
        !          76782:             @array_pop($this->_errorsByLevel[$err['level']]);
        !          76783:             if (!count($this->_errorsByLevel[$err['level']])) {
        !          76784:                 unset($this->_errorsByLevel[$err['level']]);
        !          76785:             }
1.1       misho    76786:         }
1.1.1.2 ! misho    76787:         return $err;
1.1       misho    76788:     }
                   76789: 
                   76790:     /**
1.1.1.2 ! misho    76791:      * Pop an error off of the error stack, static method
1.1       misho    76792:      *
1.1.1.2 ! misho    76793:      * @param string package name
        !          76794:      * @return boolean
        !          76795:      * @since PEAR1.5.0a1
1.1       misho    76796:      */
1.1.1.2 ! misho    76797:     function staticPop($package)
1.1       misho    76798:     {
1.1.1.2 ! misho    76799:         if ($package) {
        !          76800:             if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
        !          76801:                 return false;
1.1       misho    76802:             }
1.1.1.2 ! misho    76803:             return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->pop();
1.1       misho    76804:         }
1.1.1.2 ! misho    76805:     }
1.1       misho    76806: 
1.1.1.2 ! misho    76807:     /**
        !          76808:      * Determine whether there are any errors on the stack
        !          76809:      * @param string|array Level name.  Use to determine if any errors
        !          76810:      * of level (string), or levels (array) have been pushed
        !          76811:      * @return boolean
        !          76812:      */
        !          76813:     function hasErrors($level = false)
        !          76814:     {
        !          76815:         if ($level) {
        !          76816:             return isset($this->_errorsByLevel[$level]);
1.1       misho    76817:         }
1.1.1.2 ! misho    76818:         return count($this->_errors);
        !          76819:     }
        !          76820:     
        !          76821:     /**
        !          76822:      * Retrieve all errors since last purge
        !          76823:      * 
        !          76824:      * @param boolean set in order to empty the error stack
        !          76825:      * @param string level name, to return only errors of a particular severity
        !          76826:      * @return array
        !          76827:      */
        !          76828:     function getErrors($purge = false, $level = false)
        !          76829:     {
        !          76830:         if (!$purge) {
        !          76831:             if ($level) {
        !          76832:                 if (!isset($this->_errorsByLevel[$level])) {
        !          76833:                     return array();
        !          76834:                 } else {
        !          76835:                     return $this->_errorsByLevel[$level];
1.1       misho    76836:                 }
                   76837:             } else {
1.1.1.2 ! misho    76838:                 return $this->_errors;
1.1       misho    76839:             }
                   76840:         }
1.1.1.2 ! misho    76841:         if ($level) {
        !          76842:             $ret = $this->_errorsByLevel[$level];
        !          76843:             foreach ($this->_errorsByLevel[$level] as $i => $unused) {
        !          76844:                 // entries are references to the $_errors array
        !          76845:                 $this->_errorsByLevel[$level][$i] = false;
1.1       misho    76846:             }
1.1.1.2 ! misho    76847:             // array_filter removes all entries === false
        !          76848:             $this->_errors = array_filter($this->_errors);
        !          76849:             unset($this->_errorsByLevel[$level]);
        !          76850:             return $ret;
1.1       misho    76851:         }
1.1.1.2 ! misho    76852:         $ret = $this->_errors;
        !          76853:         $this->_errors = array();
        !          76854:         $this->_errorsByLevel = array();
        !          76855:         return $ret;
        !          76856:     }
        !          76857:     
        !          76858:     /**
        !          76859:      * Determine whether there are any errors on a single error stack, or on any error stack
        !          76860:      *
        !          76861:      * The optional parameter can be used to test the existence of any errors without the need of
        !          76862:      * singleton instantiation
        !          76863:      * @param string|false Package name to check for errors
        !          76864:      * @param string Level name to check for a particular severity
        !          76865:      * @return boolean
        !          76866:      * @static
        !          76867:      */
        !          76868:     function staticHasErrors($package = false, $level = false)
        !          76869:     {
        !          76870:         if ($package) {
        !          76871:             if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
        !          76872:                 return false;
1.1       misho    76873:             }
1.1.1.2 ! misho    76874:             return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->hasErrors($level);
1.1       misho    76875:         }
1.1.1.2 ! misho    76876:         foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
        !          76877:             if ($obj->hasErrors($level)) {
        !          76878:                 return true;
        !          76879:             }
1.1       misho    76880:         }
1.1.1.2 ! misho    76881:         return false;
        !          76882:     }
        !          76883:     
        !          76884:     /**
        !          76885:      * Get a list of all errors since last purge, organized by package
        !          76886:      * @since PEAR 1.4.0dev BC break! $level is now in the place $merge used to be
        !          76887:      * @param boolean $purge Set to purge the error stack of existing errors
        !          76888:      * @param string  $level Set to a level name in order to retrieve only errors of a particular level
        !          76889:      * @param boolean $merge Set to return a flat array, not organized by package
        !          76890:      * @param array   $sortfunc Function used to sort a merged array - default
        !          76891:      *        sorts by time, and should be good for most cases
        !          76892:      * @static
        !          76893:      * @return array 
        !          76894:      */
        !          76895:     function staticGetErrors($purge = false, $level = false, $merge = false,
        !          76896:                              $sortfunc = array('PEAR_ErrorStack', '_sortErrors'))
        !          76897:     {
        !          76898:         $ret = array();
        !          76899:         if (!is_callable($sortfunc)) {
        !          76900:             $sortfunc = array('PEAR_ErrorStack', '_sortErrors');
1.1       misho    76901:         }
1.1.1.2 ! misho    76902:         foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
        !          76903:             $test = $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->getErrors($purge, $level);
        !          76904:             if ($test) {
        !          76905:                 if ($merge) {
        !          76906:                     $ret = array_merge($ret, $test);
        !          76907:                 } else {
        !          76908:                     $ret[$package] = $test;
1.1       misho    76909:                 }
                   76910:             }
                   76911:         }
1.1.1.2 ! misho    76912:         if ($merge) {
        !          76913:             usort($ret, $sortfunc);
1.1       misho    76914:         }
1.1.1.2 ! misho    76915:         return $ret;
        !          76916:     }
        !          76917:     
        !          76918:     /**
        !          76919:      * Error sorting function, sorts by time
        !          76920:      * @access private
        !          76921:      */
        !          76922:     function _sortErrors($a, $b)
        !          76923:     {
        !          76924:         if ($a['time'] == $b['time']) {
        !          76925:             return 0;
1.1       misho    76926:         }
1.1.1.2 ! misho    76927:         if ($a['time'] < $b['time']) {
        !          76928:             return 1;
1.1       misho    76929:         }
1.1.1.2 ! misho    76930:         return -1;
        !          76931:     }
1.1       misho    76932: 
1.1.1.2 ! misho    76933:     /**
        !          76934:      * Standard file/line number/function/class context callback
        !          76935:      *
        !          76936:      * This function uses a backtrace generated from {@link debug_backtrace()}
        !          76937:      * and so will not work at all in PHP < 4.3.0.  The frame should
        !          76938:      * reference the frame that contains the source of the error.
        !          76939:      * @return array|false either array('file' => file, 'line' => line,
        !          76940:      *         'function' => function name, 'class' => class name) or
        !          76941:      *         if this doesn't work, then false
        !          76942:      * @param unused
        !          76943:      * @param integer backtrace frame.
        !          76944:      * @param array Results of debug_backtrace()
        !          76945:      * @static
        !          76946:      */
        !          76947:     function getFileLine($code, $params, $backtrace = null)
        !          76948:     {
        !          76949:         if ($backtrace === null) {
        !          76950:             return false;
1.1       misho    76951:         }
1.1.1.2 ! misho    76952:         $frame = 0;
        !          76953:         $functionframe = 1;
        !          76954:         if (!isset($backtrace[1])) {
        !          76955:             $functionframe = 0;
        !          76956:         } else {
        !          76957:             while (isset($backtrace[$functionframe]['function']) &&
        !          76958:                   $backtrace[$functionframe]['function'] == 'eval' &&
        !          76959:                   isset($backtrace[$functionframe + 1])) {
        !          76960:                 $functionframe++;
1.1       misho    76961:             }
                   76962:         }
1.1.1.2 ! misho    76963:         if (isset($backtrace[$frame])) {
        !          76964:             if (!isset($backtrace[$frame]['file'])) {
        !          76965:                 $frame++;
        !          76966:             }
        !          76967:             $funcbacktrace = $backtrace[$functionframe];
        !          76968:             $filebacktrace = $backtrace[$frame];
        !          76969:             $ret = array('file' => $filebacktrace['file'],
        !          76970:                          'line' => $filebacktrace['line']);
        !          76971:             // rearrange for eval'd code or create function errors
        !          76972:             if (strpos($filebacktrace['file'], '(') && 
        !          76973:                  preg_match(';^(.*?)\((\d+)\) : (.*?)\\z;', $filebacktrace['file'],
        !          76974:                   $matches)) {
        !          76975:                 $ret['file'] = $matches[1];
        !          76976:                 $ret['line'] = $matches[2] + 0;
1.1       misho    76977:             }
1.1.1.2 ! misho    76978:             if (isset($funcbacktrace['function']) && isset($backtrace[1])) {
        !          76979:                 if ($funcbacktrace['function'] != 'eval') {
        !          76980:                     if ($funcbacktrace['function'] == '__lambda_func') {
        !          76981:                         $ret['function'] = 'create_function() code';
        !          76982:                     } else {
        !          76983:                         $ret['function'] = $funcbacktrace['function'];
        !          76984:                     }
1.1       misho    76985:                 }
                   76986:             }
1.1.1.2 ! misho    76987:             if (isset($funcbacktrace['class']) && isset($backtrace[1])) {
        !          76988:                 $ret['class'] = $funcbacktrace['class'];
        !          76989:             }
        !          76990:             return $ret;
1.1       misho    76991:         }
1.1.1.2 ! misho    76992:         return false;
        !          76993:     }
        !          76994:     
        !          76995:     /**
        !          76996:      * Standard error message generation callback
        !          76997:      * 
        !          76998:      * This method may also be called by a custom error message generator
        !          76999:      * to fill in template values from the params array, simply
        !          77000:      * set the third parameter to the error message template string to use
        !          77001:      * 
        !          77002:      * The special variable %__msg% is reserved: use it only to specify
        !          77003:      * where a message passed in by the user should be placed in the template,
        !          77004:      * like so:
        !          77005:      * 
        !          77006:      * Error message: %msg% - internal error
        !          77007:      * 
        !          77008:      * If the message passed like so:
        !          77009:      * 
        !          77010:      * <code>
        !          77011:      * $stack->push(ERROR_CODE, 'error', array(), 'server error 500');
        !          77012:      * </code>
        !          77013:      * 
        !          77014:      * The returned error message will be "Error message: server error 500 -
        !          77015:      * internal error"
        !          77016:      * @param PEAR_ErrorStack
        !          77017:      * @param array
        !          77018:      * @param string|false Pre-generated error message template
        !          77019:      * @static
        !          77020:      * @return string
        !          77021:      */
        !          77022:     function getErrorMessage(&$stack, $err, $template = false)
        !          77023:     {
        !          77024:         if ($template) {
        !          77025:             $mainmsg = $template;
        !          77026:         } else {
        !          77027:             $mainmsg = $stack->getErrorMessageTemplate($err['code']);
1.1       misho    77028:         }
1.1.1.2 ! misho    77029:         $mainmsg = str_replace('%__msg%', $err['message'], $mainmsg);
        !          77030:         if (is_array($err['params']) && count($err['params'])) {
        !          77031:             foreach ($err['params'] as $name => $val) {
        !          77032:                 if (is_array($val)) {
        !          77033:                     // @ is needed in case $val is a multi-dimensional array
        !          77034:                     $val = @implode(', ', $val);
        !          77035:                 }
        !          77036:                 if (is_object($val)) {
        !          77037:                     if (method_exists($val, '__toString')) {
        !          77038:                         $val = $val->__toString();
        !          77039:                     } else {
        !          77040:                         PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_OBJTOSTRING,
        !          77041:                             'warning', array('obj' => get_class($val)),
        !          77042:                             'object %obj% passed into getErrorMessage, but has no __toString() method');
        !          77043:                         $val = 'Object';
        !          77044:                     }
1.1       misho    77045:                 }
1.1.1.2 ! misho    77046:                 $mainmsg = str_replace('%' . $name . '%', $val, $mainmsg);
1.1       misho    77047:             }
                   77048:         }
1.1.1.2 ! misho    77049:         return $mainmsg;
1.1       misho    77050:     }
1.1.1.2 ! misho    77051:     
        !          77052:     /**
        !          77053:      * Standard Error Message Template generator from code
        !          77054:      * @return string
        !          77055:      */
        !          77056:     function getErrorMessageTemplate($code)
        !          77057:     {
        !          77058:         if (!isset($this->_errorMsgs[$code])) {
        !          77059:             return '%__msg%';
        !          77060:         }
        !          77061:         return $this->_errorMsgs[$code];
        !          77062:     }
        !          77063:     
        !          77064:     /**
        !          77065:      * Set the Error Message Template array
        !          77066:      * 
        !          77067:      * The array format must be:
        !          77068:      * <pre>
        !          77069:      * array(error code => 'message template',...)
        !          77070:      * </pre>
        !          77071:      * 
        !          77072:      * Error message parameters passed into {@link push()} will be used as input
        !          77073:      * for the error message.  If the template is 'message %foo% was %bar%', and the
        !          77074:      * parameters are array('foo' => 'one', 'bar' => 'six'), the error message returned will
        !          77075:      * be 'message one was six'
        !          77076:      * @return string
        !          77077:      */
        !          77078:     function setErrorMessageTemplate($template)
        !          77079:     {
        !          77080:         $this->_errorMsgs = $template;
        !          77081:     }
        !          77082:     
        !          77083:     
        !          77084:     /**
        !          77085:      * emulate PEAR::raiseError()
        !          77086:      * 
        !          77087:      * @return PEAR_Error
        !          77088:      */
        !          77089:     function raiseError()
        !          77090:     {
        !          77091:         require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
        !          77092:         $args = func_get_args();
        !          77093:         return call_user_func_array(array('PEAR', 'raiseError'), $args);
        !          77094:     }
        !          77095: }
        !          77096: $stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack');
        !          77097: $stack->pushCallback(array('PEAR_ErrorStack', '_handleError'));
        !          77098: ?>
        !          77099: <?php
        !          77100: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
1.1       misho    77101: /**
1.1.1.2 ! misho    77102:  * PEAR_Exception
1.1       misho    77103:  *
                   77104:  * PHP versions 4 and 5
                   77105:  *
                   77106:  * @category   pear
                   77107:  * @package    PEAR
1.1.1.2 ! misho    77108:  * @author     Tomas V. V. Cox <cox@idecnet.com>
        !          77109:  * @author     Hans Lellelid <hans@velum.net>
        !          77110:  * @author     Bertrand Mansion <bmansion@mamasam.com>
1.1       misho    77111:  * @author     Greg Beaver <cellog@php.net>
                   77112:  * @copyright  1997-2009 The Authors
                   77113:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    77114:  * @version    CVS: $Id: Exception.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    77115:  * @link       http://pear.php.net/package/PEAR
1.1.1.2 ! misho    77116:  * @since      File available since Release 1.3.3
1.1       misho    77117:  */
                   77118: 
                   77119: 
                   77120: /**
1.1.1.2 ! misho    77121:  * Base PEAR_Exception Class
1.1       misho    77122:  *
1.1.1.2 ! misho    77123:  * 1) Features:
1.1       misho    77124:  *
1.1.1.2 ! misho    77125:  * - Nestable exceptions (throw new PEAR_Exception($msg, $prev_exception))
        !          77126:  * - Definable triggers, shot when exceptions occur
        !          77127:  * - Pretty and informative error messages
        !          77128:  * - Added more context info available (like class, method or cause)
        !          77129:  * - cause can be a PEAR_Exception or an array of mixed
        !          77130:  *   PEAR_Exceptions/PEAR_ErrorStack warnings
        !          77131:  * - callbacks for specific exception classes and their children
1.1       misho    77132:  *
1.1.1.2 ! misho    77133:  * 2) Ideas:
        !          77134:  *
        !          77135:  * - Maybe a way to define a 'template' for the output
        !          77136:  *
        !          77137:  * 3) Inherited properties from PHP Exception Class:
        !          77138:  *
        !          77139:  * protected $message
        !          77140:  * protected $code
        !          77141:  * protected $line
        !          77142:  * protected $file
        !          77143:  * private   $trace
        !          77144:  *
        !          77145:  * 4) Inherited methods from PHP Exception Class:
        !          77146:  *
        !          77147:  * __clone
        !          77148:  * __construct
        !          77149:  * getMessage
        !          77150:  * getCode
        !          77151:  * getFile
        !          77152:  * getLine
        !          77153:  * getTraceSafe
        !          77154:  * getTraceSafeAsString
        !          77155:  * __toString
        !          77156:  *
        !          77157:  * 5) Usage example
        !          77158:  *
        !          77159:  * <code>
        !          77160:  *  require_once 'PEAR/Exception.php';
        !          77161:  *
        !          77162:  *  class Test {
        !          77163:  *     function foo() {
        !          77164:  *         throw new PEAR_Exception('Error Message', ERROR_CODE);
        !          77165:  *     }
        !          77166:  *  }
        !          77167:  *
        !          77168:  *  function myLogger($pear_exception) {
        !          77169:  *     echo $pear_exception->getMessage();
        !          77170:  *  }
        !          77171:  *  // each time a exception is thrown the 'myLogger' will be called
        !          77172:  *  // (its use is completely optional)
        !          77173:  *  PEAR_Exception::addObserver('myLogger');
        !          77174:  *  $test = new Test;
        !          77175:  *  try {
        !          77176:  *     $test->foo();
        !          77177:  *  } catch (PEAR_Exception $e) {
        !          77178:  *     print $e;
        !          77179:  *  }
        !          77180:  * </code>
1.1       misho    77181:  *
                   77182:  * @category   pear
                   77183:  * @package    PEAR
1.1.1.2 ! misho    77184:  * @author     Tomas V.V.Cox <cox@idecnet.com>
        !          77185:  * @author     Hans Lellelid <hans@velum.net>
        !          77186:  * @author     Bertrand Mansion <bmansion@mamasam.com>
1.1       misho    77187:  * @author     Greg Beaver <cellog@php.net>
                   77188:  * @copyright  1997-2009 The Authors
                   77189:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    77190:  * @version    Release: 1.9.4
1.1       misho    77191:  * @link       http://pear.php.net/package/PEAR
1.1.1.2 ! misho    77192:  * @since      Class available since Release 1.3.3
        !          77193:  *
1.1       misho    77194:  */
1.1.1.2 ! misho    77195: class PEAR_Exception extends Exception
1.1       misho    77196: {
1.1.1.2 ! misho    77197:     const OBSERVER_PRINT = -2;
        !          77198:     const OBSERVER_TRIGGER = -4;
        !          77199:     const OBSERVER_DIE = -8;
        !          77200:     protected $cause;
        !          77201:     private static $_observers = array();
        !          77202:     private static $_uniqueid = 0;
        !          77203:     private $_trace;
1.1       misho    77204: 
                   77205:     /**
1.1.1.2 ! misho    77206:      * Supported signatures:
        !          77207:      *  - PEAR_Exception(string $message);
        !          77208:      *  - PEAR_Exception(string $message, int $code);
        !          77209:      *  - PEAR_Exception(string $message, Exception $cause);
        !          77210:      *  - PEAR_Exception(string $message, Exception $cause, int $code);
        !          77211:      *  - PEAR_Exception(string $message, PEAR_Error $cause);
        !          77212:      *  - PEAR_Exception(string $message, PEAR_Error $cause, int $code);
        !          77213:      *  - PEAR_Exception(string $message, array $causes);
        !          77214:      *  - PEAR_Exception(string $message, array $causes, int $code);
        !          77215:      * @param string exception message
        !          77216:      * @param int|Exception|PEAR_Error|array|null exception cause
        !          77217:      * @param int|null exception code or null
1.1       misho    77218:      */
1.1.1.2 ! misho    77219:     public function __construct($message, $p2 = null, $p3 = null)
1.1       misho    77220:     {
1.1.1.2 ! misho    77221:         if (is_int($p2)) {
        !          77222:             $code = $p2;
        !          77223:             $this->cause = null;
        !          77224:         } elseif (is_object($p2) || is_array($p2)) {
        !          77225:             // using is_object allows both Exception and PEAR_Error
        !          77226:             if (is_object($p2) && !($p2 instanceof Exception)) {
        !          77227:                 if (!class_exists('PEAR_Error') || !($p2 instanceof PEAR_Error)) {
        !          77228:                     throw new PEAR_Exception('exception cause must be Exception, ' .
        !          77229:                         'array, or PEAR_Error');
1.1       misho    77230:                 }
                   77231:             }
1.1.1.2 ! misho    77232:             $code = $p3;
        !          77233:             if (is_array($p2) && isset($p2['message'])) {
        !          77234:                 // fix potential problem of passing in a single warning
        !          77235:                 $p2 = array($p2);
1.1       misho    77236:             }
1.1.1.2 ! misho    77237:             $this->cause = $p2;
        !          77238:         } else {
        !          77239:             $code = null;
        !          77240:             $this->cause = null;
1.1       misho    77241:         }
1.1.1.2 ! misho    77242:         parent::__construct($message, $code);
        !          77243:         $this->signal();
1.1       misho    77244:     }
                   77245: 
                   77246:     /**
1.1.1.2 ! misho    77247:      * @param mixed $callback  - A valid php callback, see php func is_callable()
        !          77248:      *                         - A PEAR_Exception::OBSERVER_* constant
        !          77249:      *                         - An array(const PEAR_Exception::OBSERVER_*,
        !          77250:      *                           mixed $options)
        !          77251:      * @param string $label    The name of the observer. Use this if you want
        !          77252:      *                         to remove it later with removeObserver()
1.1       misho    77253:      */
1.1.1.2 ! misho    77254:     public static function addObserver($callback, $label = 'default')
1.1       misho    77255:     {
1.1.1.2 ! misho    77256:         self::$_observers[$label] = $callback;
        !          77257:     }
1.1       misho    77258: 
1.1.1.2 ! misho    77259:     public static function removeObserver($label = 'default')
        !          77260:     {
        !          77261:         unset(self::$_observers[$label]);
        !          77262:     }
1.1       misho    77263: 
1.1.1.2 ! misho    77264:     /**
        !          77265:      * @return int unique identifier for an observer
        !          77266:      */
        !          77267:     public static function getUniqueId()
        !          77268:     {
        !          77269:         return self::$_uniqueid++;
1.1       misho    77270:     }
                   77271: 
1.1.1.2 ! misho    77272:     private function signal()
1.1       misho    77273:     {
1.1.1.2 ! misho    77274:         foreach (self::$_observers as $func) {
        !          77275:             if (is_callable($func)) {
        !          77276:                 call_user_func($func, $this);
        !          77277:                 continue;
        !          77278:             }
        !          77279:             settype($func, 'array');
        !          77280:             switch ($func[0]) {
        !          77281:                 case self::OBSERVER_PRINT :
        !          77282:                     $f = (isset($func[1])) ? $func[1] : '%s';
        !          77283:                     printf($f, $this->getMessage());
        !          77284:                     break;
        !          77285:                 case self::OBSERVER_TRIGGER :
        !          77286:                     $f = (isset($func[1])) ? $func[1] : E_USER_NOTICE;
        !          77287:                     trigger_error($this->getMessage(), $f);
        !          77288:                     break;
        !          77289:                 case self::OBSERVER_DIE :
        !          77290:                     $f = (isset($func[1])) ? $func[1] : '%s';
        !          77291:                     die(printf($f, $this->getMessage()));
        !          77292:                     break;
        !          77293:                 default:
        !          77294:                     trigger_error('invalid observer type', E_USER_WARNING);
        !          77295:             }
        !          77296:         }
1.1       misho    77297:     }
                   77298: 
1.1.1.2 ! misho    77299:     /**
        !          77300:      * Return specific error information that can be used for more detailed
        !          77301:      * error messages or translation.
        !          77302:      *
        !          77303:      * This method may be overridden in child exception classes in order
        !          77304:      * to add functionality not present in PEAR_Exception and is a placeholder
        !          77305:      * to define API
        !          77306:      *
        !          77307:      * The returned array must be an associative array of parameter => value like so:
        !          77308:      * <pre>
        !          77309:      * array('name' => $name, 'context' => array(...))
        !          77310:      * </pre>
        !          77311:      * @return array
        !          77312:      */
        !          77313:     public function getErrorData()
1.1       misho    77314:     {
1.1.1.2 ! misho    77315:         return array();
1.1       misho    77316:     }
                   77317: 
1.1.1.2 ! misho    77318:     /**
        !          77319:      * Returns the exception that caused this exception to be thrown
        !          77320:      * @access public
        !          77321:      * @return Exception|array The context of the exception
        !          77322:      */
        !          77323:     public function getCause()
1.1       misho    77324:     {
1.1.1.2 ! misho    77325:         return $this->cause;
1.1       misho    77326:     }
                   77327: 
                   77328:     /**
1.1.1.2 ! misho    77329:      * Function must be public to call on caused exceptions
        !          77330:      * @param array
1.1       misho    77331:      */
1.1.1.2 ! misho    77332:     public function getCauseMessage(&$causes)
1.1       misho    77333:     {
1.1.1.2 ! misho    77334:         $trace = $this->getTraceSafe();
        !          77335:         $cause = array('class'   => get_class($this),
        !          77336:                        'message' => $this->message,
        !          77337:                        'file' => 'unknown',
        !          77338:                        'line' => 'unknown');
        !          77339:         if (isset($trace[0])) {
        !          77340:             if (isset($trace[0]['file'])) {
        !          77341:                 $cause['file'] = $trace[0]['file'];
        !          77342:                 $cause['line'] = $trace[0]['line'];
1.1       misho    77343:             }
1.1.1.2 ! misho    77344:         }
        !          77345:         $causes[] = $cause;
        !          77346:         if ($this->cause instanceof PEAR_Exception) {
        !          77347:             $this->cause->getCauseMessage($causes);
        !          77348:         } elseif ($this->cause instanceof Exception) {
        !          77349:             $causes[] = array('class'   => get_class($this->cause),
        !          77350:                               'message' => $this->cause->getMessage(),
        !          77351:                               'file' => $this->cause->getFile(),
        !          77352:                               'line' => $this->cause->getLine());
        !          77353:         } elseif (class_exists('PEAR_Error') && $this->cause instanceof PEAR_Error) {
        !          77354:             $causes[] = array('class' => get_class($this->cause),
        !          77355:                               'message' => $this->cause->getMessage(),
        !          77356:                               'file' => 'unknown',
        !          77357:                               'line' => 'unknown');
        !          77358:         } elseif (is_array($this->cause)) {
        !          77359:             foreach ($this->cause as $cause) {
        !          77360:                 if ($cause instanceof PEAR_Exception) {
        !          77361:                     $cause->getCauseMessage($causes);
        !          77362:                 } elseif ($cause instanceof Exception) {
        !          77363:                     $causes[] = array('class'   => get_class($cause),
        !          77364:                                    'message' => $cause->getMessage(),
        !          77365:                                    'file' => $cause->getFile(),
        !          77366:                                    'line' => $cause->getLine());
        !          77367:                 } elseif (class_exists('PEAR_Error') && $cause instanceof PEAR_Error) {
        !          77368:                     $causes[] = array('class' => get_class($cause),
        !          77369:                                       'message' => $cause->getMessage(),
        !          77370:                                       'file' => 'unknown',
        !          77371:                                       'line' => 'unknown');
        !          77372:                 } elseif (is_array($cause) && isset($cause['message'])) {
        !          77373:                     // PEAR_ErrorStack warning
        !          77374:                     $causes[] = array(
        !          77375:                         'class' => $cause['package'],
        !          77376:                         'message' => $cause['message'],
        !          77377:                         'file' => isset($cause['context']['file']) ?
        !          77378:                                             $cause['context']['file'] :
        !          77379:                                             'unknown',
        !          77380:                         'line' => isset($cause['context']['line']) ?
        !          77381:                                             $cause['context']['line'] :
        !          77382:                                             'unknown',
        !          77383:                     );
1.1       misho    77384:                 }
                   77385:             }
                   77386:         }
                   77387:     }
                   77388: 
1.1.1.2 ! misho    77389:     public function getTraceSafe()
1.1       misho    77390:     {
1.1.1.2 ! misho    77391:         if (!isset($this->_trace)) {
        !          77392:             $this->_trace = $this->getTrace();
        !          77393:             if (empty($this->_trace)) {
        !          77394:                 $backtrace = debug_backtrace();
        !          77395:                 $this->_trace = array($backtrace[count($backtrace)-1]);
        !          77396:             }
1.1       misho    77397:         }
1.1.1.2 ! misho    77398:         return $this->_trace;
        !          77399:     }
1.1       misho    77400: 
1.1.1.2 ! misho    77401:     public function getErrorClass()
        !          77402:     {
        !          77403:         $trace = $this->getTraceSafe();
        !          77404:         return $trace[0]['class'];
1.1       misho    77405:     }
                   77406: 
1.1.1.2 ! misho    77407:     public function getErrorMethod()
1.1       misho    77408:     {
1.1.1.2 ! misho    77409:         $trace = $this->getTraceSafe();
        !          77410:         return $trace[0]['function'];
1.1       misho    77411:     }
                   77412: 
1.1.1.2 ! misho    77413:     public function __toString()
1.1       misho    77414:     {
1.1.1.2 ! misho    77415:         if (isset($_SERVER['REQUEST_URI'])) {
        !          77416:             return $this->toHtml();
        !          77417:         }
        !          77418:         return $this->toText();
1.1       misho    77419:     }
                   77420: 
1.1.1.2 ! misho    77421:     public function toHtml()
1.1       misho    77422:     {
1.1.1.2 ! misho    77423:         $trace = $this->getTraceSafe();
        !          77424:         $causes = array();
        !          77425:         $this->getCauseMessage($causes);
        !          77426:         $html =  '<table style="border: 1px" cellspacing="0">' . "\n";
        !          77427:         foreach ($causes as $i => $cause) {
        !          77428:             $html .= '<tr><td colspan="3" style="background: #ff9999">'
        !          77429:                . str_repeat('-', $i) . ' <b>' . $cause['class'] . '</b>: '
        !          77430:                . htmlspecialchars($cause['message']) . ' in <b>' . $cause['file'] . '</b> '
        !          77431:                . 'on line <b>' . $cause['line'] . '</b>'
        !          77432:                . "</td></tr>\n";
1.1       misho    77433:         }
1.1.1.2 ! misho    77434:         $html .= '<tr><td colspan="3" style="background-color: #aaaaaa; text-align: center; font-weight: bold;">Exception trace</td></tr>' . "\n"
        !          77435:                . '<tr><td style="text-align: center; background: #cccccc; width:20px; font-weight: bold;">#</td>'
        !          77436:                . '<td style="text-align: center; background: #cccccc; font-weight: bold;">Function</td>'
        !          77437:                . '<td style="text-align: center; background: #cccccc; font-weight: bold;">Location</td></tr>' . "\n";
1.1       misho    77438: 
1.1.1.2 ! misho    77439:         foreach ($trace as $k => $v) {
        !          77440:             $html .= '<tr><td style="text-align: center;">' . $k . '</td>'
        !          77441:                    . '<td>';
        !          77442:             if (!empty($v['class'])) {
        !          77443:                 $html .= $v['class'] . $v['type'];
        !          77444:             }
        !          77445:             $html .= $v['function'];
        !          77446:             $args = array();
        !          77447:             if (!empty($v['args'])) {
        !          77448:                 foreach ($v['args'] as $arg) {
        !          77449:                     if (is_null($arg)) $args[] = 'null';
        !          77450:                     elseif (is_array($arg)) $args[] = 'Array';
        !          77451:                     elseif (is_object($arg)) $args[] = 'Object('.get_class($arg).')';
        !          77452:                     elseif (is_bool($arg)) $args[] = $arg ? 'true' : 'false';
        !          77453:                     elseif (is_int($arg) || is_double($arg)) $args[] = $arg;
        !          77454:                     else {
        !          77455:                         $arg = (string)$arg;
        !          77456:                         $str = htmlspecialchars(substr($arg, 0, 16));
        !          77457:                         if (strlen($arg) > 16) $str .= '&hellip;';
        !          77458:                         $args[] = "'" . $str . "'";
1.1       misho    77459:                     }
                   77460:                 }
                   77461:             }
1.1.1.2 ! misho    77462:             $html .= '(' . implode(', ',$args) . ')'
        !          77463:                    . '</td>'
        !          77464:                    . '<td>' . (isset($v['file']) ? $v['file'] : 'unknown')
        !          77465:                    . ':' . (isset($v['line']) ? $v['line'] : 'unknown')
        !          77466:                    . '</td></tr>' . "\n";
1.1       misho    77467:         }
1.1.1.2 ! misho    77468:         $html .= '<tr><td style="text-align: center;">' . ($k+1) . '</td>'
        !          77469:                . '<td>{main}</td>'
        !          77470:                . '<td>&nbsp;</td></tr>' . "\n"
        !          77471:                . '</table>';
        !          77472:         return $html;
1.1       misho    77473:     }
                   77474: 
1.1.1.2 ! misho    77475:     public function toText()
1.1       misho    77476:     {
1.1.1.2 ! misho    77477:         $causes = array();
        !          77478:         $this->getCauseMessage($causes);
        !          77479:         $causeMsg = '';
        !          77480:         foreach ($causes as $i => $cause) {
        !          77481:             $causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': '
        !          77482:                    . $cause['message'] . ' in ' . $cause['file']
        !          77483:                    . ' on line ' . $cause['line'] . "\n";
        !          77484:         }
        !          77485:         return $causeMsg . $this->getTraceAsString();
        !          77486:     }
        !          77487: }<?php
        !          77488: if ($skipmsg) {
        !          77489:     $a = &new $ec($code, $mode, $options, $userinfo);
        !          77490: } else {
        !          77491:     $a = &new $ec($message, $code, $mode, $options, $userinfo);
        !          77492: }
        !          77493: ?><?php
        !          77494: /**
        !          77495:  * PEAR_Frontend, the singleton-based frontend for user input/output
        !          77496:  *
        !          77497:  * PHP versions 4 and 5
        !          77498:  *
        !          77499:  * @category   pear
        !          77500:  * @package    PEAR
        !          77501:  * @author     Greg Beaver <cellog@php.net>
        !          77502:  * @copyright  1997-2009 The Authors
        !          77503:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          77504:  * @version    CVS: $Id: Frontend.php 313023 2011-07-06 19:17:11Z dufuz $
        !          77505:  * @link       http://pear.php.net/package/PEAR
        !          77506:  * @since      File available since Release 1.4.0a1
        !          77507:  */
1.1       misho    77508: 
1.1.1.2 ! misho    77509: /**
        !          77510:  * Include error handling
        !          77511:  */
        !          77512: //require_once 'PEAR.php';
1.1       misho    77513: 
1.1.1.2 ! misho    77514: /**
        !          77515:  * Which user interface class is being used.
        !          77516:  * @var string class name
        !          77517:  */
        !          77518: $GLOBALS['_PEAR_FRONTEND_CLASS'] = 'PEAR_Frontend_CLI';
1.1       misho    77519: 
1.1.1.2 ! misho    77520: /**
        !          77521:  * Instance of $_PEAR_Command_uiclass.
        !          77522:  * @var object
        !          77523:  */
        !          77524: $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = null;
1.1       misho    77525: 
1.1.1.2 ! misho    77526: /**
        !          77527:  * Singleton-based frontend for PEAR user input/output
        !          77528:  *
        !          77529:  * @category   pear
        !          77530:  * @package    PEAR
        !          77531:  * @author     Greg Beaver <cellog@php.net>
        !          77532:  * @copyright  1997-2009 The Authors
        !          77533:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          77534:  * @version    Release: 1.9.4
        !          77535:  * @link       http://pear.php.net/package/PEAR
        !          77536:  * @since      Class available since Release 1.4.0a1
        !          77537:  */
        !          77538: class PEAR_Frontend extends PEAR
        !          77539: {
        !          77540:     /**
        !          77541:      * Retrieve the frontend object
        !          77542:      * @return PEAR_Frontend_CLI|PEAR_Frontend_Web|PEAR_Frontend_Gtk
        !          77543:      * @static
        !          77544:      */
        !          77545:     function &singleton($type = null)
        !          77546:     {
        !          77547:         if ($type === null) {
        !          77548:             if (!isset($GLOBALS['_PEAR_FRONTEND_SINGLETON'])) {
        !          77549:                 $a = false;
        !          77550:                 return $a;
1.1       misho    77551:             }
1.1.1.2 ! misho    77552:             return $GLOBALS['_PEAR_FRONTEND_SINGLETON'];
        !          77553:         }
1.1       misho    77554: 
1.1.1.2 ! misho    77555:         $a = PEAR_Frontend::setFrontendClass($type);
        !          77556:         return $a;
        !          77557:     }
1.1       misho    77558: 
1.1.1.2 ! misho    77559:     /**
        !          77560:      * Set the frontend class that will be used by calls to {@link singleton()}
        !          77561:      *
        !          77562:      * Frontends are expected to conform to the PEAR naming standard of
        !          77563:      * _ => DIRECTORY_SEPARATOR (PEAR_Frontend_CLI is in PEAR/Frontend/CLI.php)
        !          77564:      * @param string $uiclass full class name
        !          77565:      * @return PEAR_Frontend
        !          77566:      * @static
        !          77567:      */
        !          77568:     function &setFrontendClass($uiclass)
        !          77569:     {
        !          77570:         if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) &&
        !          77571:               is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], $uiclass)) {
        !          77572:             return $GLOBALS['_PEAR_FRONTEND_SINGLETON'];
        !          77573:         }
1.1       misho    77574: 
1.1.1.2 ! misho    77575:         if (!class_exists($uiclass)) {
        !          77576:             $file = 'phar://install-pear-nozlib.phar/' . str_replace('_', '/', $uiclass) . '.php';
        !          77577:             if (PEAR_Frontend::isIncludeable($file)) {
        !          77578:                 include_once $file;
1.1       misho    77579:             }
1.1.1.2 ! misho    77580:         }
1.1       misho    77581: 
1.1.1.2 ! misho    77582:         if (class_exists($uiclass)) {
        !          77583:             $obj = &new $uiclass;
        !          77584:             // quick test to see if this class implements a few of the most
        !          77585:             // important frontend methods
        !          77586:             if (is_a($obj, 'PEAR_Frontend')) {
        !          77587:                 $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$obj;
        !          77588:                 $GLOBALS['_PEAR_FRONTEND_CLASS'] = $uiclass;
        !          77589:                 return $obj;
1.1       misho    77590:             }
                   77591: 
1.1.1.2 ! misho    77592:             $err = PEAR::raiseError("not a frontend class: $uiclass");
        !          77593:             return $err;
1.1       misho    77594:         }
1.1.1.2 ! misho    77595: 
        !          77596:         $err = PEAR::raiseError("no such class: $uiclass");
        !          77597:         return $err;
1.1       misho    77598:     }
                   77599: 
1.1.1.2 ! misho    77600:     /**
        !          77601:      * Set the frontend class that will be used by calls to {@link singleton()}
        !          77602:      *
        !          77603:      * Frontends are expected to be a descendant of PEAR_Frontend
        !          77604:      * @param PEAR_Frontend
        !          77605:      * @return PEAR_Frontend
        !          77606:      * @static
        !          77607:      */
        !          77608:     function &setFrontendObject($uiobject)
1.1       misho    77609:     {
1.1.1.2 ! misho    77610:         if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) &&
        !          77611:               is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], get_class($uiobject))) {
        !          77612:             return $GLOBALS['_PEAR_FRONTEND_SINGLETON'];
1.1       misho    77613:         }
                   77614: 
1.1.1.2 ! misho    77615:         if (!is_a($uiobject, 'PEAR_Frontend')) {
        !          77616:             $err = PEAR::raiseError('not a valid frontend class: (' .
        !          77617:                 get_class($uiobject) . ')');
        !          77618:             return $err;
1.1       misho    77619:         }
                   77620: 
1.1.1.2 ! misho    77621:         $GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$uiobject;
        !          77622:         $GLOBALS['_PEAR_FRONTEND_CLASS'] = get_class($uiobject);
        !          77623:         return $uiobject;
        !          77624:     }
1.1       misho    77625: 
1.1.1.2 ! misho    77626:     /**
        !          77627:      * @param string $path relative or absolute include path
        !          77628:      * @return boolean
        !          77629:      * @static
        !          77630:      */
        !          77631:     function isIncludeable($path)
        !          77632:     {
        !          77633:         if (file_exists($path) && is_readable($path)) {
        !          77634:             return true;
1.1       misho    77635:         }
                   77636: 
1.1.1.2 ! misho    77637:         $fp = @fopen($path, 'r', true);
        !          77638:         if ($fp) {
        !          77639:             fclose($fp);
        !          77640:             return true;
1.1       misho    77641:         }
                   77642: 
1.1.1.2 ! misho    77643:         return false;
        !          77644:     }
1.1       misho    77645: 
1.1.1.2 ! misho    77646:     /**
        !          77647:      * @param PEAR_Config
        !          77648:      */
        !          77649:     function setConfig(&$config)
        !          77650:     {
        !          77651:     }
1.1       misho    77652: 
1.1.1.2 ! misho    77653:     /**
        !          77654:      * This can be overridden to allow session-based temporary file management
        !          77655:      *
        !          77656:      * By default, all files are deleted at the end of a session.  The web installer
        !          77657:      * needs to be able to sustain a list over many sessions in order to support
        !          77658:      * user interaction with install scripts
        !          77659:      */
        !          77660:     function addTempFile($file)
        !          77661:     {
        !          77662:         $GLOBALS['_PEAR_Common_tempfiles'][] = $file;
        !          77663:     }
1.1       misho    77664: 
1.1.1.2 ! misho    77665:     /**
        !          77666:      * Log an action
        !          77667:      *
        !          77668:      * @param string $msg the message to log
        !          77669:      * @param boolean $append_crlf
        !          77670:      * @return boolean true
        !          77671:      * @abstract
        !          77672:      */
        !          77673:     function log($msg, $append_crlf = true)
        !          77674:     {
        !          77675:     }
1.1       misho    77676: 
1.1.1.2 ! misho    77677:     /**
        !          77678:      * Run a post-installation script
        !          77679:      *
        !          77680:      * @param array $scripts array of post-install scripts
        !          77681:      * @abstract
        !          77682:      */
        !          77683:     function runPostinstallScripts(&$scripts)
        !          77684:     {
        !          77685:     }
1.1       misho    77686: 
1.1.1.2 ! misho    77687:     /**
        !          77688:      * Display human-friendly output formatted depending on the
        !          77689:      * $command parameter.
        !          77690:      *
        !          77691:      * This should be able to handle basic output data with no command
        !          77692:      * @param mixed  $data    data structure containing the information to display
        !          77693:      * @param string $command command from which this method was called
        !          77694:      * @abstract
        !          77695:      */
        !          77696:     function outputData($data, $command = '_default')
        !          77697:     {
        !          77698:     }
1.1       misho    77699: 
1.1.1.2 ! misho    77700:     /**
        !          77701:      * Display a modal form dialog and return the given input
        !          77702:      *
        !          77703:      * A frontend that requires multiple requests to retrieve and process
        !          77704:      * data must take these needs into account, and implement the request
        !          77705:      * handling code.
        !          77706:      * @param string $command  command from which this method was called
        !          77707:      * @param array  $prompts  associative array. keys are the input field names
        !          77708:      *                         and values are the description
        !          77709:      * @param array  $types    array of input field types (text, password,
        !          77710:      *                         etc.) keys have to be the same like in $prompts
        !          77711:      * @param array  $defaults array of default values. again keys have
        !          77712:      *                         to be the same like in $prompts.  Do not depend
        !          77713:      *                         on a default value being set.
        !          77714:      * @return array input sent by the user
        !          77715:      * @abstract
        !          77716:      */
        !          77717:     function userDialog($command, $prompts, $types = array(), $defaults = array())
        !          77718:     {
1.1       misho    77719:     }
1.1.1.2 ! misho    77720: }<?php
        !          77721: /**
        !          77722:  * PEAR_Frontend_CLI
        !          77723:  *
        !          77724:  * PHP versions 4 and 5
        !          77725:  *
        !          77726:  * @category   pear
        !          77727:  * @package    PEAR
        !          77728:  * @author     Stig Bakken <ssb@php.net>
        !          77729:  * @author     Greg Beaver <cellog@php.net>
        !          77730:  * @copyright  1997-2009 The Authors
        !          77731:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          77732:  * @version    CVS: $Id: CLI.php 313023 2011-07-06 19:17:11Z dufuz $
        !          77733:  * @link       http://pear.php.net/package/PEAR
        !          77734:  * @since      File available since Release 0.1
        !          77735:  */
        !          77736: /**
        !          77737:  * base class
        !          77738:  */
        !          77739: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Frontend.php';
1.1       misho    77740: 
1.1.1.2 ! misho    77741: /**
        !          77742:  * Command-line Frontend for the PEAR Installer
        !          77743:  * @category   pear
        !          77744:  * @package    PEAR
        !          77745:  * @author     Stig Bakken <ssb@php.net>
        !          77746:  * @author     Greg Beaver <cellog@php.net>
        !          77747:  * @copyright  1997-2009 The Authors
        !          77748:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          77749:  * @version    Release: 1.9.4
        !          77750:  * @link       http://pear.php.net/package/PEAR
        !          77751:  * @since      Class available since Release 0.1
        !          77752:  */
        !          77753: class PEAR_Frontend_CLI extends PEAR_Frontend
        !          77754: {
        !          77755:     /**
        !          77756:      * What type of user interface this frontend is for.
        !          77757:      * @var string
        !          77758:      * @access public
        !          77759:      */
        !          77760:     var $type = 'CLI';
        !          77761:     var $lp = ''; // line prefix
        !          77762: 
        !          77763:     var $params = array();
        !          77764:     var $term = array(
        !          77765:         'bold'   => '',
        !          77766:         'normal' => '',
        !          77767:     );
        !          77768: 
        !          77769:     function PEAR_Frontend_CLI()
1.1       misho    77770:     {
1.1.1.2 ! misho    77771:         parent::PEAR();
        !          77772:         $term = getenv('TERM'); //(cox) $_ENV is empty for me in 4.1.1
        !          77773:         if (function_exists('posix_isatty') && !posix_isatty(1)) {
        !          77774:             // output is being redirected to a file or through a pipe
        !          77775:         } elseif ($term) {
        !          77776:             if (preg_match('/^(xterm|vt220|linux)/', $term)) {
        !          77777:                 $this->term['bold']   = sprintf("%c%c%c%c", 27, 91, 49, 109);
        !          77778:                 $this->term['normal'] = sprintf("%c%c%c", 27, 91, 109);
        !          77779:             } elseif (preg_match('/^vt100/', $term)) {
        !          77780:                 $this->term['bold']   = sprintf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0);
        !          77781:                 $this->term['normal'] = sprintf("%c%c%c%c%c", 27, 91, 109, 0, 0);
        !          77782:             }
        !          77783:         } elseif (OS_WINDOWS) {
        !          77784:             // XXX add ANSI codes here
        !          77785:         }
        !          77786:     }
1.1       misho    77787: 
1.1.1.2 ! misho    77788:     /**
        !          77789:      * @param object PEAR_Error object
        !          77790:      */
        !          77791:     function displayError($e)
        !          77792:     {
        !          77793:         return $this->_displayLine($e->getMessage());
        !          77794:     }
1.1       misho    77795: 
1.1.1.2 ! misho    77796:     /**
        !          77797:      * @param object PEAR_Error object
        !          77798:      */
        !          77799:     function displayFatalError($eobj)
        !          77800:     {
        !          77801:         $this->displayError($eobj);
        !          77802:         if (class_exists('PEAR_Config')) {
        !          77803:             $config = &PEAR_Config::singleton();
        !          77804:             if ($config->get('verbose') > 5) {
        !          77805:                 if (function_exists('debug_print_backtrace')) {
        !          77806:                     debug_print_backtrace();
        !          77807:                     exit(1);
        !          77808:                 }
1.1       misho    77809: 
1.1.1.2 ! misho    77810:                 $raised = false;
        !          77811:                 foreach (debug_backtrace() as $i => $frame) {
        !          77812:                     if (!$raised) {
        !          77813:                         if (isset($frame['class'])
        !          77814:                             && strtolower($frame['class']) == 'pear'
        !          77815:                             && strtolower($frame['function']) == 'raiseerror'
        !          77816:                         ) {
        !          77817:                             $raised = true;
1.1       misho    77818:                         } else {
1.1.1.2 ! misho    77819:                             continue;
1.1       misho    77820:                         }
                   77821:                     }
                   77822: 
1.1.1.2 ! misho    77823:                     $frame['class']    = !isset($frame['class'])    ? '' : $frame['class'];
        !          77824:                     $frame['type']     = !isset($frame['type'])     ? '' : $frame['type'];
        !          77825:                     $frame['function'] = !isset($frame['function']) ? '' : $frame['function'];
        !          77826:                     $frame['line']     = !isset($frame['line'])     ? '' : $frame['line'];
        !          77827:                     $this->_displayLine("#$i: $frame[class]$frame[type]$frame[function] $frame[line]");
1.1       misho    77828:                 }
1.1.1.2 ! misho    77829:             }
        !          77830:         }
1.1       misho    77831: 
1.1.1.2 ! misho    77832:         exit(1);
        !          77833:     }
1.1       misho    77834: 
1.1.1.2 ! misho    77835:     /**
        !          77836:      * Instruct the runInstallScript method to skip a paramgroup that matches the
        !          77837:      * id value passed in.
        !          77838:      *
        !          77839:      * This method is useful for dynamically configuring which sections of a post-install script
        !          77840:      * will be run based on the user's setup, which is very useful for making flexible
        !          77841:      * post-install scripts without losing the cross-Frontend ability to retrieve user input
        !          77842:      * @param string
        !          77843:      */
        !          77844:     function skipParamgroup($id)
        !          77845:     {
        !          77846:         $this->_skipSections[$id] = true;
        !          77847:     }
1.1       misho    77848: 
1.1.1.2 ! misho    77849:     function runPostinstallScripts(&$scripts)
        !          77850:     {
        !          77851:         foreach ($scripts as $i => $script) {
        !          77852:             $this->runInstallScript($scripts[$i]->_params, $scripts[$i]->_obj);
        !          77853:         }
        !          77854:     }
1.1       misho    77855: 
1.1.1.2 ! misho    77856:     /**
        !          77857:      * @param array $xml contents of postinstallscript tag
        !          77858:      * @param object $script post-installation script
        !          77859:      * @param string install|upgrade
        !          77860:      */
        !          77861:     function runInstallScript($xml, &$script)
        !          77862:     {
        !          77863:         $this->_skipSections = array();
        !          77864:         if (!is_array($xml) || !isset($xml['paramgroup'])) {
        !          77865:             $script->run(array(), '_default');
        !          77866:             return;
        !          77867:         }
        !          77868: 
        !          77869:         $completedPhases = array();
        !          77870:         if (!isset($xml['paramgroup'][0])) {
        !          77871:             $xml['paramgroup'] = array($xml['paramgroup']);
        !          77872:         }
        !          77873: 
        !          77874:         foreach ($xml['paramgroup'] as $group) {
        !          77875:             if (isset($this->_skipSections[$group['id']])) {
        !          77876:                 // the post-install script chose to skip this section dynamically
        !          77877:                 continue;
        !          77878:             }
        !          77879: 
        !          77880:             if (isset($group['name'])) {
        !          77881:                 $paramname = explode('::', $group['name']);
        !          77882:                 if ($lastgroup['id'] != $paramname[0]) {
        !          77883:                     continue;
        !          77884:                 }
        !          77885: 
        !          77886:                 $group['name'] = $paramname[1];
        !          77887:                 if (!isset($answers)) {
        !          77888:                     return;
        !          77889:                 }
        !          77890: 
        !          77891:                 if (isset($answers[$group['name']])) {
        !          77892:                     switch ($group['conditiontype']) {
        !          77893:                         case '=' :
        !          77894:                             if ($answers[$group['name']] != $group['value']) {
        !          77895:                                 continue 2;
        !          77896:                             }
        !          77897:                         break;
        !          77898:                         case '!=' :
        !          77899:                             if ($answers[$group['name']] == $group['value']) {
        !          77900:                                 continue 2;
        !          77901:                             }
        !          77902:                         break;
        !          77903:                         case 'preg_match' :
        !          77904:                             if (!@preg_match('/' . $group['value'] . '/',
        !          77905:                                   $answers[$group['name']])) {
        !          77906:                                 continue 2;
        !          77907:                             }
        !          77908:                         break;
        !          77909:                         default :
        !          77910:                         return;
1.1       misho    77911:                     }
                   77912:                 }
1.1.1.2 ! misho    77913:             }
1.1       misho    77914: 
1.1.1.2 ! misho    77915:             $lastgroup = $group;
        !          77916:             if (isset($group['instructions'])) {
        !          77917:                 $this->_display($group['instructions']);
        !          77918:             }
1.1       misho    77919: 
1.1.1.2 ! misho    77920:             if (!isset($group['param'][0])) {
        !          77921:                 $group['param'] = array($group['param']);
        !          77922:             }
1.1       misho    77923: 
1.1.1.2 ! misho    77924:             if (isset($group['param'])) {
        !          77925:                 if (method_exists($script, 'postProcessPrompts')) {
        !          77926:                     $prompts = $script->postProcessPrompts($group['param'], $group['id']);
        !          77927:                     if (!is_array($prompts) || count($prompts) != count($group['param'])) {
        !          77928:                         $this->outputData('postinstall', 'Error: post-install script did not ' .
        !          77929:                             'return proper post-processed prompts');
        !          77930:                         $prompts = $group['param'];
        !          77931:                     } else {
        !          77932:                         foreach ($prompts as $i => $var) {
        !          77933:                             if (!is_array($var) || !isset($var['prompt']) ||
        !          77934:                                   !isset($var['name']) ||
        !          77935:                                   ($var['name'] != $group['param'][$i]['name']) ||
        !          77936:                                   ($var['type'] != $group['param'][$i]['type'])
        !          77937:                             ) {
        !          77938:                                 $this->outputData('postinstall', 'Error: post-install script ' .
        !          77939:                                     'modified the variables or prompts, severe security risk. ' .
        !          77940:                                     'Will instead use the defaults from the package.xml');
        !          77941:                                 $prompts = $group['param'];
        !          77942:                             }
        !          77943:                         }
1.1       misho    77944:                     }
                   77945: 
1.1.1.2 ! misho    77946:                     $answers = $this->confirmDialog($prompts);
        !          77947:                 } else {
        !          77948:                     $answers = $this->confirmDialog($group['param']);
        !          77949:                 }
1.1       misho    77950:             }
                   77951: 
1.1.1.2 ! misho    77952:             if ((isset($answers) && $answers) || !isset($group['param'])) {
        !          77953:                 if (!isset($answers)) {
        !          77954:                     $answers = array();
        !          77955:                 }
        !          77956: 
        !          77957:                 array_unshift($completedPhases, $group['id']);
        !          77958:                 if (!$script->run($answers, $group['id'])) {
        !          77959:                     $script->run($completedPhases, '_undoOnError');
        !          77960:                     return;
        !          77961:                 }
        !          77962:             } else {
        !          77963:                 $script->run($completedPhases, '_undoOnError');
        !          77964:                 return;
1.1       misho    77965:             }
                   77966:         }
                   77967:     }
                   77968: 
                   77969:     /**
1.1.1.2 ! misho    77970:      * Ask for user input, confirm the answers and continue until the user is satisfied
        !          77971:      * @param array an array of arrays, format array('name' => 'paramname', 'prompt' =>
        !          77972:      *              'text to display', 'type' => 'string'[, default => 'default value'])
        !          77973:      * @return array
1.1       misho    77974:      */
1.1.1.2 ! misho    77975:     function confirmDialog($params)
1.1       misho    77976:     {
1.1.1.2 ! misho    77977:         $answers = $prompts = $types = array();
        !          77978:         foreach ($params as $param) {
        !          77979:             $prompts[$param['name']] = $param['prompt'];
        !          77980:             $types[$param['name']]   = $param['type'];
        !          77981:             $answers[$param['name']] = isset($param['default']) ? $param['default'] : '';
1.1       misho    77982:         }
                   77983: 
1.1.1.2 ! misho    77984:         $tried = false;
        !          77985:         do {
        !          77986:             if ($tried) {
        !          77987:                 $i = 1;
        !          77988:                 foreach ($answers as $var => $value) {
        !          77989:                     if (!strlen($value)) {
        !          77990:                         echo $this->bold("* Enter an answer for #" . $i . ": ({$prompts[$var]})\n");
        !          77991:                     }
        !          77992:                     $i++;
        !          77993:                 }
        !          77994:             }
1.1       misho    77995: 
1.1.1.2 ! misho    77996:             $answers = $this->userDialog('', $prompts, $types, $answers);
        !          77997:             $tried   = true;
        !          77998:         } while (is_array($answers) && count(array_filter($answers)) != count($prompts));
1.1       misho    77999: 
1.1.1.2 ! misho    78000:         return $answers;
1.1       misho    78001:     }
                   78002: 
1.1.1.2 ! misho    78003:     function userDialog($command, $prompts, $types = array(), $defaults = array(), $screensize = 20)
1.1       misho    78004:     {
1.1.1.2 ! misho    78005:         if (!is_array($prompts)) {
        !          78006:             return array();
1.1       misho    78007:         }
                   78008: 
1.1.1.2 ! misho    78009:         $testprompts = array_keys($prompts);
        !          78010:         $result      = $defaults;
1.1       misho    78011: 
1.1.1.2 ! misho    78012:         reset($prompts);
        !          78013:         if (count($prompts) === 1) {
        !          78014:             foreach ($prompts as $key => $prompt) {
        !          78015:                 $type    = $types[$key];
        !          78016:                 $default = @$defaults[$key];
        !          78017:                 print "$prompt ";
        !          78018:                 if ($default) {
        !          78019:                     print "[$default] ";
        !          78020:                 }
        !          78021:                 print ": ";
1.1       misho    78022: 
1.1.1.2 ! misho    78023:                 $line         = fgets(STDIN, 2048);
        !          78024:                 $result[$key] =  ($default && trim($line) == '') ? $default : trim($line);
        !          78025:             }
1.1       misho    78026: 
1.1.1.2 ! misho    78027:             return $result;
1.1       misho    78028:         }
                   78029: 
1.1.1.2 ! misho    78030:         $first_run = true;
        !          78031:         while (true) {
        !          78032:             $descLength = max(array_map('strlen', $prompts));
        !          78033:             $descFormat = "%-{$descLength}s";
        !          78034:             $last       = count($prompts);
1.1       misho    78035: 
1.1.1.2 ! misho    78036:             $i = 0;
        !          78037:             foreach ($prompts as $n => $var) {
        !          78038:                 $res = isset($result[$n]) ? $result[$n] : null;
        !          78039:                 printf("%2d. $descFormat : %s\n", ++$i, $prompts[$n], $res);
        !          78040:             }
        !          78041:             print "\n1-$last, 'all', 'abort', or Enter to continue: ";
1.1       misho    78042: 
1.1.1.2 ! misho    78043:             $tmp = trim(fgets(STDIN, 1024));
        !          78044:             if (empty($tmp)) {
        !          78045:                 break;
        !          78046:             }
1.1       misho    78047: 
1.1.1.2 ! misho    78048:             if ($tmp == 'abort') {
        !          78049:                 return false;
        !          78050:             }
1.1       misho    78051: 
1.1.1.2 ! misho    78052:             if (isset($testprompts[(int)$tmp - 1])) {
        !          78053:                 $var     = $testprompts[(int)$tmp - 1];
        !          78054:                 $desc    = $prompts[$var];
        !          78055:                 $current = @$result[$var];
        !          78056:                 print "$desc [$current] : ";
        !          78057:                 $tmp = trim(fgets(STDIN, 1024));
        !          78058:                 if ($tmp !== '') {
        !          78059:                     $result[$var] = $tmp;
        !          78060:                 }
        !          78061:             } elseif ($tmp == 'all') {
        !          78062:                 foreach ($prompts as $var => $desc) {
        !          78063:                     $current = $result[$var];
        !          78064:                     print "$desc [$current] : ";
        !          78065:                     $tmp = trim(fgets(STDIN, 1024));
        !          78066:                     if (trim($tmp) !== '') {
        !          78067:                         $result[$var] = trim($tmp);
        !          78068:                     }
        !          78069:                 }
        !          78070:             }
1.1       misho    78071: 
1.1.1.2 ! misho    78072:             $first_run = false;
1.1       misho    78073:         }
                   78074: 
1.1.1.2 ! misho    78075:         return $result;
1.1       misho    78076:     }
                   78077: 
1.1.1.2 ! misho    78078:     function userConfirm($prompt, $default = 'yes')
1.1       misho    78079:     {
1.1.1.2 ! misho    78080:         trigger_error("PEAR_Frontend_CLI::userConfirm not yet converted", E_USER_ERROR);
        !          78081:         static $positives = array('y', 'yes', 'on', '1');
        !          78082:         static $negatives = array('n', 'no', 'off', '0');
        !          78083:         print "$this->lp$prompt [$default] : ";
        !          78084:         $fp = fopen("php://stdin", "r");
        !          78085:         $line = fgets($fp, 2048);
        !          78086:         fclose($fp);
        !          78087:         $answer = strtolower(trim($line));
        !          78088:         if (empty($answer)) {
        !          78089:             $answer = $default;
1.1       misho    78090:         }
1.1.1.2 ! misho    78091:         if (in_array($answer, $positives)) {
        !          78092:             return true;
        !          78093:         }
        !          78094:         if (in_array($answer, $negatives)) {
        !          78095:             return false;
        !          78096:         }
        !          78097:         if (in_array($default, $positives)) {
        !          78098:             return true;
1.1       misho    78099:         }
                   78100:         return false;
                   78101:     }
                   78102: 
1.1.1.2 ! misho    78103:     function outputData($data, $command = '_default')
1.1       misho    78104:     {
1.1.1.2 ! misho    78105:         switch ($command) {
        !          78106:             case 'channel-info':
        !          78107:                 foreach ($data as $type => $section) {
        !          78108:                     if ($type == 'main') {
        !          78109:                         $section['data'] = array_values($section['data']);
        !          78110:                     }
1.1       misho    78111: 
1.1.1.2 ! misho    78112:                     $this->outputData($section);
        !          78113:                 }
        !          78114:                 break;
        !          78115:             case 'install':
        !          78116:             case 'upgrade':
        !          78117:             case 'upgrade-all':
        !          78118:                 if (is_array($data) && isset($data['release_warnings'])) {
        !          78119:                     $this->_displayLine('');
        !          78120:                     $this->_startTable(array(
        !          78121:                         'border' => false,
        !          78122:                         'caption' => 'Release Warnings'
        !          78123:                     ));
        !          78124:                     $this->_tableRow(array($data['release_warnings']), null, array(1 => array('wrap' => 55)));
        !          78125:                     $this->_endTable();
        !          78126:                     $this->_displayLine('');
        !          78127:                 }
1.1       misho    78128: 
1.1.1.2 ! misho    78129:                 $this->_displayLine(is_array($data) ? $data['data'] : $data);
        !          78130:                 break;
        !          78131:             case 'search':
        !          78132:                 $this->_startTable($data);
        !          78133:                 if (isset($data['headline']) && is_array($data['headline'])) {
        !          78134:                     $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55)));
        !          78135:                 }
1.1       misho    78136: 
1.1.1.2 ! misho    78137:                 $packages = array();
        !          78138:                 foreach($data['data'] as $category) {
        !          78139:                     foreach($category as $name => $pkg) {
        !          78140:                         $packages[$pkg[0]] = $pkg;
        !          78141:                     }
        !          78142:                 }
1.1       misho    78143: 
1.1.1.2 ! misho    78144:                 $p = array_keys($packages);
        !          78145:                 natcasesort($p);
        !          78146:                 foreach ($p as $name) {
        !          78147:                     $this->_tableRow($packages[$name], null, array(1 => array('wrap' => 55)));
        !          78148:                 }
1.1       misho    78149: 
1.1.1.2 ! misho    78150:                 $this->_endTable();
        !          78151:                 break;
        !          78152:             case 'list-all':
        !          78153:                 if (!isset($data['data'])) {
        !          78154:                       $this->_displayLine('No packages in channel');
        !          78155:                       break;
        !          78156:                 }
1.1       misho    78157: 
1.1.1.2 ! misho    78158:                 $this->_startTable($data);
        !          78159:                 if (isset($data['headline']) && is_array($data['headline'])) {
        !          78160:                     $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55)));
        !          78161:                 }
1.1       misho    78162: 
1.1.1.2 ! misho    78163:                 $packages = array();
        !          78164:                 foreach($data['data'] as $category) {
        !          78165:                     foreach($category as $name => $pkg) {
        !          78166:                         $packages[$pkg[0]] = $pkg;
        !          78167:                     }
        !          78168:                 }
1.1       misho    78169: 
1.1.1.2 ! misho    78170:                 $p = array_keys($packages);
        !          78171:                 natcasesort($p);
        !          78172:                 foreach ($p as $name) {
        !          78173:                     $pkg = $packages[$name];
        !          78174:                     unset($pkg[4], $pkg[5]);
        !          78175:                     $this->_tableRow($pkg, null, array(1 => array('wrap' => 55)));
        !          78176:                 }
1.1       misho    78177: 
1.1.1.2 ! misho    78178:                 $this->_endTable();
        !          78179:                 break;
        !          78180:             case 'config-show':
        !          78181:                 $data['border'] = false;
        !          78182:                 $opts = array(
        !          78183:                     0 => array('wrap' => 30),
        !          78184:                     1 => array('wrap' => 20),
        !          78185:                     2 => array('wrap' => 35)
        !          78186:                 );
1.1       misho    78187: 
1.1.1.2 ! misho    78188:                 $this->_startTable($data);
        !          78189:                 if (isset($data['headline']) && is_array($data['headline'])) {
        !          78190:                     $this->_tableRow($data['headline'], array('bold' => true), $opts);
        !          78191:                 }
1.1       misho    78192: 
1.1.1.2 ! misho    78193:                 foreach ($data['data'] as $group) {
        !          78194:                     foreach ($group as $value) {
        !          78195:                         if ($value[2] == '') {
        !          78196:                             $value[2] = "<not set>";
        !          78197:                         }
1.1       misho    78198: 
1.1.1.2 ! misho    78199:                         $this->_tableRow($value, null, $opts);
        !          78200:                     }
        !          78201:                 }
        !          78202: 
        !          78203:                 $this->_endTable();
        !          78204:                 break;
        !          78205:             case 'remote-info':
        !          78206:                 $d = $data;
        !          78207:                 $data = array(
        !          78208:                     'caption' => 'Package details:',
        !          78209:                     'border'  => false,
        !          78210:                     'data'    => array(
        !          78211:                         array("Latest",      $data['stable']),
        !          78212:                         array("Installed",   $data['installed']),
        !          78213:                         array("Package",     $data['name']),
        !          78214:                         array("License",     $data['license']),
        !          78215:                         array("Category",    $data['category']),
        !          78216:                         array("Summary",     $data['summary']),
        !          78217:                         array("Description", $data['description']),
        !          78218:                     ),
1.1       misho    78219:                 );
1.1.1.2 ! misho    78220: 
        !          78221:                 if (isset($d['deprecated']) && $d['deprecated']) {
        !          78222:                     $conf = &PEAR_Config::singleton();
        !          78223:                     $reg = $conf->getRegistry();
        !          78224:                     $name = $reg->parsedPackageNameToString($d['deprecated'], true);
        !          78225:                     $data['data'][] = array('Deprecated! use', $name);
1.1       misho    78226:                 }
1.1.1.2 ! misho    78227:             default: {
        !          78228:                 if (is_array($data)) {
        !          78229:                     $this->_startTable($data);
        !          78230:                     $count = count($data['data'][0]);
        !          78231:                     if ($count == 2) {
        !          78232:                         $opts = array(0 => array('wrap' => 25),
        !          78233:                                       1 => array('wrap' => 48)
        !          78234:                         );
        !          78235:                     } elseif ($count == 3) {
        !          78236:                         $opts = array(0 => array('wrap' => 30),
        !          78237:                                       1 => array('wrap' => 20),
        !          78238:                                       2 => array('wrap' => 35)
        !          78239:                         );
        !          78240:                     } else {
        !          78241:                         $opts = null;
        !          78242:                     }
        !          78243:                     if (isset($data['headline']) && is_array($data['headline'])) {
        !          78244:                         $this->_tableRow($data['headline'],
        !          78245:                                          array('bold' => true),
        !          78246:                                          $opts);
        !          78247:                     }
1.1       misho    78248: 
1.1.1.2 ! misho    78249:                     if (is_array($data['data'])) {
        !          78250:                         foreach($data['data'] as $row) {
        !          78251:                             $this->_tableRow($row, null, $opts);
        !          78252:                         }
        !          78253:                     } else {
        !          78254:                         $this->_tableRow(array($data['data']), null, $opts);
        !          78255:                      }
        !          78256:                     $this->_endTable();
        !          78257:                 } else {
        !          78258:                     $this->_displayLine($data);
1.1       misho    78259:                 }
1.1.1.2 ! misho    78260:             }
        !          78261:         }
        !          78262:     }
        !          78263: 
        !          78264:     function log($text, $append_crlf = true)
        !          78265:     {
        !          78266:         if ($append_crlf) {
        !          78267:             return $this->_displayLine($text);
        !          78268:         }
1.1       misho    78269: 
1.1.1.2 ! misho    78270:         return $this->_display($text);
        !          78271:     }
        !          78272: 
        !          78273:     function bold($text)
        !          78274:     {
        !          78275:         if (empty($this->term['bold'])) {
        !          78276:             return strtoupper($text);
1.1       misho    78277:         }
                   78278: 
1.1.1.2 ! misho    78279:         return $this->term['bold'] . $text . $this->term['normal'];
        !          78280:     }
1.1       misho    78281: 
1.1.1.2 ! misho    78282:     function _displayHeading($title)
        !          78283:     {
        !          78284:         print $this->lp.$this->bold($title)."\n";
        !          78285:         print $this->lp.str_repeat("=", strlen($title))."\n";
        !          78286:     }
        !          78287: 
        !          78288:     function _startTable($params = array())
        !          78289:     {
        !          78290:         $params['table_data'] = array();
        !          78291:         $params['widest']     = array();  // indexed by column
        !          78292:         $params['highest']    = array(); // indexed by row
        !          78293:         $params['ncols']      = 0;
        !          78294:         $this->params         = $params;
        !          78295:     }
        !          78296: 
        !          78297:     function _tableRow($columns, $rowparams = array(), $colparams = array())
        !          78298:     {
        !          78299:         $highest = 1;
        !          78300:         for ($i = 0; $i < count($columns); $i++) {
        !          78301:             $col = &$columns[$i];
        !          78302:             if (isset($colparams[$i]) && !empty($colparams[$i]['wrap'])) {
        !          78303:                 $col = wordwrap($col, $colparams[$i]['wrap']);
1.1       misho    78304:             }
                   78305: 
1.1.1.2 ! misho    78306:             if (strpos($col, "\n") !== false) {
        !          78307:                 $multiline = explode("\n", $col);
        !          78308:                 $w = 0;
        !          78309:                 foreach ($multiline as $n => $line) {
        !          78310:                     $len = strlen($line);
        !          78311:                     if ($len > $w) {
        !          78312:                         $w = $len;
        !          78313:                     }
1.1       misho    78314:                 }
1.1.1.2 ! misho    78315:                 $lines = count($multiline);
        !          78316:             } else {
        !          78317:                 $w = strlen($col);
1.1       misho    78318:             }
1.1.1.2 ! misho    78319: 
        !          78320:             if (isset($this->params['widest'][$i])) {
        !          78321:                 if ($w > $this->params['widest'][$i]) {
        !          78322:                     $this->params['widest'][$i] = $w;
1.1       misho    78323:                 }
1.1.1.2 ! misho    78324:             } else {
        !          78325:                 $this->params['widest'][$i] = $w;
1.1       misho    78326:             }
                   78327: 
1.1.1.2 ! misho    78328:             $tmp = count_chars($columns[$i], 1);
        !          78329:             // handle unix, mac and windows formats
        !          78330:             $lines = (isset($tmp[10]) ? $tmp[10] : (isset($tmp[13]) ? $tmp[13] : 0)) + 1;
        !          78331:             if ($lines > $highest) {
        !          78332:                 $highest = $lines;
1.1       misho    78333:             }
                   78334:         }
                   78335: 
1.1.1.2 ! misho    78336:         if (count($columns) > $this->params['ncols']) {
        !          78337:             $this->params['ncols'] = count($columns);
1.1       misho    78338:         }
                   78339: 
1.1.1.2 ! misho    78340:         $new_row = array(
        !          78341:             'data'      => $columns,
        !          78342:             'height'    => $highest,
        !          78343:             'rowparams' => $rowparams,
        !          78344:             'colparams' => $colparams,
        !          78345:         );
        !          78346:         $this->params['table_data'][] = $new_row;
1.1       misho    78347:     }
                   78348: 
1.1.1.2 ! misho    78349:     function _endTable()
1.1       misho    78350:     {
1.1.1.2 ! misho    78351:         extract($this->params);
        !          78352:         if (!empty($caption)) {
        !          78353:             $this->_displayHeading($caption);
1.1       misho    78354:         }
                   78355: 
1.1.1.2 ! misho    78356:         if (count($table_data) === 0) {
        !          78357:             return;
1.1       misho    78358:         }
                   78359: 
1.1.1.2 ! misho    78360:         if (!isset($width)) {
        !          78361:             $width = $widest;
        !          78362:         } else {
        !          78363:             for ($i = 0; $i < $ncols; $i++) {
        !          78364:                 if (!isset($width[$i])) {
        !          78365:                     $width[$i] = $widest[$i];
        !          78366:                 }
1.1       misho    78367:             }
1.1.1.2 ! misho    78368:         }
        !          78369: 
        !          78370:         $border = false;
        !          78371:         if (empty($border)) {
        !          78372:             $cellstart  = '';
        !          78373:             $cellend    = ' ';
        !          78374:             $rowend     = '';
        !          78375:             $padrowend  = false;
        !          78376:             $borderline = '';
1.1       misho    78377:         } else {
1.1.1.2 ! misho    78378:             $cellstart  = '| ';
        !          78379:             $cellend    = ' ';
        !          78380:             $rowend     = '|';
        !          78381:             $padrowend  = true;
        !          78382:             $borderline = '+';
        !          78383:             foreach ($width as $w) {
        !          78384:                 $borderline .= str_repeat('-', $w + strlen($cellstart) + strlen($cellend) - 1);
        !          78385:                 $borderline .= '+';
1.1       misho    78386:             }
                   78387:         }
                   78388: 
1.1.1.2 ! misho    78389:         if ($borderline) {
        !          78390:             $this->_displayLine($borderline);
1.1       misho    78391:         }
                   78392: 
1.1.1.2 ! misho    78393:         for ($i = 0; $i < count($table_data); $i++) {
        !          78394:             extract($table_data[$i]);
        !          78395:             if (!is_array($rowparams)) {
        !          78396:                 $rowparams = array();
1.1       misho    78397:             }
                   78398: 
1.1.1.2 ! misho    78399:             if (!is_array($colparams)) {
        !          78400:                 $colparams = array();
        !          78401:             }
1.1       misho    78402: 
1.1.1.2 ! misho    78403:             $rowlines = array();
        !          78404:             if ($height > 1) {
        !          78405:                 for ($c = 0; $c < count($data); $c++) {
        !          78406:                     $rowlines[$c] = preg_split('/(\r?\n|\r)/', $data[$c]);
        !          78407:                     if (count($rowlines[$c]) < $height) {
        !          78408:                         $rowlines[$c] = array_pad($rowlines[$c], $height, '');
        !          78409:                     }
        !          78410:                 }
        !          78411:             } else {
        !          78412:                 for ($c = 0; $c < count($data); $c++) {
        !          78413:                     $rowlines[$c] = array($data[$c]);
        !          78414:                 }
1.1       misho    78415:             }
                   78416: 
1.1.1.2 ! misho    78417:             for ($r = 0; $r < $height; $r++) {
        !          78418:                 $rowtext = '';
        !          78419:                 for ($c = 0; $c < count($data); $c++) {
        !          78420:                     if (isset($colparams[$c])) {
        !          78421:                         $attribs = array_merge($rowparams, $colparams);
        !          78422:                     } else {
        !          78423:                         $attribs = $rowparams;
        !          78424:                     }
1.1       misho    78425: 
1.1.1.2 ! misho    78426:                     $w = isset($width[$c]) ? $width[$c] : 0;
        !          78427:                     //$cell = $data[$c];
        !          78428:                     $cell = $rowlines[$c][$r];
        !          78429:                     $l = strlen($cell);
        !          78430:                     if ($l > $w) {
        !          78431:                         $cell = substr($cell, 0, $w);
        !          78432:                     }
1.1       misho    78433: 
1.1.1.2 ! misho    78434:                     if (isset($attribs['bold'])) {
        !          78435:                         $cell = $this->bold($cell);
        !          78436:                     }
1.1       misho    78437: 
1.1.1.2 ! misho    78438:                     if ($l < $w) {
        !          78439:                         // not using str_pad here because we may
        !          78440:                         // add bold escape characters to $cell
        !          78441:                         $cell .= str_repeat(' ', $w - $l);
        !          78442:                     }
1.1       misho    78443: 
1.1.1.2 ! misho    78444:                     $rowtext .= $cellstart . $cell . $cellend;
        !          78445:                 }
1.1       misho    78446: 
1.1.1.2 ! misho    78447:                 if (!$border) {
        !          78448:                     $rowtext = rtrim($rowtext);
1.1       misho    78449:                 }
1.1.1.2 ! misho    78450: 
        !          78451:                 $rowtext .= $rowend;
        !          78452:                 $this->_displayLine($rowtext);
1.1       misho    78453:             }
                   78454:         }
                   78455: 
1.1.1.2 ! misho    78456:         if ($borderline) {
        !          78457:             $this->_displayLine($borderline);
1.1       misho    78458:         }
1.1.1.2 ! misho    78459:     }
1.1       misho    78460: 
1.1.1.2 ! misho    78461:     function _displayLine($text)
        !          78462:     {
        !          78463:         print "$this->lp$text\n";
1.1       misho    78464:     }
                   78465: 
1.1.1.2 ! misho    78466:     function _display($text)
1.1       misho    78467:     {
1.1.1.2 ! misho    78468:         print $text;
        !          78469:     }
        !          78470: }<?php
        !          78471: /**
        !          78472:  * PEAR_Installer
        !          78473:  *
        !          78474:  * PHP versions 4 and 5
        !          78475:  *
        !          78476:  * @category   pear
        !          78477:  * @package    PEAR
        !          78478:  * @author     Stig Bakken <ssb@php.net>
        !          78479:  * @author     Tomas V.V. Cox <cox@idecnet.com>
        !          78480:  * @author     Martin Jansen <mj@php.net>
        !          78481:  * @author     Greg Beaver <cellog@php.net>
        !          78482:  * @copyright  1997-2009 The Authors
        !          78483:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          78484:  * @version    CVS: $Id: Installer.php 313024 2011-07-06 19:51:24Z dufuz $
        !          78485:  * @link       http://pear.php.net/package/PEAR
        !          78486:  * @since      File available since Release 0.1
        !          78487:  */
1.1       misho    78488: 
1.1.1.2 ! misho    78489: /**
        !          78490:  * Used for installation groups in package.xml 2.0 and platform exceptions
        !          78491:  */
        !          78492: require_once 'phar://install-pear-nozlib.phar/' . 'OS/Guess.php';
        !          78493: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Downloader.php';
1.1       misho    78494: 
1.1.1.2 ! misho    78495: define('PEAR_INSTALLER_NOBINARY', -240);
        !          78496: /**
        !          78497:  * Administration class used to install PEAR packages and maintain the
        !          78498:  * installed package database.
        !          78499:  *
        !          78500:  * @category   pear
        !          78501:  * @package    PEAR
        !          78502:  * @author     Stig Bakken <ssb@php.net>
        !          78503:  * @author     Tomas V.V. Cox <cox@idecnet.com>
        !          78504:  * @author     Martin Jansen <mj@php.net>
        !          78505:  * @author     Greg Beaver <cellog@php.net>
        !          78506:  * @copyright  1997-2009 The Authors
        !          78507:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          78508:  * @version    Release: 1.9.4
        !          78509:  * @link       http://pear.php.net/package/PEAR
        !          78510:  * @since      Class available since Release 0.1
        !          78511:  */
        !          78512: class PEAR_Installer extends PEAR_Downloader
        !          78513: {
        !          78514:     // {{{ properties
1.1       misho    78515: 
1.1.1.2 ! misho    78516:     /** name of the package directory, for example Foo-1.0
        !          78517:      * @var string
        !          78518:      */
        !          78519:     var $pkgdir;
1.1       misho    78520: 
1.1.1.2 ! misho    78521:     /** directory where PHP code files go
        !          78522:      * @var string
        !          78523:      */
        !          78524:     var $phpdir;
1.1       misho    78525: 
1.1.1.2 ! misho    78526:     /** directory where PHP extension files go
        !          78527:      * @var string
        !          78528:      */
        !          78529:     var $extdir;
1.1       misho    78530: 
1.1.1.2 ! misho    78531:     /** directory where documentation goes
        !          78532:      * @var string
        !          78533:      */
        !          78534:     var $docdir;
1.1       misho    78535: 
1.1.1.2 ! misho    78536:     /** installation root directory (ala PHP's INSTALL_ROOT or
        !          78537:      * automake's DESTDIR
        !          78538:      * @var string
        !          78539:      */
        !          78540:     var $installroot = '';
1.1       misho    78541: 
1.1.1.2 ! misho    78542:     /** debug level
        !          78543:      * @var int
        !          78544:      */
        !          78545:     var $debug = 1;
1.1       misho    78546: 
1.1.1.2 ! misho    78547:     /** temporary directory
        !          78548:      * @var string
        !          78549:      */
        !          78550:     var $tmpdir;
1.1       misho    78551: 
                   78552:     /**
1.1.1.2 ! misho    78553:      * PEAR_Registry object used by the installer
        !          78554:      * @var PEAR_Registry
1.1       misho    78555:      */
1.1.1.2 ! misho    78556:     var $registry;
1.1       misho    78557: 
1.1.1.2 ! misho    78558:     /**
        !          78559:      * array of PEAR_Downloader_Packages
        !          78560:      * @var array
        !          78561:      */
        !          78562:     var $_downloadedPackages;
1.1       misho    78563: 
1.1.1.2 ! misho    78564:     /** List of file transactions queued for an install/upgrade/uninstall.
        !          78565:      *
        !          78566:      *  Format:
        !          78567:      *    array(
        !          78568:      *      0 => array("rename => array("from-file", "to-file")),
        !          78569:      *      1 => array("delete" => array("file-to-delete")),
        !          78570:      *      ...
        !          78571:      *    )
        !          78572:      *
        !          78573:      * @var array
        !          78574:      */
        !          78575:     var $file_operations = array();
1.1       misho    78576: 
1.1.1.2 ! misho    78577:     // }}}
1.1       misho    78578: 
1.1.1.2 ! misho    78579:     // {{{ constructor
1.1       misho    78580: 
1.1.1.2 ! misho    78581:     /**
        !          78582:      * PEAR_Installer constructor.
        !          78583:      *
        !          78584:      * @param object $ui user interface object (instance of PEAR_Frontend_*)
        !          78585:      *
        !          78586:      * @access public
        !          78587:      */
        !          78588:     function PEAR_Installer(&$ui)
        !          78589:     {
        !          78590:         parent::PEAR_Common();
        !          78591:         $this->setFrontendObject($ui);
        !          78592:         $this->debug = $this->config->get('verbose');
        !          78593:     }
1.1       misho    78594: 
1.1.1.2 ! misho    78595:     function setOptions($options)
        !          78596:     {
        !          78597:         $this->_options = $options;
        !          78598:     }
1.1       misho    78599: 
1.1.1.2 ! misho    78600:     function setConfig(&$config)
        !          78601:     {
        !          78602:         $this->config    = &$config;
        !          78603:         $this->_registry = &$config->getRegistry();
        !          78604:     }
1.1       misho    78605: 
1.1.1.2 ! misho    78606:     // }}}
        !          78607: 
        !          78608:     function _removeBackups($files)
        !          78609:     {
        !          78610:         foreach ($files as $path) {
        !          78611:             $this->addFileOperation('removebackup', array($path));
        !          78612:         }
        !          78613:     }
        !          78614: 
        !          78615:     // {{{ _deletePackageFiles()
        !          78616: 
        !          78617:     /**
        !          78618:      * Delete a package's installed files, does not remove empty directories.
        !          78619:      *
        !          78620:      * @param string package name
        !          78621:      * @param string channel name
        !          78622:      * @param bool if true, then files are backed up first
        !          78623:      * @return bool TRUE on success, or a PEAR error on failure
        !          78624:      * @access protected
        !          78625:      */
        !          78626:     function _deletePackageFiles($package, $channel = false, $backup = false)
        !          78627:     {
        !          78628:         if (!$channel) {
        !          78629:             $channel = 'pear.php.net';
1.1       misho    78630:         }
                   78631: 
1.1.1.2 ! misho    78632:         if (!strlen($package)) {
        !          78633:             return $this->raiseError("No package to uninstall given");
1.1       misho    78634:         }
                   78635: 
1.1.1.2 ! misho    78636:         if (strtolower($package) == 'pear' && $channel == 'pear.php.net') {
        !          78637:             // to avoid race conditions, include all possible needed files
        !          78638:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Common.php';
        !          78639:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Replace.php';
        !          78640:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Unixeol.php';
        !          78641:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Windowseol.php';
        !          78642:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v1.php';
        !          78643:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2.php';
        !          78644:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/Generator/v1.php';
        !          78645:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/Generator/v2.php';
1.1       misho    78646:         }
                   78647: 
1.1.1.2 ! misho    78648:         $filelist = $this->_registry->packageInfo($package, 'filelist', $channel);
        !          78649:         if ($filelist == null) {
        !          78650:             return $this->raiseError("$channel/$package not installed");
        !          78651:         }
1.1       misho    78652: 
1.1.1.2 ! misho    78653:         $ret = array();
        !          78654:         foreach ($filelist as $file => $props) {
        !          78655:             if (empty($props['installed_as'])) {
        !          78656:                 continue;
        !          78657:             }
1.1       misho    78658: 
1.1.1.2 ! misho    78659:             $path = $props['installed_as'];
        !          78660:             if ($backup) {
        !          78661:                 $this->addFileOperation('backup', array($path));
        !          78662:                 $ret[] = $path;
1.1       misho    78663:             }
1.1.1.2 ! misho    78664: 
        !          78665:             $this->addFileOperation('delete', array($path));
1.1       misho    78666:         }
                   78667: 
1.1.1.2 ! misho    78668:         if ($backup) {
        !          78669:             return $ret;
1.1       misho    78670:         }
                   78671: 
1.1.1.2 ! misho    78672:         return true;
1.1       misho    78673:     }
                   78674: 
1.1.1.2 ! misho    78675:     // }}}
        !          78676:     // {{{ _installFile()
1.1       misho    78677: 
                   78678:     /**
1.1.1.2 ! misho    78679:      * @param string filename
        !          78680:      * @param array attributes from <file> tag in package.xml
        !          78681:      * @param string path to install the file in
        !          78682:      * @param array options from command-line
        !          78683:      * @access private
1.1       misho    78684:      */
1.1.1.2 ! misho    78685:     function _installFile($file, $atts, $tmp_path, $options)
1.1       misho    78686:     {
1.1.1.2 ! misho    78687:         // {{{ return if this file is meant for another platform
        !          78688:         static $os;
        !          78689:         if (!isset($this->_registry)) {
        !          78690:             $this->_registry = &$this->config->getRegistry();
1.1       misho    78691:         }
                   78692: 
1.1.1.2 ! misho    78693:         if (isset($atts['platform'])) {
        !          78694:             if (empty($os)) {
        !          78695:                 $os = new OS_Guess();
        !          78696:             }
        !          78697: 
        !          78698:             if (strlen($atts['platform']) && $atts['platform']{0} == '!') {
        !          78699:                 $negate   = true;
        !          78700:                 $platform = substr($atts['platform'], 1);
        !          78701:             } else {
        !          78702:                 $negate    = false;
        !          78703:                 $platform = $atts['platform'];
        !          78704:             }
        !          78705: 
        !          78706:             if ((bool) $os->matchSignature($platform) === $negate) {
        !          78707:                 $this->log(3, "skipped $file (meant for $atts[platform], we are ".$os->getSignature().")");
        !          78708:                 return PEAR_INSTALLER_SKIPPED;
1.1       misho    78709:             }
                   78710:         }
1.1.1.2 ! misho    78711:         // }}}
1.1       misho    78712: 
1.1.1.2 ! misho    78713:         $channel = $this->pkginfo->getChannel();
        !          78714:         // {{{ assemble the destination paths
        !          78715:         switch ($atts['role']) {
        !          78716:             case 'src':
        !          78717:             case 'extsrc':
        !          78718:                 $this->source_files++;
        !          78719:                 return;
        !          78720:             case 'doc':
        !          78721:             case 'data':
        !          78722:             case 'test':
        !          78723:                 $dest_dir = $this->config->get($atts['role'] . '_dir', null, $channel) .
        !          78724:                             DIRECTORY_SEPARATOR . $this->pkginfo->getPackage();
        !          78725:                 unset($atts['baseinstalldir']);
        !          78726:                 break;
        !          78727:             case 'ext':
        !          78728:             case 'php':
        !          78729:                 $dest_dir = $this->config->get($atts['role'] . '_dir', null, $channel);
        !          78730:                 break;
        !          78731:             case 'script':
        !          78732:                 $dest_dir = $this->config->get('bin_dir', null, $channel);
        !          78733:                 break;
        !          78734:             default:
        !          78735:                 return $this->raiseError("Invalid role `$atts[role]' for file $file");
        !          78736:         }
1.1       misho    78737: 
1.1.1.2 ! misho    78738:         $save_destdir = $dest_dir;
        !          78739:         if (!empty($atts['baseinstalldir'])) {
        !          78740:             $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
        !          78741:         }
1.1       misho    78742: 
1.1.1.2 ! misho    78743:         if (dirname($file) != '.' && empty($atts['install-as'])) {
        !          78744:             $dest_dir .= DIRECTORY_SEPARATOR . dirname($file);
        !          78745:         }
1.1       misho    78746: 
1.1.1.2 ! misho    78747:         if (empty($atts['install-as'])) {
        !          78748:             $dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file);
        !          78749:         } else {
        !          78750:             $dest_file = $dest_dir . DIRECTORY_SEPARATOR . $atts['install-as'];
1.1       misho    78751:         }
1.1.1.2 ! misho    78752:         $orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file;
1.1       misho    78753: 
1.1.1.2 ! misho    78754:         // Clean up the DIRECTORY_SEPARATOR mess
        !          78755:         $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
        !          78756:         list($dest_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"),
        !          78757:                                                     array(DIRECTORY_SEPARATOR,
        !          78758:                                                           DIRECTORY_SEPARATOR,
        !          78759:                                                           DIRECTORY_SEPARATOR),
        !          78760:                                                     array($dest_file, $orig_file));
        !          78761:         $final_dest_file = $installed_as = $dest_file;
        !          78762:         if (isset($this->_options['packagingroot'])) {
        !          78763:             $installedas_dest_dir  = dirname($final_dest_file);
        !          78764:             $installedas_dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
        !          78765:             $final_dest_file = $this->_prependPath($final_dest_file, $this->_options['packagingroot']);
        !          78766:         } else {
        !          78767:             $installedas_dest_dir  = dirname($final_dest_file);
        !          78768:             $installedas_dest_file = $installedas_dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
        !          78769:         }
        !          78770: 
        !          78771:         $dest_dir  = dirname($final_dest_file);
        !          78772:         $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
        !          78773:         if (preg_match('~/\.\.(/|\\z)|^\.\./~', str_replace('\\', '/', $dest_file))) {
        !          78774:             return $this->raiseError("SECURITY ERROR: file $file (installed to $dest_file) contains parent directory reference ..", PEAR_INSTALLER_FAILED);
        !          78775:         }
        !          78776:         // }}}
        !          78777: 
        !          78778:         if (empty($this->_options['register-only']) &&
        !          78779:               (!file_exists($dest_dir) || !is_dir($dest_dir))) {
        !          78780:             if (!$this->mkDirHier($dest_dir)) {
        !          78781:                 return $this->raiseError("failed to mkdir $dest_dir",
        !          78782:                                          PEAR_INSTALLER_FAILED);
1.1       misho    78783:             }
1.1.1.2 ! misho    78784:             $this->log(3, "+ mkdir $dest_dir");
        !          78785:         }
1.1       misho    78786: 
1.1.1.2 ! misho    78787:         // pretty much nothing happens if we are only registering the install
        !          78788:         if (empty($this->_options['register-only'])) {
        !          78789:             if (empty($atts['replacements'])) {
        !          78790:                 if (!file_exists($orig_file)) {
        !          78791:                     return $this->raiseError("file $orig_file does not exist",
        !          78792:                                              PEAR_INSTALLER_FAILED);
1.1       misho    78793:                 }
                   78794: 
1.1.1.2 ! misho    78795:                 if (!@copy($orig_file, $dest_file)) {
        !          78796:                     return $this->raiseError("failed to write $dest_file: $php_errormsg",
        !          78797:                                              PEAR_INSTALLER_FAILED);
1.1       misho    78798:                 }
                   78799: 
1.1.1.2 ! misho    78800:                 $this->log(3, "+ cp $orig_file $dest_file");
        !          78801:                 if (isset($atts['md5sum'])) {
        !          78802:                     $md5sum = md5_file($dest_file);
        !          78803:                 }
        !          78804:             } else {
        !          78805:                 // {{{ file with replacements
        !          78806:                 if (!file_exists($orig_file)) {
        !          78807:                     return $this->raiseError("file does not exist",
        !          78808:                                              PEAR_INSTALLER_FAILED);
        !          78809:                 }
1.1       misho    78810: 
1.1.1.2 ! misho    78811:                 $contents = file_get_contents($orig_file);
        !          78812:                 if ($contents === false) {
        !          78813:                     $contents = '';
1.1       misho    78814:                 }
                   78815: 
1.1.1.2 ! misho    78816:                 if (isset($atts['md5sum'])) {
        !          78817:                     $md5sum = md5($contents);
        !          78818:                 }
1.1       misho    78819: 
1.1.1.2 ! misho    78820:                 $subst_from = $subst_to = array();
        !          78821:                 foreach ($atts['replacements'] as $a) {
        !          78822:                     $to = '';
        !          78823:                     if ($a['type'] == 'php-const') {
        !          78824:                         if (preg_match('/^[a-z0-9_]+\\z/i', $a['to'])) {
        !          78825:                             eval("\$to = $a[to];");
        !          78826:                         } else {
        !          78827:                             if (!isset($options['soft'])) {
        !          78828:                                 $this->log(0, "invalid php-const replacement: $a[to]");
        !          78829:                             }
        !          78830:                             continue;
1.1       misho    78831:                         }
1.1.1.2 ! misho    78832:                     } elseif ($a['type'] == 'pear-config') {
        !          78833:                         if ($a['to'] == 'master_server') {
        !          78834:                             $chan = $this->_registry->getChannel($channel);
        !          78835:                             if (!PEAR::isError($chan)) {
        !          78836:                                 $to = $chan->getServer();
        !          78837:                             } else {
        !          78838:                                 $to = $this->config->get($a['to'], null, $channel);
        !          78839:                             }
        !          78840:                         } else {
        !          78841:                             $to = $this->config->get($a['to'], null, $channel);
        !          78842:                         }
        !          78843:                         if (is_null($to)) {
        !          78844:                             if (!isset($options['soft'])) {
        !          78845:                                 $this->log(0, "invalid pear-config replacement: $a[to]");
        !          78846:                             }
        !          78847:                             continue;
        !          78848:                         }
        !          78849:                     } elseif ($a['type'] == 'package-info') {
        !          78850:                         if ($t = $this->pkginfo->packageInfo($a['to'])) {
        !          78851:                             $to = $t;
        !          78852:                         } else {
        !          78853:                             if (!isset($options['soft'])) {
        !          78854:                                 $this->log(0, "invalid package-info replacement: $a[to]");
        !          78855:                             }
        !          78856:                             continue;
1.1       misho    78857:                         }
                   78858:                     }
1.1.1.2 ! misho    78859:                     if (!is_null($to)) {
        !          78860:                         $subst_from[] = $a['from'];
        !          78861:                         $subst_to[] = $to;
        !          78862:                     }
1.1       misho    78863:                 }
                   78864: 
1.1.1.2 ! misho    78865:                 $this->log(3, "doing ".sizeof($subst_from)." substitution(s) for $final_dest_file");
        !          78866:                 if (sizeof($subst_from)) {
        !          78867:                     $contents = str_replace($subst_from, $subst_to, $contents);
1.1       misho    78868:                 }
                   78869: 
1.1.1.2 ! misho    78870:                 $wp = @fopen($dest_file, "wb");
        !          78871:                 if (!is_resource($wp)) {
        !          78872:                     return $this->raiseError("failed to create $dest_file: $php_errormsg",
        !          78873:                                              PEAR_INSTALLER_FAILED);
        !          78874:                 }
1.1       misho    78875: 
1.1.1.2 ! misho    78876:                 if (@fwrite($wp, $contents) === false) {
        !          78877:                     return $this->raiseError("failed writing to $dest_file: $php_errormsg",
        !          78878:                                              PEAR_INSTALLER_FAILED);
        !          78879:                 }
1.1       misho    78880: 
1.1.1.2 ! misho    78881:                 fclose($wp);
        !          78882:                 // }}}
1.1       misho    78883:             }
                   78884: 
1.1.1.2 ! misho    78885:             // {{{ check the md5
        !          78886:             if (isset($md5sum)) {
        !          78887:                 if (strtolower($md5sum) === strtolower($atts['md5sum'])) {
        !          78888:                     $this->log(2, "md5sum ok: $final_dest_file");
        !          78889:                 } else {
        !          78890:                     if (empty($options['force'])) {
        !          78891:                         // delete the file
        !          78892:                         if (file_exists($dest_file)) {
        !          78893:                             unlink($dest_file);
1.1       misho    78894:                         }
                   78895: 
1.1.1.2 ! misho    78896:                         if (!isset($options['ignore-errors'])) {
        !          78897:                             return $this->raiseError("bad md5sum for file $final_dest_file",
        !          78898:                                                  PEAR_INSTALLER_FAILED);
        !          78899:                         }
1.1       misho    78900: 
1.1.1.2 ! misho    78901:                         if (!isset($options['soft'])) {
        !          78902:                             $this->log(0, "warning : bad md5sum for file $final_dest_file");
        !          78903:                         }
        !          78904:                     } else {
        !          78905:                         if (!isset($options['soft'])) {
        !          78906:                             $this->log(0, "warning : bad md5sum for file $final_dest_file");
        !          78907:                         }
1.1       misho    78908:                     }
                   78909:                 }
                   78910:             }
1.1.1.2 ! misho    78911:             // }}}
        !          78912:             // {{{ set file permissions
        !          78913:             if (!OS_WINDOWS) {
        !          78914:                 if ($atts['role'] == 'script') {
        !          78915:                     $mode = 0777 & ~(int)octdec($this->config->get('umask'));
        !          78916:                     $this->log(3, "+ chmod +x $dest_file");
        !          78917:                 } else {
        !          78918:                     $mode = 0666 & ~(int)octdec($this->config->get('umask'));
        !          78919:                 }
1.1       misho    78920: 
1.1.1.2 ! misho    78921:                 if ($atts['role'] != 'src') {
        !          78922:                     $this->addFileOperation("chmod", array($mode, $dest_file));
        !          78923:                     if (!@chmod($dest_file, $mode)) {
        !          78924:                         if (!isset($options['soft'])) {
        !          78925:                             $this->log(0, "failed to change mode of $dest_file: $php_errormsg");
        !          78926:                         }
1.1       misho    78927:                     }
                   78928:                 }
                   78929:             }
1.1.1.2 ! misho    78930:             // }}}
1.1       misho    78931: 
1.1.1.2 ! misho    78932:             if ($atts['role'] == 'src') {
        !          78933:                 rename($dest_file, $final_dest_file);
        !          78934:                 $this->log(2, "renamed source file $dest_file to $final_dest_file");
        !          78935:             } else {
        !          78936:                 $this->addFileOperation("rename", array($dest_file, $final_dest_file,
        !          78937:                     $atts['role'] == 'ext'));
        !          78938:             }
1.1       misho    78939:         }
                   78940: 
1.1.1.2 ! misho    78941:         // Store the full path where the file was installed for easy unistall
        !          78942:         if ($atts['role'] != 'script') {
        !          78943:             $loc = $this->config->get($atts['role'] . '_dir');
        !          78944:         } else {
        !          78945:             $loc = $this->config->get('bin_dir');
1.1       misho    78946:         }
                   78947: 
1.1.1.2 ! misho    78948:         if ($atts['role'] != 'src') {
        !          78949:             $this->addFileOperation("installed_as", array($file, $installed_as,
        !          78950:                                     $loc,
        !          78951:                                     dirname(substr($installedas_dest_file, strlen($loc)))));
1.1       misho    78952:         }
1.1.1.2 ! misho    78953: 
        !          78954:         //$this->log(2, "installed: $dest_file");
        !          78955:         return PEAR_INSTALLER_OK;
1.1       misho    78956:     }
                   78957: 
1.1.1.2 ! misho    78958:     // }}}
        !          78959:     // {{{ _installFile2()
        !          78960: 
1.1       misho    78961:     /**
1.1.1.2 ! misho    78962:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
        !          78963:      * @param string filename
        !          78964:      * @param array attributes from <file> tag in package.xml
        !          78965:      * @param string path to install the file in
        !          78966:      * @param array options from command-line
1.1       misho    78967:      * @access private
                   78968:      */
1.1.1.2 ! misho    78969:     function _installFile2(&$pkg, $file, &$real_atts, $tmp_path, $options)
1.1       misho    78970:     {
1.1.1.2 ! misho    78971:         $atts = $real_atts;
        !          78972:         if (!isset($this->_registry)) {
        !          78973:             $this->_registry = &$this->config->getRegistry();
1.1       misho    78974:         }
                   78975: 
1.1.1.2 ! misho    78976:         $channel = $pkg->getChannel();
        !          78977:         // {{{ assemble the destination paths
        !          78978:         if (!in_array($atts['attribs']['role'],
        !          78979:               PEAR_Installer_Role::getValidRoles($pkg->getPackageType()))) {
        !          78980:             return $this->raiseError('Invalid role `' . $atts['attribs']['role'] .
        !          78981:                     "' for file $file");
        !          78982:         }
1.1       misho    78983: 
1.1.1.2 ! misho    78984:         $role = &PEAR_Installer_Role::factory($pkg, $atts['attribs']['role'], $this->config);
        !          78985:         $err  = $role->setup($this, $pkg, $atts['attribs'], $file);
        !          78986:         if (PEAR::isError($err)) {
        !          78987:             return $err;
1.1       misho    78988:         }
                   78989: 
1.1.1.2 ! misho    78990:         if (!$role->isInstallable()) {
        !          78991:             return;
        !          78992:         }
1.1       misho    78993: 
1.1.1.2 ! misho    78994:         $info = $role->processInstallation($pkg, $atts['attribs'], $file, $tmp_path);
        !          78995:         if (PEAR::isError($info)) {
        !          78996:             return $info;
1.1       misho    78997:         }
                   78998: 
1.1.1.2 ! misho    78999:         list($save_destdir, $dest_dir, $dest_file, $orig_file) = $info;
        !          79000:         if (preg_match('~/\.\.(/|\\z)|^\.\./~', str_replace('\\', '/', $dest_file))) {
        !          79001:             return $this->raiseError("SECURITY ERROR: file $file (installed to $dest_file) contains parent directory reference ..", PEAR_INSTALLER_FAILED);
        !          79002:         }
        !          79003: 
        !          79004:         $final_dest_file = $installed_as = $dest_file;
        !          79005:         if (isset($this->_options['packagingroot'])) {
        !          79006:             $final_dest_file = $this->_prependPath($final_dest_file,
        !          79007:                 $this->_options['packagingroot']);
        !          79008:         }
        !          79009: 
        !          79010:         $dest_dir  = dirname($final_dest_file);
        !          79011:         $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
        !          79012:         // }}}
        !          79013: 
        !          79014:         if (empty($this->_options['register-only'])) {
        !          79015:             if (!file_exists($dest_dir) || !is_dir($dest_dir)) {
        !          79016:                 if (!$this->mkDirHier($dest_dir)) {
        !          79017:                     return $this->raiseError("failed to mkdir $dest_dir",
        !          79018:                                              PEAR_INSTALLER_FAILED);
1.1       misho    79019:                 }
1.1.1.2 ! misho    79020:                 $this->log(3, "+ mkdir $dest_dir");
1.1       misho    79021:             }
1.1.1.2 ! misho    79022:         }
1.1       misho    79023: 
1.1.1.2 ! misho    79024:         $attribs = $atts['attribs'];
        !          79025:         unset($atts['attribs']);
        !          79026:         // pretty much nothing happens if we are only registering the install
        !          79027:         if (empty($this->_options['register-only'])) {
        !          79028:             if (!count($atts)) { // no tasks
        !          79029:                 if (!file_exists($orig_file)) {
        !          79030:                     return $this->raiseError("file $orig_file does not exist",
        !          79031:                                              PEAR_INSTALLER_FAILED);
1.1       misho    79032:                 }
                   79033: 
1.1.1.2 ! misho    79034:                 if (!@copy($orig_file, $dest_file)) {
        !          79035:                     return $this->raiseError("failed to write $dest_file: $php_errormsg",
        !          79036:                                              PEAR_INSTALLER_FAILED);
        !          79037:                 }
1.1       misho    79038: 
1.1.1.2 ! misho    79039:                 $this->log(3, "+ cp $orig_file $dest_file");
        !          79040:                 if (isset($attribs['md5sum'])) {
        !          79041:                     $md5sum = md5_file($dest_file);
        !          79042:                 }
        !          79043:             } else { // file with tasks
        !          79044:                 if (!file_exists($orig_file)) {
        !          79045:                     return $this->raiseError("file $orig_file does not exist",
        !          79046:                                              PEAR_INSTALLER_FAILED);
1.1       misho    79047:                 }
                   79048: 
1.1.1.2 ! misho    79049:                 $contents = file_get_contents($orig_file);
        !          79050:                 if ($contents === false) {
        !          79051:                     $contents = '';
        !          79052:                 }
1.1       misho    79053: 
1.1.1.2 ! misho    79054:                 if (isset($attribs['md5sum'])) {
        !          79055:                     $md5sum = md5($contents);
        !          79056:                 }
1.1       misho    79057: 
1.1.1.2 ! misho    79058:                 foreach ($atts as $tag => $raw) {
        !          79059:                     $tag = str_replace(array($pkg->getTasksNs() . ':', '-'), array('', '_'), $tag);
        !          79060:                     $task = "PEAR_Task_$tag";
        !          79061:                     $task = &new $task($this->config, $this, PEAR_TASK_INSTALL);
        !          79062:                     if (!$task->isScript()) { // scripts are only handled after installation
        !          79063:                         $task->init($raw, $attribs, $pkg->getLastInstalledVersion());
        !          79064:                         $res = $task->startSession($pkg, $contents, $final_dest_file);
        !          79065:                         if ($res === false) {
        !          79066:                             continue; // skip this file
1.1       misho    79067:                         }
                   79068: 
1.1.1.2 ! misho    79069:                         if (PEAR::isError($res)) {
        !          79070:                             return $res;
1.1       misho    79071:                         }
1.1.1.2 ! misho    79072: 
        !          79073:                         $contents = $res; // save changes
1.1       misho    79074:                     }
                   79075: 
1.1.1.2 ! misho    79076:                     $wp = @fopen($dest_file, "wb");
        !          79077:                     if (!is_resource($wp)) {
        !          79078:                         return $this->raiseError("failed to create $dest_file: $php_errormsg",
        !          79079:                                                  PEAR_INSTALLER_FAILED);
        !          79080:                     }
1.1       misho    79081: 
1.1.1.2 ! misho    79082:                     if (fwrite($wp, $contents) === false) {
        !          79083:                         return $this->raiseError("failed writing to $dest_file: $php_errormsg",
        !          79084:                                                  PEAR_INSTALLER_FAILED);
        !          79085:                     }
        !          79086: 
        !          79087:                     fclose($wp);
1.1       misho    79088:                 }
1.1.1.2 ! misho    79089:             }
1.1       misho    79090: 
1.1.1.2 ! misho    79091:             // {{{ check the md5
        !          79092:             if (isset($md5sum)) {
        !          79093:                 // Make sure the original md5 sum matches with expected
        !          79094:                 if (strtolower($md5sum) === strtolower($attribs['md5sum'])) {
        !          79095:                     $this->log(2, "md5sum ok: $final_dest_file");
1.1       misho    79096: 
1.1.1.2 ! misho    79097:                     if (isset($contents)) {
        !          79098:                         // set md5 sum based on $content in case any tasks were run.
        !          79099:                         $real_atts['attribs']['md5sum'] = md5($contents);
        !          79100:                     }
        !          79101:                 } else {
        !          79102:                     if (empty($options['force'])) {
        !          79103:                         // delete the file
        !          79104:                         if (file_exists($dest_file)) {
        !          79105:                             unlink($dest_file);
1.1       misho    79106:                         }
1.1.1.2 ! misho    79107: 
        !          79108:                         if (!isset($options['ignore-errors'])) {
        !          79109:                             return $this->raiseError("bad md5sum for file $final_dest_file",
        !          79110:                                                      PEAR_INSTALLER_FAILED);
1.1       misho    79111:                         }
                   79112: 
1.1.1.2 ! misho    79113:                         if (!isset($options['soft'])) {
        !          79114:                             $this->log(0, "warning : bad md5sum for file $final_dest_file");
        !          79115:                         }
        !          79116:                     } else {
        !          79117:                         if (!isset($options['soft'])) {
        !          79118:                             $this->log(0, "warning : bad md5sum for file $final_dest_file");
1.1       misho    79119:                         }
                   79120:                     }
                   79121:                 }
1.1.1.2 ! misho    79122:             } else {
        !          79123:                 $real_atts['attribs']['md5sum'] = md5_file($dest_file);
        !          79124:             }
1.1       misho    79125: 
1.1.1.2 ! misho    79126:             // }}}
        !          79127:             // {{{ set file permissions
        !          79128:             if (!OS_WINDOWS) {
        !          79129:                 if ($role->isExecutable()) {
        !          79130:                     $mode = 0777 & ~(int)octdec($this->config->get('umask'));
        !          79131:                     $this->log(3, "+ chmod +x $dest_file");
        !          79132:                 } else {
        !          79133:                     $mode = 0666 & ~(int)octdec($this->config->get('umask'));
1.1       misho    79134:                 }
                   79135: 
1.1.1.2 ! misho    79136:                 if ($attribs['role'] != 'src') {
        !          79137:                     $this->addFileOperation("chmod", array($mode, $dest_file));
        !          79138:                     if (!@chmod($dest_file, $mode)) {
        !          79139:                         if (!isset($options['soft'])) {
        !          79140:                             $this->log(0, "failed to change mode of $dest_file: $php_errormsg");
        !          79141:                         }
        !          79142:                     }
1.1       misho    79143:                 }
                   79144:             }
1.1.1.2 ! misho    79145:             // }}}
1.1       misho    79146: 
1.1.1.2 ! misho    79147:             if ($attribs['role'] == 'src') {
        !          79148:                 rename($dest_file, $final_dest_file);
        !          79149:                 $this->log(2, "renamed source file $dest_file to $final_dest_file");
        !          79150:             } else {
        !          79151:                 $this->addFileOperation("rename", array($dest_file, $final_dest_file, $role->isExtension()));
        !          79152:             }
        !          79153:         }
        !          79154: 
        !          79155:         // Store the full path where the file was installed for easy uninstall
        !          79156:         if ($attribs['role'] != 'src') {
        !          79157:             $loc = $this->config->get($role->getLocationConfig(), null, $channel);
        !          79158:             $this->addFileOperation('installed_as', array($file, $installed_as,
        !          79159:                                 $loc,
        !          79160:                                 dirname(substr($installed_as, strlen($loc)))));
        !          79161:         }
        !          79162: 
        !          79163:         //$this->log(2, "installed: $dest_file");
        !          79164:         return PEAR_INSTALLER_OK;
        !          79165:     }
        !          79166: 
        !          79167:     // }}}
        !          79168:     // {{{ addFileOperation()
1.1       misho    79169: 
                   79170:     /**
1.1.1.2 ! misho    79171:      * Add a file operation to the current file transaction.
1.1       misho    79172:      *
1.1.1.2 ! misho    79173:      * @see startFileTransaction()
        !          79174:      * @param string $type This can be one of:
        !          79175:      *    - rename:  rename a file ($data has 3 values)
        !          79176:      *    - backup:  backup an existing file ($data has 1 value)
        !          79177:      *    - removebackup:  clean up backups created during install ($data has 1 value)
        !          79178:      *    - chmod:   change permissions on a file ($data has 2 values)
        !          79179:      *    - delete:  delete a file ($data has 1 value)
        !          79180:      *    - rmdir:   delete a directory if empty ($data has 1 value)
        !          79181:      *    - installed_as: mark a file as installed ($data has 4 values).
        !          79182:      * @param array $data For all file operations, this array must contain the
        !          79183:      *    full path to the file or directory that is being operated on.  For
        !          79184:      *    the rename command, the first parameter must be the file to rename,
        !          79185:      *    the second its new name, the third whether this is a PHP extension.
        !          79186:      *
        !          79187:      *    The installed_as operation contains 4 elements in this order:
        !          79188:      *    1. Filename as listed in the filelist element from package.xml
        !          79189:      *    2. Full path to the installed file
        !          79190:      *    3. Full path from the php_dir configuration variable used in this
        !          79191:      *       installation
        !          79192:      *    4. Relative path from the php_dir that this file is installed in
1.1       misho    79193:      */
1.1.1.2 ! misho    79194:     function addFileOperation($type, $data)
        !          79195:     {
        !          79196:         if (!is_array($data)) {
        !          79197:             return $this->raiseError('Internal Error: $data in addFileOperation'
        !          79198:                 . ' must be an array, was ' . gettype($data));
        !          79199:         }
1.1       misho    79200: 
1.1.1.2 ! misho    79201:         if ($type == 'chmod') {
        !          79202:             $octmode = decoct($data[0]);
        !          79203:             $this->log(3, "adding to transaction: $type $octmode $data[1]");
        !          79204:         } else {
        !          79205:             $this->log(3, "adding to transaction: $type " . implode(" ", $data));
        !          79206:         }
        !          79207:         $this->file_operations[] = array($type, $data);
        !          79208:     }
        !          79209: 
        !          79210:     // }}}
        !          79211:     // {{{ startFileTransaction()
        !          79212: 
        !          79213:     function startFileTransaction($rollback_in_case = false)
1.1       misho    79214:     {
1.1.1.2 ! misho    79215:         if (count($this->file_operations) && $rollback_in_case) {
        !          79216:             $this->rollbackFileTransaction();
        !          79217:         }
        !          79218:         $this->file_operations = array();
1.1       misho    79219:     }
1.1.1.2 ! misho    79220: 
        !          79221:     // }}}
        !          79222:     // {{{ commitFileTransaction()
        !          79223: 
        !          79224:     function commitFileTransaction()
1.1       misho    79225:     {
1.1.1.2 ! misho    79226:         // {{{ first, check permissions and such manually
        !          79227:         $errors = array();
        !          79228:         foreach ($this->file_operations as $key => $tr) {
        !          79229:             list($type, $data) = $tr;
        !          79230:             switch ($type) {
        !          79231:                 case 'rename':
        !          79232:                     if (!file_exists($data[0])) {
        !          79233:                         $errors[] = "cannot rename file $data[0], doesn't exist";
        !          79234:                     }
        !          79235: 
        !          79236:                     // check that dest dir. is writable
        !          79237:                     if (!is_writable(dirname($data[1]))) {
        !          79238:                         $errors[] = "permission denied ($type): $data[1]";
        !          79239:                     }
        !          79240:                     break;
        !          79241:                 case 'chmod':
        !          79242:                     // check that file is writable
        !          79243:                     if (!is_writable($data[1])) {
        !          79244:                         $errors[] = "permission denied ($type): $data[1] " . decoct($data[0]);
        !          79245:                     }
        !          79246:                     break;
        !          79247:                 case 'delete':
        !          79248:                     if (!file_exists($data[0])) {
        !          79249:                         $this->log(2, "warning: file $data[0] doesn't exist, can't be deleted");
        !          79250:                     }
        !          79251:                     // check that directory is writable
        !          79252:                     if (file_exists($data[0])) {
        !          79253:                         if (!is_writable(dirname($data[0]))) {
        !          79254:                             $errors[] = "permission denied ($type): $data[0]";
        !          79255:                         } else {
        !          79256:                             // make sure the file to be deleted can be opened for writing
        !          79257:                             $fp = false;
        !          79258:                             if (!is_dir($data[0]) &&
        !          79259:                                   (!is_writable($data[0]) || !($fp = @fopen($data[0], 'a')))) {
        !          79260:                                 $errors[] = "permission denied ($type): $data[0]";
        !          79261:                             } elseif ($fp) {
        !          79262:                                 fclose($fp);
        !          79263:                             }
        !          79264:                         }
        !          79265: 
        !          79266:                         /* Verify we are not deleting a file owned by another package
        !          79267:                          * This can happen when a file moves from package A to B in
        !          79268:                          * an upgrade ala http://pear.php.net/17986
        !          79269:                          */
        !          79270:                         $info = array(
        !          79271:                             'package' => strtolower($this->pkginfo->getName()),
        !          79272:                             'channel' => strtolower($this->pkginfo->getChannel()),
        !          79273:                         );
        !          79274:                         $result = $this->_registry->checkFileMap($data[0], $info, '1.1');
        !          79275:                         if (is_array($result)) {
        !          79276:                             $res = array_diff($result, $info);
        !          79277:                             if (!empty($res)) {
        !          79278:                                 $new = $this->_registry->getPackage($result[1], $result[0]);
        !          79279:                                 $this->file_operations[$key] = false;
        !          79280:                                 $this->log(3, "file $data[0] was scheduled for removal from {$this->pkginfo->getName()} but is owned by {$new->getChannel()}/{$new->getName()}, removal has been cancelled.");
        !          79281:                             }
        !          79282:                         }
        !          79283:                     }
        !          79284:                     break;
        !          79285:             }
        !          79286: 
1.1       misho    79287:         }
1.1.1.2 ! misho    79288:         // }}}
        !          79289: 
        !          79290:         $n = count($this->file_operations);
        !          79291:         $this->log(2, "about to commit $n file operations for " . $this->pkginfo->getName());
        !          79292: 
        !          79293:         $m = count($errors);
        !          79294:         if ($m > 0) {
        !          79295:             foreach ($errors as $error) {
        !          79296:                 if (!isset($this->_options['soft'])) {
        !          79297:                     $this->log(1, $error);
        !          79298:                 }
        !          79299:             }
        !          79300: 
        !          79301:             if (!isset($this->_options['ignore-errors'])) {
        !          79302:                 return false;
1.1       misho    79303:             }
                   79304:         }
                   79305: 
1.1.1.2 ! misho    79306:         $this->_dirtree = array();
        !          79307:         // {{{ really commit the transaction
        !          79308:         foreach ($this->file_operations as $i => $tr) {
        !          79309:             if (!$tr) {
        !          79310:                 // support removal of non-existing backups
        !          79311:                 continue;
        !          79312:             }
1.1       misho    79313: 
1.1.1.2 ! misho    79314:             list($type, $data) = $tr;
        !          79315:             switch ($type) {
        !          79316:                 case 'backup':
        !          79317:                     if (!file_exists($data[0])) {
        !          79318:                         $this->file_operations[$i] = false;
        !          79319:                         break;
        !          79320:                     }
        !          79321: 
        !          79322:                     if (!@copy($data[0], $data[0] . '.bak')) {
        !          79323:                         $this->log(1, 'Could not copy ' . $data[0] . ' to ' . $data[0] .
        !          79324:                             '.bak ' . $php_errormsg);
        !          79325:                         return false;
        !          79326:                     }
        !          79327:                     $this->log(3, "+ backup $data[0] to $data[0].bak");
        !          79328:                     break;
        !          79329:                 case 'removebackup':
        !          79330:                     if (file_exists($data[0] . '.bak') && is_writable($data[0] . '.bak')) {
        !          79331:                         unlink($data[0] . '.bak');
        !          79332:                         $this->log(3, "+ rm backup of $data[0] ($data[0].bak)");
        !          79333:                     }
        !          79334:                     break;
        !          79335:                 case 'rename':
        !          79336:                     $test = file_exists($data[1]) ? @unlink($data[1]) : null;
        !          79337:                     if (!$test && file_exists($data[1])) {
        !          79338:                         if ($data[2]) {
        !          79339:                             $extra = ', this extension must be installed manually.  Rename to "' .
        !          79340:                                 basename($data[1]) . '"';
        !          79341:                         } else {
        !          79342:                             $extra = '';
        !          79343:                         }
        !          79344: 
        !          79345:                         if (!isset($this->_options['soft'])) {
        !          79346:                             $this->log(1, 'Could not delete ' . $data[1] . ', cannot rename ' .
        !          79347:                                 $data[0] . $extra);
        !          79348:                         }
        !          79349: 
        !          79350:                         if (!isset($this->_options['ignore-errors'])) {
        !          79351:                             return false;
        !          79352:                         }
        !          79353:                     }
        !          79354: 
        !          79355:                     // permissions issues with rename - copy() is far superior
        !          79356:                     $perms = @fileperms($data[0]);
        !          79357:                     if (!@copy($data[0], $data[1])) {
        !          79358:                         $this->log(1, 'Could not rename ' . $data[0] . ' to ' . $data[1] .
        !          79359:                             ' ' . $php_errormsg);
        !          79360:                         return false;
        !          79361:                     }
        !          79362: 
        !          79363:                     // copy over permissions, otherwise they are lost
        !          79364:                     @chmod($data[1], $perms);
        !          79365:                     @unlink($data[0]);
        !          79366:                     $this->log(3, "+ mv $data[0] $data[1]");
        !          79367:                     break;
        !          79368:                 case 'chmod':
        !          79369:                     if (!@chmod($data[1], $data[0])) {
        !          79370:                         $this->log(1, 'Could not chmod ' . $data[1] . ' to ' .
        !          79371:                             decoct($data[0]) . ' ' . $php_errormsg);
        !          79372:                         return false;
        !          79373:                     }
        !          79374: 
        !          79375:                     $octmode = decoct($data[0]);
        !          79376:                     $this->log(3, "+ chmod $octmode $data[1]");
        !          79377:                     break;
        !          79378:                 case 'delete':
        !          79379:                     if (file_exists($data[0])) {
        !          79380:                         if (!@unlink($data[0])) {
        !          79381:                             $this->log(1, 'Could not delete ' . $data[0] . ' ' .
        !          79382:                                 $php_errormsg);
        !          79383:                             return false;
        !          79384:                         }
        !          79385:                         $this->log(3, "+ rm $data[0]");
        !          79386:                     }
        !          79387:                     break;
        !          79388:                 case 'rmdir':
        !          79389:                     if (file_exists($data[0])) {
        !          79390:                         do {
        !          79391:                             $testme = opendir($data[0]);
        !          79392:                             while (false !== ($entry = readdir($testme))) {
        !          79393:                                 if ($entry == '.' || $entry == '..') {
        !          79394:                                     continue;
        !          79395:                                 }
        !          79396:                                 closedir($testme);
        !          79397:                                 break 2; // this directory is not empty and can't be
        !          79398:                                          // deleted
        !          79399:                             }
        !          79400: 
        !          79401:                             closedir($testme);
        !          79402:                             if (!@rmdir($data[0])) {
        !          79403:                                 $this->log(1, 'Could not rmdir ' . $data[0] . ' ' .
        !          79404:                                     $php_errormsg);
        !          79405:                                 return false;
        !          79406:                             }
        !          79407:                             $this->log(3, "+ rmdir $data[0]");
        !          79408:                         } while (false);
        !          79409:                     }
        !          79410:                     break;
        !          79411:                 case 'installed_as':
        !          79412:                     $this->pkginfo->setInstalledAs($data[0], $data[1]);
        !          79413:                     if (!isset($this->_dirtree[dirname($data[1])])) {
        !          79414:                         $this->_dirtree[dirname($data[1])] = true;
        !          79415:                         $this->pkginfo->setDirtree(dirname($data[1]));
        !          79416: 
        !          79417:                         while(!empty($data[3]) && dirname($data[3]) != $data[3] &&
        !          79418:                                 $data[3] != '/' && $data[3] != '\\') {
        !          79419:                             $this->pkginfo->setDirtree($pp =
        !          79420:                                 $this->_prependPath($data[3], $data[2]));
        !          79421:                             $this->_dirtree[$pp] = true;
        !          79422:                             $data[3] = dirname($data[3]);
        !          79423:                         }
        !          79424:                     }
        !          79425:                     break;
1.1       misho    79426:             }
                   79427:         }
1.1.1.2 ! misho    79428:         // }}}
        !          79429:         $this->log(2, "successfully committed $n file operations");
        !          79430:         $this->file_operations = array();
        !          79431:         return true;
1.1       misho    79432:     }
1.1.1.2 ! misho    79433: 
        !          79434:     // }}}
        !          79435:     // {{{ rollbackFileTransaction()
        !          79436: 
        !          79437:     function rollbackFileTransaction()
1.1       misho    79438:     {
1.1.1.2 ! misho    79439:         $n = count($this->file_operations);
        !          79440:         $this->log(2, "rolling back $n file operations");
        !          79441:         foreach ($this->file_operations as $tr) {
        !          79442:             list($type, $data) = $tr;
        !          79443:             switch ($type) {
        !          79444:                 case 'backup':
        !          79445:                     if (file_exists($data[0] . '.bak')) {
        !          79446:                         if (file_exists($data[0] && is_writable($data[0]))) {
        !          79447:                             unlink($data[0]);
        !          79448:                         }
        !          79449:                         @copy($data[0] . '.bak', $data[0]);
        !          79450:                         $this->log(3, "+ restore $data[0] from $data[0].bak");
        !          79451:                     }
        !          79452:                     break;
        !          79453:                 case 'removebackup':
        !          79454:                     if (file_exists($data[0] . '.bak') && is_writable($data[0] . '.bak')) {
        !          79455:                         unlink($data[0] . '.bak');
        !          79456:                         $this->log(3, "+ rm backup of $data[0] ($data[0].bak)");
        !          79457:                     }
        !          79458:                     break;
        !          79459:                 case 'rename':
        !          79460:                     @unlink($data[0]);
        !          79461:                     $this->log(3, "+ rm $data[0]");
        !          79462:                     break;
        !          79463:                 case 'mkdir':
        !          79464:                     @rmdir($data[0]);
        !          79465:                     $this->log(3, "+ rmdir $data[0]");
        !          79466:                     break;
        !          79467:                 case 'chmod':
        !          79468:                     break;
        !          79469:                 case 'delete':
        !          79470:                     break;
        !          79471:                 case 'installed_as':
        !          79472:                     $this->pkginfo->setInstalledAs($data[0], false);
        !          79473:                     break;
        !          79474:             }
1.1       misho    79475:         }
1.1.1.2 ! misho    79476:         $this->pkginfo->resetDirtree();
        !          79477:         $this->file_operations = array();
1.1       misho    79478:     }
1.1.1.2 ! misho    79479: 
        !          79480:     // }}}
        !          79481:     // {{{ mkDirHier($dir)
        !          79482: 
        !          79483:     function mkDirHier($dir)
1.1       misho    79484:     {
1.1.1.2 ! misho    79485:         $this->addFileOperation('mkdir', array($dir));
        !          79486:         return parent::mkDirHier($dir);
1.1       misho    79487:     }
1.1.1.2 ! misho    79488: 
        !          79489:     // }}}
        !          79490:     // {{{ download()
        !          79491: 
1.1       misho    79492:     /**
1.1.1.2 ! misho    79493:      * Download any files and their dependencies, if necessary
        !          79494:      *
        !          79495:      * @param array a mixed list of package names, local files, or package.xml
        !          79496:      * @param PEAR_Config
        !          79497:      * @param array options from the command line
        !          79498:      * @param array this is the array that will be populated with packages to
        !          79499:      *              install.  Format of each entry:
        !          79500:      *
        !          79501:      * <code>
        !          79502:      * array('pkg' => 'package_name', 'file' => '/path/to/local/file',
        !          79503:      *    'info' => array() // parsed package.xml
        !          79504:      * );
        !          79505:      * </code>
        !          79506:      * @param array this will be populated with any error messages
        !          79507:      * @param false private recursion variable
        !          79508:      * @param false private recursion variable
        !          79509:      * @param false private recursion variable
        !          79510:      * @deprecated in favor of PEAR_Downloader
1.1       misho    79511:      */
1.1.1.2 ! misho    79512:     function download($packages, $options, &$config, &$installpackages,
        !          79513:                       &$errors, $installed = false, $willinstall = false, $state = false)
1.1       misho    79514:     {
1.1.1.2 ! misho    79515:         // trickiness: initialize here
        !          79516:         parent::PEAR_Downloader($this->ui, $options, $config);
        !          79517:         $ret             = parent::download($packages);
        !          79518:         $errors          = $this->getErrorMsgs();
        !          79519:         $installpackages = $this->getDownloadedPackages();
        !          79520:         trigger_error("PEAR Warning: PEAR_Installer::download() is deprecated " .
        !          79521:                       "in favor of PEAR_Downloader class", E_USER_WARNING);
        !          79522:         return $ret;
1.1       misho    79523:     }
1.1.1.2 ! misho    79524: 
        !          79525:     // }}}
        !          79526:     // {{{ _parsePackageXml()
        !          79527: 
        !          79528:     function _parsePackageXml(&$descfile)
1.1       misho    79529:     {
1.1.1.2 ! misho    79530:         // Parse xml file -----------------------------------------------
        !          79531:         $pkg = new PEAR_PackageFile($this->config, $this->debug);
        !          79532:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          79533:         $p = &$pkg->fromAnyFile($descfile, PEAR_VALIDATE_INSTALLING);
        !          79534:         PEAR::staticPopErrorHandling();
        !          79535:         if (PEAR::isError($p)) {
        !          79536:             if (is_array($p->getUserInfo())) {
        !          79537:                 foreach ($p->getUserInfo() as $err) {
        !          79538:                     $loglevel = $err['level'] == 'error' ? 0 : 1;
        !          79539:                     if (!isset($this->_options['soft'])) {
        !          79540:                         $this->log($loglevel, ucfirst($err['level']) . ': ' . $err['message']);
        !          79541:                     }
        !          79542:                 }
        !          79543:             }
        !          79544:             return $this->raiseError('Installation failed: invalid package file');
1.1       misho    79545:         }
1.1.1.2 ! misho    79546: 
        !          79547:         $descfile = $p->getPackageFile();
        !          79548:         return $p;
1.1       misho    79549:     }
1.1.1.2 ! misho    79550: 
        !          79551:     // }}}
1.1       misho    79552:     /**
1.1.1.2 ! misho    79553:      * Set the list of PEAR_Downloader_Package objects to allow more sane
        !          79554:      * dependency validation
        !          79555:      * @param array
1.1       misho    79556:      */
1.1.1.2 ! misho    79557:     function setDownloadedPackages(&$pkgs)
1.1       misho    79558:     {
1.1.1.2 ! misho    79559:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          79560:         $err = $this->analyzeDependencies($pkgs);
        !          79561:         PEAR::popErrorHandling();
        !          79562:         if (PEAR::isError($err)) {
        !          79563:             return $err;
1.1       misho    79564:         }
1.1.1.2 ! misho    79565:         $this->_downloadedPackages = &$pkgs;
1.1       misho    79566:     }
1.1.1.2 ! misho    79567: 
1.1       misho    79568:     /**
1.1.1.2 ! misho    79569:      * Set the list of PEAR_Downloader_Package objects to allow more sane
        !          79570:      * dependency validation
        !          79571:      * @param array
1.1       misho    79572:      */
1.1.1.2 ! misho    79573:     function setUninstallPackages(&$pkgs)
1.1       misho    79574:     {
1.1.1.2 ! misho    79575:         $this->_downloadedPackages = &$pkgs;
1.1       misho    79576:     }
1.1.1.2 ! misho    79577: 
        !          79578:     function getInstallPackages()
1.1       misho    79579:     {
1.1.1.2 ! misho    79580:         return $this->_downloadedPackages;
1.1       misho    79581:     }
1.1.1.2 ! misho    79582: 
        !          79583:     // {{{ install()
        !          79584: 
1.1       misho    79585:     /**
1.1.1.2 ! misho    79586:      * Installs the files within the package file specified.
1.1       misho    79587:      *
1.1.1.2 ! misho    79588:      * @param string|PEAR_Downloader_Package $pkgfile path to the package file,
        !          79589:      *        or a pre-initialized packagefile object
        !          79590:      * @param array $options
        !          79591:      * recognized options:
        !          79592:      * - installroot   : optional prefix directory for installation
        !          79593:      * - force         : force installation
        !          79594:      * - register-only : update registry but don't install files
        !          79595:      * - upgrade       : upgrade existing install
        !          79596:      * - soft          : fail silently
        !          79597:      * - nodeps        : ignore dependency conflicts/missing dependencies
        !          79598:      * - alldeps       : install all dependencies
        !          79599:      * - onlyreqdeps   : install only required dependencies
        !          79600:      *
        !          79601:      * @return array|PEAR_Error package info if successful
1.1       misho    79602:      */
1.1.1.2 ! misho    79603:     function install($pkgfile, $options = array())
1.1       misho    79604:     {
1.1.1.2 ! misho    79605:         $this->_options = $options;
        !          79606:         $this->_registry = &$this->config->getRegistry();
        !          79607:         if (is_object($pkgfile)) {
        !          79608:             $dlpkg    = &$pkgfile;
        !          79609:             $pkg      = $pkgfile->getPackageFile();
        !          79610:             $pkgfile  = $pkg->getArchiveFile();
        !          79611:             $descfile = $pkg->getPackageFile();
        !          79612:         } else {
        !          79613:             $descfile = $pkgfile;
        !          79614:             $pkg      = $this->_parsePackageXml($descfile);
        !          79615:             if (PEAR::isError($pkg)) {
        !          79616:                 return $pkg;
        !          79617:             }
1.1       misho    79618:         }
1.1.1.2 ! misho    79619: 
        !          79620:         $tmpdir = dirname($descfile);
        !          79621:         if (realpath($descfile) != realpath($pkgfile)) {
        !          79622:             // Use the temp_dir since $descfile can contain the download dir path
        !          79623:             $tmpdir = $this->config->get('temp_dir', null, 'pear.php.net');
        !          79624:             $tmpdir = System::mktemp('-d -t "' . $tmpdir . '"');
        !          79625: 
        !          79626:             $tar = new Archive_Tar($pkgfile);
        !          79627:             if (!$tar->extract($tmpdir)) {
        !          79628:                 return $this->raiseError("unable to unpack $pkgfile");
        !          79629:             }
        !          79630:         }
        !          79631: 
        !          79632:         $pkgname = $pkg->getName();
        !          79633:         $channel = $pkg->getChannel();
        !          79634:         if (isset($this->_options['packagingroot'])) {
        !          79635:             $regdir = $this->_prependPath(
        !          79636:                 $this->config->get('php_dir', null, 'pear.php.net'),
        !          79637:                 $this->_options['packagingroot']);
        !          79638: 
        !          79639:             $packrootphp_dir = $this->_prependPath(
        !          79640:                 $this->config->get('php_dir', null, $channel),
        !          79641:                 $this->_options['packagingroot']);
        !          79642:         }
        !          79643: 
        !          79644:         if (isset($options['installroot'])) {
        !          79645:             $this->config->setInstallRoot($options['installroot']);
        !          79646:             $this->_registry = &$this->config->getRegistry();
        !          79647:             $installregistry = &$this->_registry;
        !          79648:             $this->installroot = ''; // all done automagically now
        !          79649:             $php_dir = $this->config->get('php_dir', null, $channel);
        !          79650:         } else {
        !          79651:             $this->config->setInstallRoot(false);
        !          79652:             $this->_registry = &$this->config->getRegistry();
        !          79653:             if (isset($this->_options['packagingroot'])) {
        !          79654:                 $installregistry = &new PEAR_Registry($regdir);
        !          79655:                 if (!$installregistry->channelExists($channel, true)) {
        !          79656:                     // we need to fake a channel-discover of this channel
        !          79657:                     $chanobj = $this->_registry->getChannel($channel, true);
        !          79658:                     $installregistry->addChannel($chanobj);
        !          79659:                 }
        !          79660:                 $php_dir = $packrootphp_dir;
        !          79661:             } else {
        !          79662:                 $installregistry = &$this->_registry;
        !          79663:                 $php_dir = $this->config->get('php_dir', null, $channel);
        !          79664:             }
        !          79665:             $this->installroot = '';
        !          79666:         }
        !          79667: 
        !          79668:         // {{{ checks to do when not in "force" mode
        !          79669:         if (empty($options['force']) &&
        !          79670:               (file_exists($this->config->get('php_dir')) &&
        !          79671:                is_dir($this->config->get('php_dir')))) {
        !          79672:             $testp = $channel == 'pear.php.net' ? $pkgname : array($channel, $pkgname);
        !          79673:             $instfilelist = $pkg->getInstallationFileList(true);
        !          79674:             if (PEAR::isError($instfilelist)) {
        !          79675:                 return $instfilelist;
        !          79676:             }
        !          79677: 
        !          79678:             // ensure we have the most accurate registry
        !          79679:             $installregistry->flushFileMap();
        !          79680:             $test = $installregistry->checkFileMap($instfilelist, $testp, '1.1');
        !          79681:             if (PEAR::isError($test)) {
        !          79682:                 return $test;
        !          79683:             }
        !          79684: 
        !          79685:             if (sizeof($test)) {
        !          79686:                 $pkgs = $this->getInstallPackages();
        !          79687:                 $found = false;
        !          79688:                 foreach ($pkgs as $param) {
        !          79689:                     if ($pkg->isSubpackageOf($param)) {
        !          79690:                         $found = true;
        !          79691:                         break;
        !          79692:                     }
        !          79693:                 }
        !          79694: 
        !          79695:                 if ($found) {
        !          79696:                     // subpackages can conflict with earlier versions of parent packages
        !          79697:                     $parentreg = $installregistry->packageInfo($param->getPackage(), null, $param->getChannel());
        !          79698:                     $tmp = $test;
        !          79699:                     foreach ($tmp as $file => $info) {
        !          79700:                         if (is_array($info)) {
        !          79701:                             if (strtolower($info[1]) == strtolower($param->getPackage()) &&
        !          79702:                                   strtolower($info[0]) == strtolower($param->getChannel())
        !          79703:                             ) {
        !          79704:                                 if (isset($parentreg['filelist'][$file])) {
        !          79705:                                     unset($parentreg['filelist'][$file]);
        !          79706:                                 } else{
        !          79707:                                     $pos     = strpos($file, '/');
        !          79708:                                     $basedir = substr($file, 0, $pos);
        !          79709:                                     $file2   = substr($file, $pos + 1);
        !          79710:                                     if (isset($parentreg['filelist'][$file2]['baseinstalldir'])
        !          79711:                                         && $parentreg['filelist'][$file2]['baseinstalldir'] === $basedir
        !          79712:                                     ) {
        !          79713:                                         unset($parentreg['filelist'][$file2]);
        !          79714:                                     }
        !          79715:                                 }
        !          79716: 
        !          79717:                                 unset($test[$file]);
        !          79718:                             }
        !          79719:                         } else {
        !          79720:                             if (strtolower($param->getChannel()) != 'pear.php.net') {
        !          79721:                                 continue;
        !          79722:                             }
        !          79723: 
        !          79724:                             if (strtolower($info) == strtolower($param->getPackage())) {
        !          79725:                                 if (isset($parentreg['filelist'][$file])) {
        !          79726:                                     unset($parentreg['filelist'][$file]);
        !          79727:                                 } else{
        !          79728:                                     $pos     = strpos($file, '/');
        !          79729:                                     $basedir = substr($file, 0, $pos);
        !          79730:                                     $file2   = substr($file, $pos + 1);
        !          79731:                                     if (isset($parentreg['filelist'][$file2]['baseinstalldir'])
        !          79732:                                         && $parentreg['filelist'][$file2]['baseinstalldir'] === $basedir
        !          79733:                                     ) {
        !          79734:                                         unset($parentreg['filelist'][$file2]);
        !          79735:                                     }
        !          79736:                                 }
        !          79737: 
        !          79738:                                 unset($test[$file]);
        !          79739:                             }
        !          79740:                         }
        !          79741:                     }
        !          79742: 
        !          79743:                     $pfk = &new PEAR_PackageFile($this->config);
        !          79744:                     $parentpkg = &$pfk->fromArray($parentreg);
        !          79745:                     $installregistry->updatePackage2($parentpkg);
        !          79746:                 }
        !          79747: 
        !          79748:                 if ($param->getChannel() == 'pecl.php.net' && isset($options['upgrade'])) {
        !          79749:                     $tmp = $test;
        !          79750:                     foreach ($tmp as $file => $info) {
        !          79751:                         if (is_string($info)) {
        !          79752:                             // pear.php.net packages are always stored as strings
        !          79753:                             if (strtolower($info) == strtolower($param->getPackage())) {
        !          79754:                                 // upgrading existing package
        !          79755:                                 unset($test[$file]);
        !          79756:                             }
        !          79757:                         }
        !          79758:                     }
        !          79759:                 }
        !          79760: 
        !          79761:                 if (count($test)) {
        !          79762:                     $msg = "$channel/$pkgname: conflicting files found:\n";
        !          79763:                     $longest = max(array_map("strlen", array_keys($test)));
        !          79764:                     $fmt = "%${longest}s (%s)\n";
        !          79765:                     foreach ($test as $file => $info) {
        !          79766:                         if (!is_array($info)) {
        !          79767:                             $info = array('pear.php.net', $info);
        !          79768:                         }
        !          79769:                         $info = $info[0] . '/' . $info[1];
        !          79770:                         $msg .= sprintf($fmt, $file, $info);
        !          79771:                     }
        !          79772: 
        !          79773:                     if (!isset($options['ignore-errors'])) {
        !          79774:                         return $this->raiseError($msg);
        !          79775:                     }
        !          79776: 
        !          79777:                     if (!isset($options['soft'])) {
        !          79778:                         $this->log(0, "WARNING: $msg");
        !          79779:                     }
        !          79780:                 }
        !          79781:             }
        !          79782:         }
        !          79783:         // }}}
        !          79784: 
        !          79785:         $this->startFileTransaction();
        !          79786: 
        !          79787:         $usechannel = $channel;
        !          79788:         if ($channel == 'pecl.php.net') {
        !          79789:             $test = $installregistry->packageExists($pkgname, $channel);
        !          79790:             if (!$test) {
        !          79791:                 $test = $installregistry->packageExists($pkgname, 'pear.php.net');
        !          79792:                 $usechannel = 'pear.php.net';
        !          79793:             }
        !          79794:         } else {
        !          79795:             $test = $installregistry->packageExists($pkgname, $channel);
        !          79796:         }
        !          79797: 
        !          79798:         if (empty($options['upgrade']) && empty($options['soft'])) {
        !          79799:             // checks to do only when installing new packages
        !          79800:             if (empty($options['force']) && $test) {
        !          79801:                 return $this->raiseError("$channel/$pkgname is already installed");
        !          79802:             }
        !          79803:         } else {
        !          79804:             // Upgrade
        !          79805:             if ($test) {
        !          79806:                 $v1 = $installregistry->packageInfo($pkgname, 'version', $usechannel);
        !          79807:                 $v2 = $pkg->getVersion();
        !          79808:                 $cmp = version_compare("$v1", "$v2", 'gt');
        !          79809:                 if (empty($options['force']) && !version_compare("$v2", "$v1", 'gt')) {
        !          79810:                     return $this->raiseError("upgrade to a newer version ($v2 is not newer than $v1)");
        !          79811:                 }
        !          79812:             }
        !          79813:         }
        !          79814: 
        !          79815:         // Do cleanups for upgrade and install, remove old release's files first
        !          79816:         if ($test && empty($options['register-only'])) {
        !          79817:             // when upgrading, remove old release's files first:
        !          79818:             if (PEAR::isError($err = $this->_deletePackageFiles($pkgname, $usechannel,
        !          79819:                   true))) {
        !          79820:                 if (!isset($options['ignore-errors'])) {
        !          79821:                     return $this->raiseError($err);
        !          79822:                 }
        !          79823: 
        !          79824:                 if (!isset($options['soft'])) {
        !          79825:                     $this->log(0, 'WARNING: ' . $err->getMessage());
        !          79826:                 }
        !          79827:             } else {
        !          79828:                 $backedup = $err;
        !          79829:             }
        !          79830:         }
        !          79831: 
        !          79832:         // {{{ Copy files to dest dir ---------------------------------------
        !          79833: 
        !          79834:         // info from the package it self we want to access from _installFile
        !          79835:         $this->pkginfo = &$pkg;
        !          79836:         // used to determine whether we should build any C code
        !          79837:         $this->source_files = 0;
        !          79838: 
        !          79839:         $savechannel = $this->config->get('default_channel');
        !          79840:         if (empty($options['register-only']) && !is_dir($php_dir)) {
        !          79841:             if (PEAR::isError(System::mkdir(array('-p'), $php_dir))) {
        !          79842:                 return $this->raiseError("no installation destination directory '$php_dir'\n");
        !          79843:             }
        !          79844:         }
        !          79845: 
        !          79846:         if (substr($pkgfile, -4) != '.xml') {
        !          79847:             $tmpdir .= DIRECTORY_SEPARATOR . $pkgname . '-' . $pkg->getVersion();
        !          79848:         }
        !          79849: 
        !          79850:         $this->configSet('default_channel', $channel);
        !          79851:         // {{{ install files
        !          79852: 
        !          79853:         $ver = $pkg->getPackagexmlVersion();
        !          79854:         if (version_compare($ver, '2.0', '>=')) {
        !          79855:             $filelist = $pkg->getInstallationFilelist();
        !          79856:         } else {
        !          79857:             $filelist = $pkg->getFileList();
        !          79858:         }
        !          79859: 
        !          79860:         if (PEAR::isError($filelist)) {
        !          79861:             return $filelist;
        !          79862:         }
        !          79863: 
        !          79864:         $p = &$installregistry->getPackage($pkgname, $channel);
        !          79865:         $dirtree = (empty($options['register-only']) && $p) ? $p->getDirTree() : false;
        !          79866: 
        !          79867:         $pkg->resetFilelist();
        !          79868:         $pkg->setLastInstalledVersion($installregistry->packageInfo($pkg->getPackage(),
        !          79869:             'version', $pkg->getChannel()));
        !          79870:         foreach ($filelist as $file => $atts) {
        !          79871:             $this->expectError(PEAR_INSTALLER_FAILED);
        !          79872:             if ($pkg->getPackagexmlVersion() == '1.0') {
        !          79873:                 $res = $this->_installFile($file, $atts, $tmpdir, $options);
        !          79874:             } else {
        !          79875:                 $res = $this->_installFile2($pkg, $file, $atts, $tmpdir, $options);
        !          79876:             }
        !          79877:             $this->popExpect();
        !          79878: 
        !          79879:             if (PEAR::isError($res)) {
        !          79880:                 if (empty($options['ignore-errors'])) {
        !          79881:                     $this->rollbackFileTransaction();
        !          79882:                     if ($res->getMessage() == "file does not exist") {
        !          79883:                         $this->raiseError("file $file in package.xml does not exist");
        !          79884:                     }
        !          79885: 
        !          79886:                     return $this->raiseError($res);
        !          79887:                 }
        !          79888: 
        !          79889:                 if (!isset($options['soft'])) {
        !          79890:                     $this->log(0, "Warning: " . $res->getMessage());
        !          79891:                 }
        !          79892:             }
        !          79893: 
        !          79894:             $real = isset($atts['attribs']) ? $atts['attribs'] : $atts;
        !          79895:             if ($res == PEAR_INSTALLER_OK && $real['role'] != 'src') {
        !          79896:                 // Register files that were installed
        !          79897:                 $pkg->installedFile($file, $atts);
        !          79898:             }
        !          79899:         }
        !          79900:         // }}}
        !          79901: 
        !          79902:         // {{{ compile and install source files
        !          79903:         if ($this->source_files > 0 && empty($options['nobuild'])) {
        !          79904:             if (PEAR::isError($err =
        !          79905:                   $this->_compileSourceFiles($savechannel, $pkg))) {
        !          79906:                 return $err;
1.1       misho    79907:             }
                   79908:         }
1.1.1.2 ! misho    79909:         // }}}
1.1       misho    79910: 
1.1.1.2 ! misho    79911:         if (isset($backedup)) {
        !          79912:             $this->_removeBackups($backedup);
1.1       misho    79913:         }
                   79914: 
1.1.1.2 ! misho    79915:         if (!$this->commitFileTransaction()) {
        !          79916:             $this->rollbackFileTransaction();
        !          79917:             $this->configSet('default_channel', $savechannel);
        !          79918:             return $this->raiseError("commit failed", PEAR_INSTALLER_FAILED);
1.1       misho    79919:         }
1.1.1.2 ! misho    79920:         // }}}
        !          79921: 
        !          79922:         $ret          = false;
        !          79923:         $installphase = 'install';
        !          79924:         $oldversion   = false;
        !          79925:         // {{{ Register that the package is installed -----------------------
        !          79926:         if (empty($options['upgrade'])) {
        !          79927:             // if 'force' is used, replace the info in registry
        !          79928:             $usechannel = $channel;
        !          79929:             if ($channel == 'pecl.php.net') {
        !          79930:                 $test = $installregistry->packageExists($pkgname, $channel);
        !          79931:                 if (!$test) {
        !          79932:                     $test = $installregistry->packageExists($pkgname, 'pear.php.net');
        !          79933:                     $usechannel = 'pear.php.net';
        !          79934:                 }
1.1       misho    79935:             } else {
1.1.1.2 ! misho    79936:                 $test = $installregistry->packageExists($pkgname, $channel);
1.1       misho    79937:             }
1.1.1.2 ! misho    79938: 
        !          79939:             if (!empty($options['force']) && $test) {
        !          79940:                 $oldversion = $installregistry->packageInfo($pkgname, 'version', $usechannel);
        !          79941:                 $installregistry->deletePackage($pkgname, $usechannel);
1.1       misho    79942:             }
1.1.1.2 ! misho    79943:             $ret = $installregistry->addPackage2($pkg);
        !          79944:         } else {
        !          79945:             if ($dirtree) {
        !          79946:                 $this->startFileTransaction();
        !          79947:                 // attempt to delete empty directories
        !          79948:                 uksort($dirtree, array($this, '_sortDirs'));
        !          79949:                 foreach($dirtree as $dir => $notused) {
        !          79950:                     $this->addFileOperation('rmdir', array($dir));
        !          79951:                 }
        !          79952:                 $this->commitFileTransaction();
1.1       misho    79953:             }
1.1.1.2 ! misho    79954: 
        !          79955:             $usechannel = $channel;
        !          79956:             if ($channel == 'pecl.php.net') {
        !          79957:                 $test = $installregistry->packageExists($pkgname, $channel);
        !          79958:                 if (!$test) {
        !          79959:                     $test = $installregistry->packageExists($pkgname, 'pear.php.net');
        !          79960:                     $usechannel = 'pear.php.net';
        !          79961:                 }
        !          79962:             } else {
        !          79963:                 $test = $installregistry->packageExists($pkgname, $channel);
        !          79964:             }
        !          79965: 
        !          79966:             // new: upgrade installs a package if it isn't installed
        !          79967:             if (!$test) {
        !          79968:                 $ret = $installregistry->addPackage2($pkg);
        !          79969:             } else {
        !          79970:                 if ($usechannel != $channel) {
        !          79971:                     $installregistry->deletePackage($pkgname, $usechannel);
        !          79972:                     $ret = $installregistry->addPackage2($pkg);
        !          79973:                 } else {
        !          79974:                     $ret = $installregistry->updatePackage2($pkg);
        !          79975:                 }
        !          79976:                 $installphase = 'upgrade';
1.1       misho    79977:             }
                   79978:         }
1.1.1.2 ! misho    79979: 
        !          79980:         if (!$ret) {
        !          79981:             $this->configSet('default_channel', $savechannel);
        !          79982:             return $this->raiseError("Adding package $channel/$pkgname to registry failed");
1.1       misho    79983:         }
1.1.1.2 ! misho    79984:         // }}}
        !          79985: 
        !          79986:         $this->configSet('default_channel', $savechannel);
        !          79987:         if (class_exists('PEAR_Task_Common')) { // this is auto-included if any tasks exist
        !          79988:             if (PEAR_Task_Common::hasPostinstallTasks()) {
        !          79989:                 PEAR_Task_Common::runPostinstallTasks($installphase);
        !          79990:             }
1.1       misho    79991:         }
1.1.1.2 ! misho    79992: 
        !          79993:         return $pkg->toArray(true);
1.1       misho    79994:     }
1.1.1.2 ! misho    79995: 
        !          79996:     // }}}
        !          79997: 
        !          79998:     // {{{ _compileSourceFiles()
1.1       misho    79999:     /**
1.1.1.2 ! misho    80000:      * @param string
        !          80001:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
1.1       misho    80002:      */
1.1.1.2 ! misho    80003:     function _compileSourceFiles($savechannel, &$filelist)
1.1       misho    80004:     {
1.1.1.2 ! misho    80005:         require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Builder.php';
        !          80006:         $this->log(1, "$this->source_files source files, building");
        !          80007:         $bob = &new PEAR_Builder($this->ui);
        !          80008:         $bob->debug = $this->debug;
        !          80009:         $built = $bob->build($filelist, array(&$this, '_buildCallback'));
        !          80010:         if (PEAR::isError($built)) {
        !          80011:             $this->rollbackFileTransaction();
        !          80012:             $this->configSet('default_channel', $savechannel);
        !          80013:             return $built;
        !          80014:         }
        !          80015: 
        !          80016:         $this->log(1, "\nBuild process completed successfully");
        !          80017:         foreach ($built as $ext) {
        !          80018:             $bn = basename($ext['file']);
        !          80019:             list($_ext_name, $_ext_suff) = explode('.', $bn);
        !          80020:             if ($_ext_suff == '.so' || $_ext_suff == '.dll') {
        !          80021:                 if (extension_loaded($_ext_name)) {
        !          80022:                     $this->raiseError("Extension '$_ext_name' already loaded. " .
        !          80023:                                       'Please unload it in your php.ini file ' .
        !          80024:                                       'prior to install or upgrade');
        !          80025:                 }
        !          80026:                 $role = 'ext';
        !          80027:             } else {
        !          80028:                 $role = 'src';
        !          80029:             }
        !          80030: 
        !          80031:             $dest = $ext['dest'];
        !          80032:             $packagingroot = '';
        !          80033:             if (isset($this->_options['packagingroot'])) {
        !          80034:                 $packagingroot = $this->_options['packagingroot'];
        !          80035:             }
        !          80036: 
        !          80037:             $copyto = $this->_prependPath($dest, $packagingroot);
        !          80038:             $extra  = $copyto != $dest ? " as '$copyto'" : '';
        !          80039:             $this->log(1, "Installing '$dest'$extra");
        !          80040: 
        !          80041:             $copydir = dirname($copyto);
        !          80042:             // pretty much nothing happens if we are only registering the install
        !          80043:             if (empty($this->_options['register-only'])) {
        !          80044:                 if (!file_exists($copydir) || !is_dir($copydir)) {
        !          80045:                     if (!$this->mkDirHier($copydir)) {
        !          80046:                         return $this->raiseError("failed to mkdir $copydir",
        !          80047:                             PEAR_INSTALLER_FAILED);
        !          80048:                     }
        !          80049: 
        !          80050:                     $this->log(3, "+ mkdir $copydir");
        !          80051:                 }
        !          80052: 
        !          80053:                 if (!@copy($ext['file'], $copyto)) {
        !          80054:                     return $this->raiseError("failed to write $copyto ($php_errormsg)", PEAR_INSTALLER_FAILED);
1.1       misho    80055:                 }
1.1.1.2 ! misho    80056: 
        !          80057:                 $this->log(3, "+ cp $ext[file] $copyto");
        !          80058:                 $this->addFileOperation('rename', array($ext['file'], $copyto));
        !          80059:                 if (!OS_WINDOWS) {
        !          80060:                     $mode = 0666 & ~(int)octdec($this->config->get('umask'));
        !          80061:                     $this->addFileOperation('chmod', array($mode, $copyto));
        !          80062:                     if (!@chmod($copyto, $mode)) {
        !          80063:                         $this->log(0, "failed to change mode of $copyto ($php_errormsg)");
        !          80064:                     }
        !          80065:                 }
        !          80066:             }
        !          80067: 
        !          80068: 
        !          80069:             $data = array(
        !          80070:                 'role'         => $role,
        !          80071:                 'name'         => $bn,
        !          80072:                 'installed_as' => $dest,
        !          80073:                 'php_api'      => $ext['php_api'],
        !          80074:                 'zend_mod_api' => $ext['zend_mod_api'],
        !          80075:                 'zend_ext_api' => $ext['zend_ext_api'],
        !          80076:             );
        !          80077: 
        !          80078:             if ($filelist->getPackageXmlVersion() == '1.0') {
        !          80079:                 $filelist->installedFile($bn, $data);
        !          80080:             } else {
        !          80081:                 $filelist->installedFile($bn, array('attribs' => $data));
1.1       misho    80082:             }
                   80083:         }
                   80084:     }
1.1.1.2 ! misho    80085: 
        !          80086:     // }}}
        !          80087:     function &getUninstallPackages()
        !          80088:     {
        !          80089:         return $this->_downloadedPackages;
        !          80090:     }
        !          80091:     // {{{ uninstall()
        !          80092: 
1.1       misho    80093:     /**
1.1.1.2 ! misho    80094:      * Uninstall a package
        !          80095:      *
        !          80096:      * This method removes all files installed by the application, and then
        !          80097:      * removes any empty directories.
        !          80098:      * @param string package name
        !          80099:      * @param array Command-line options.  Possibilities include:
        !          80100:      *
        !          80101:      *              - installroot: base installation dir, if not the default
        !          80102:      *              - register-only : update registry but don't remove files
        !          80103:      *              - nodeps: do not process dependencies of other packages to ensure
        !          80104:      *                        uninstallation does not break things
1.1       misho    80105:      */
1.1.1.2 ! misho    80106:     function uninstall($package, $options = array())
1.1       misho    80107:     {
1.1.1.2 ! misho    80108:         $installRoot = isset($options['installroot']) ? $options['installroot'] : '';
        !          80109:         $this->config->setInstallRoot($installRoot);
        !          80110: 
        !          80111:         $this->installroot = '';
        !          80112:         $this->_registry = &$this->config->getRegistry();
        !          80113:         if (is_object($package)) {
        !          80114:             $channel = $package->getChannel();
        !          80115:             $pkg     = $package;
        !          80116:             $package = $pkg->getPackage();
1.1       misho    80117:         } else {
1.1.1.2 ! misho    80118:             $pkg = false;
        !          80119:             $info = $this->_registry->parsePackageName($package,
        !          80120:                 $this->config->get('default_channel'));
        !          80121:             $channel = $info['channel'];
        !          80122:             $package = $info['package'];
1.1       misho    80123:         }
1.1.1.2 ! misho    80124: 
        !          80125:         $savechannel = $this->config->get('default_channel');
        !          80126:         $this->configSet('default_channel', $channel);
        !          80127:         if (!is_object($pkg)) {
        !          80128:             $pkg = $this->_registry->getPackage($package, $channel);
        !          80129:         }
        !          80130: 
        !          80131:         if (!$pkg) {
        !          80132:             $this->configSet('default_channel', $savechannel);
        !          80133:             return $this->raiseError($this->_registry->parsedPackageNameToString(
        !          80134:                 array(
        !          80135:                     'channel' => $channel,
        !          80136:                     'package' => $package
        !          80137:                 ), true) . ' not installed');
        !          80138:         }
        !          80139: 
        !          80140:         if ($pkg->getInstalledBinary()) {
        !          80141:             // this is just an alias for a binary package
        !          80142:             return $this->_registry->deletePackage($package, $channel);
        !          80143:         }
        !          80144: 
        !          80145:         $filelist = $pkg->getFilelist();
        !          80146:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          80147:         if (!class_exists('PEAR_Dependency2')) {
        !          80148:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Dependency2.php';
        !          80149:         }
        !          80150: 
        !          80151:         $depchecker = &new PEAR_Dependency2($this->config, $options,
        !          80152:             array('channel' => $channel, 'package' => $package),
        !          80153:             PEAR_VALIDATE_UNINSTALLING);
        !          80154:         $e = $depchecker->validatePackageUninstall($this);
        !          80155:         PEAR::staticPopErrorHandling();
        !          80156:         if (PEAR::isError($e)) {
        !          80157:             if (!isset($options['ignore-errors'])) {
        !          80158:                 return $this->raiseError($e);
        !          80159:             }
        !          80160: 
        !          80161:             if (!isset($options['soft'])) {
        !          80162:                 $this->log(0, 'WARNING: ' . $e->getMessage());
        !          80163:             }
        !          80164:         } elseif (is_array($e)) {
        !          80165:             if (!isset($options['soft'])) {
        !          80166:                 $this->log(0, $e[0]);
        !          80167:             }
        !          80168:         }
        !          80169: 
        !          80170:         $this->pkginfo = &$pkg;
        !          80171:         // pretty much nothing happens if we are only registering the uninstall
        !          80172:         if (empty($options['register-only'])) {
        !          80173:             // {{{ Delete the files
        !          80174:             $this->startFileTransaction();
        !          80175:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          80176:             if (PEAR::isError($err = $this->_deletePackageFiles($package, $channel))) {
        !          80177:                 PEAR::popErrorHandling();
        !          80178:                 $this->rollbackFileTransaction();
        !          80179:                 $this->configSet('default_channel', $savechannel);
        !          80180:                 if (!isset($options['ignore-errors'])) {
        !          80181:                     return $this->raiseError($err);
        !          80182:                 }
        !          80183: 
        !          80184:                 if (!isset($options['soft'])) {
        !          80185:                     $this->log(0, 'WARNING: ' . $err->getMessage());
        !          80186:                 }
1.1       misho    80187:             } else {
1.1.1.2 ! misho    80188:                 PEAR::popErrorHandling();
1.1       misho    80189:             }
1.1.1.2 ! misho    80190: 
        !          80191:             if (!$this->commitFileTransaction()) {
        !          80192:                 $this->rollbackFileTransaction();
        !          80193:                 if (!isset($options['ignore-errors'])) {
        !          80194:                     return $this->raiseError("uninstall failed");
        !          80195:                 }
        !          80196: 
        !          80197:                 if (!isset($options['soft'])) {
        !          80198:                     $this->log(0, 'WARNING: uninstall failed');
        !          80199:                 }
        !          80200:             } else {
        !          80201:                 $this->startFileTransaction();
        !          80202:                 $dirtree = $pkg->getDirTree();
        !          80203:                 if ($dirtree === false) {
        !          80204:                     $this->configSet('default_channel', $savechannel);
        !          80205:                     return $this->_registry->deletePackage($package, $channel);
        !          80206:                 }
        !          80207: 
        !          80208:                 // attempt to delete empty directories
        !          80209:                 uksort($dirtree, array($this, '_sortDirs'));
        !          80210:                 foreach($dirtree as $dir => $notused) {
        !          80211:                     $this->addFileOperation('rmdir', array($dir));
        !          80212:                 }
        !          80213: 
        !          80214:                 if (!$this->commitFileTransaction()) {
        !          80215:                     $this->rollbackFileTransaction();
        !          80216:                     if (!isset($options['ignore-errors'])) {
        !          80217:                         return $this->raiseError("uninstall failed");
        !          80218:                     }
        !          80219: 
        !          80220:                     if (!isset($options['soft'])) {
        !          80221:                         $this->log(0, 'WARNING: uninstall failed');
        !          80222:                     }
        !          80223:                 }
        !          80224:             }
        !          80225:             // }}}
1.1       misho    80226:         }
1.1.1.2 ! misho    80227: 
        !          80228:         $this->configSet('default_channel', $savechannel);
        !          80229:         // Register that the package is no longer installed
        !          80230:         return $this->_registry->deletePackage($package, $channel);
1.1       misho    80231:     }
                   80232: 
                   80233:     /**
1.1.1.2 ! misho    80234:      * Sort a list of arrays of array(downloaded packagefilename) by dependency.
        !          80235:      *
        !          80236:      * It also removes duplicate dependencies
        !          80237:      * @param array an array of PEAR_PackageFile_v[1/2] objects
        !          80238:      * @return array|PEAR_Error array of array(packagefilename, package.xml contents)
1.1       misho    80239:      */
1.1.1.2 ! misho    80240:     function sortPackagesForUninstall(&$packages)
1.1       misho    80241:     {
1.1.1.2 ! misho    80242:         $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->config);
        !          80243:         if (PEAR::isError($this->_dependencyDB)) {
        !          80244:             return $this->_dependencyDB;
        !          80245:         }
        !          80246:         usort($packages, array(&$this, '_sortUninstall'));
        !          80247:     }
        !          80248: 
        !          80249:     function _sortUninstall($a, $b)
        !          80250:     {
        !          80251:         if (!$a->getDeps() && !$b->getDeps()) {
        !          80252:             return 0; // neither package has dependencies, order is insignificant
        !          80253:         }
        !          80254:         if ($a->getDeps() && !$b->getDeps()) {
        !          80255:             return -1; // $a must be installed after $b because $a has dependencies
        !          80256:         }
        !          80257:         if (!$a->getDeps() && $b->getDeps()) {
        !          80258:             return 1; // $b must be installed after $a because $b has dependencies
        !          80259:         }
        !          80260:         // both packages have dependencies
        !          80261:         if ($this->_dependencyDB->dependsOn($a, $b)) {
        !          80262:             return -1;
        !          80263:         }
        !          80264:         if ($this->_dependencyDB->dependsOn($b, $a)) {
        !          80265:             return 1;
        !          80266:         }
        !          80267:         return 0;
        !          80268:     }
        !          80269: 
        !          80270:     // }}}
        !          80271:     // {{{ _sortDirs()
        !          80272:     function _sortDirs($a, $b)
        !          80273:     {
        !          80274:         if (strnatcmp($a, $b) == -1) return 1;
        !          80275:         if (strnatcmp($a, $b) == 1) return -1;
        !          80276:         return 0;
        !          80277:     }
        !          80278: 
        !          80279:     // }}}
        !          80280: 
        !          80281:     // {{{ _buildCallback()
        !          80282: 
        !          80283:     function _buildCallback($what, $data)
        !          80284:     {
        !          80285:         if (($what == 'cmdoutput' && $this->debug > 1) ||
        !          80286:             ($what == 'output' && $this->debug > 0)) {
        !          80287:             $this->ui->outputData(rtrim($data), 'build');
1.1       misho    80288:         }
                   80289:     }
                   80290: 
1.1.1.2 ! misho    80291:     // }}}
        !          80292: }<?php
        !          80293: /**
        !          80294:  * PEAR_Installer_Role
        !          80295:  *
        !          80296:  * PHP versions 4 and 5
        !          80297:  *
        !          80298:  * @category   pear
        !          80299:  * @package    PEAR
        !          80300:  * @author     Greg Beaver <cellog@php.net>
        !          80301:  * @copyright  1997-2009 The Authors
        !          80302:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          80303:  * @version    CVS: $Id: Role.php 313023 2011-07-06 19:17:11Z dufuz $
        !          80304:  * @link       http://pear.php.net/package/PEAR
        !          80305:  * @since      File available since Release 1.4.0a1
        !          80306:  */
        !          80307: 
        !          80308: /**
        !          80309:  * base class for installer roles
        !          80310:  */
        !          80311: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Installer/Role/Common.php';
        !          80312: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/XMLParser.php';
        !          80313: /**
        !          80314:  * @category   pear
        !          80315:  * @package    PEAR
        !          80316:  * @author     Greg Beaver <cellog@php.net>
        !          80317:  * @copyright  1997-2009 The Authors
        !          80318:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          80319:  * @version    Release: 1.9.4
        !          80320:  * @link       http://pear.php.net/package/PEAR
        !          80321:  * @since      Class available since Release 1.4.0a1
        !          80322:  */
        !          80323: class PEAR_Installer_Role
        !          80324: {
1.1       misho    80325:     /**
1.1.1.2 ! misho    80326:      * Set up any additional configuration variables that file roles require
1.1       misho    80327:      *
1.1.1.2 ! misho    80328:      * Never call this directly, it is called by the PEAR_Config constructor
        !          80329:      * @param PEAR_Config
        !          80330:      * @access private
        !          80331:      * @static
1.1       misho    80332:      */
1.1.1.2 ! misho    80333:     function initializeConfig(&$config)
1.1       misho    80334:     {
1.1.1.2 ! misho    80335:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
        !          80336:             PEAR_Installer_Role::registerRoles();
        !          80337:         }
        !          80338: 
        !          80339:         foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $class => $info) {
        !          80340:             if (!$info['config_vars']) {
        !          80341:                 continue;
1.1       misho    80342:             }
1.1.1.2 ! misho    80343: 
        !          80344:             $config->_addConfigVars($class, $info['config_vars']);
1.1       misho    80345:         }
                   80346:     }
                   80347: 
                   80348:     /**
1.1.1.2 ! misho    80349:      * @param PEAR_PackageFile_v2
        !          80350:      * @param string role name
        !          80351:      * @param PEAR_Config
        !          80352:      * @return PEAR_Installer_Role_Common
        !          80353:      * @static
1.1       misho    80354:      */
1.1.1.2 ! misho    80355:     function &factory($pkg, $role, &$config)
1.1       misho    80356:     {
1.1.1.2 ! misho    80357:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
        !          80358:             PEAR_Installer_Role::registerRoles();
1.1       misho    80359:         }
1.1.1.2 ! misho    80360: 
        !          80361:         if (!in_array($role, PEAR_Installer_Role::getValidRoles($pkg->getPackageType()))) {
        !          80362:             $a = false;
        !          80363:             return $a;
        !          80364:         }
        !          80365: 
        !          80366:         $a = 'PEAR_Installer_Role_' . ucfirst($role);
        !          80367:         if (!class_exists($a)) {
        !          80368:             require_once 'phar://install-pear-nozlib.phar/' . str_replace('_', '/', $a) . '.php';
        !          80369:         }
        !          80370: 
        !          80371:         $b = new $a($config);
        !          80372:         return $b;
1.1       misho    80373:     }
1.1.1.2 ! misho    80374: 
1.1       misho    80375:     /**
1.1.1.2 ! misho    80376:      * Get a list of file roles that are valid for the particular release type.
        !          80377:      *
        !          80378:      * For instance, src files serve no purpose in regular php releases.
        !          80379:      * @param string
        !          80380:      * @param bool clear cache
1.1       misho    80381:      * @return array
1.1.1.2 ! misho    80382:      * @static
1.1       misho    80383:      */
1.1.1.2 ! misho    80384:     function getValidRoles($release, $clear = false)
1.1       misho    80385:     {
1.1.1.2 ! misho    80386:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
        !          80387:             PEAR_Installer_Role::registerRoles();
1.1       misho    80388:         }
1.1.1.2 ! misho    80389: 
        !          80390:         static $ret = array();
        !          80391:         if ($clear) {
        !          80392:             $ret = array();
        !          80393:         }
        !          80394: 
        !          80395:         if (isset($ret[$release])) {
        !          80396:             return $ret[$release];
        !          80397:         }
        !          80398: 
        !          80399:         $ret[$release] = array();
        !          80400:         foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
        !          80401:             if (in_array($release, $okreleases['releasetypes'])) {
        !          80402:                 $ret[$release][] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
1.1       misho    80403:             }
                   80404:         }
1.1.1.2 ! misho    80405: 
        !          80406:         return $ret[$release];
1.1       misho    80407:     }
1.1.1.2 ! misho    80408: 
1.1       misho    80409:     /**
1.1.1.2 ! misho    80410:      * Get a list of roles that require their files to be installed
1.1       misho    80411:      *
1.1.1.2 ! misho    80412:      * Most roles must be installed, but src and package roles, for instance
        !          80413:      * are pseudo-roles.  src files are compiled into a new extension.  Package
        !          80414:      * roles are actually fully bundled releases of a package
        !          80415:      * @param bool clear cache
        !          80416:      * @return array
1.1       misho    80417:      * @static
                   80418:      */
1.1.1.2 ! misho    80419:     function getInstallableRoles($clear = false)
1.1       misho    80420:     {
1.1.1.2 ! misho    80421:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
        !          80422:             PEAR_Installer_Role::registerRoles();
1.1       misho    80423:         }
1.1.1.2 ! misho    80424: 
        !          80425:         static $ret;
        !          80426:         if ($clear) {
        !          80427:             unset($ret);
        !          80428:         }
        !          80429: 
        !          80430:         if (isset($ret)) {
        !          80431:             return $ret;
        !          80432:         }
        !          80433: 
        !          80434:         $ret = array();
        !          80435:         foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
        !          80436:             if ($okreleases['installable']) {
        !          80437:                 $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
1.1       misho    80438:             }
                   80439:         }
1.1.1.2 ! misho    80440: 
        !          80441:         return $ret;
1.1       misho    80442:     }
1.1.1.2 ! misho    80443: 
1.1       misho    80444:     /**
1.1.1.2 ! misho    80445:      * Return an array of roles that are affected by the baseinstalldir attribute
        !          80446:      *
        !          80447:      * Most roles ignore this attribute, and instead install directly into:
        !          80448:      * PackageName/filepath
        !          80449:      * so a tests file tests/file.phpt is installed into PackageName/tests/filepath.php
        !          80450:      * @param bool clear cache
        !          80451:      * @return array
1.1       misho    80452:      * @static
                   80453:      */
1.1.1.2 ! misho    80454:     function getBaseinstallRoles($clear = false)
1.1       misho    80455:     {
1.1.1.2 ! misho    80456:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
        !          80457:             PEAR_Installer_Role::registerRoles();
1.1       misho    80458:         }
1.1.1.2 ! misho    80459: 
        !          80460:         static $ret;
        !          80461:         if ($clear) {
        !          80462:             unset($ret);
1.1       misho    80463:         }
1.1.1.2 ! misho    80464: 
        !          80465:         if (isset($ret)) {
        !          80466:             return $ret;
        !          80467:         }
        !          80468: 
        !          80469:         $ret = array();
        !          80470:         foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
        !          80471:             if ($okreleases['honorsbaseinstall']) {
        !          80472:                 $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
        !          80473:             }
1.1       misho    80474:         }
1.1.1.2 ! misho    80475: 
1.1       misho    80476:         return $ret;
                   80477:     }
1.1.1.2 ! misho    80478: 
1.1       misho    80479:     /**
1.1.1.2 ! misho    80480:      * Return an array of file roles that should be analyzed for PHP content at package time,
        !          80481:      * like the "php" role.
        !          80482:      * @param bool clear cache
        !          80483:      * @return array
        !          80484:      * @static
1.1       misho    80485:      */
1.1.1.2 ! misho    80486:     function getPhpRoles($clear = false)
1.1       misho    80487:     {
1.1.1.2 ! misho    80488:         if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
        !          80489:             PEAR_Installer_Role::registerRoles();
1.1       misho    80490:         }
1.1.1.2 ! misho    80491: 
        !          80492:         static $ret;
        !          80493:         if ($clear) {
        !          80494:             unset($ret);
1.1       misho    80495:         }
1.1.1.2 ! misho    80496: 
        !          80497:         if (isset($ret)) {
        !          80498:             return $ret;
        !          80499:         }
        !          80500: 
        !          80501:         $ret = array();
        !          80502:         foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
        !          80503:             if ($okreleases['phpfile']) {
        !          80504:                 $ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
        !          80505:             }
        !          80506:         }
        !          80507: 
        !          80508:         return $ret;
1.1       misho    80509:     }
                   80510: 
                   80511:     /**
1.1.1.2 ! misho    80512:      * Scan through the Command directory looking for classes
        !          80513:      * and see what commands they implement.
        !          80514:      * @param string which directory to look for classes, defaults to
        !          80515:      *               the Installer/Roles subdirectory of
        !          80516:      *               the directory from where this file (__FILE__) is
        !          80517:      *               included.
1.1       misho    80518:      *
1.1.1.2 ! misho    80519:      * @return bool TRUE on success, a PEAR error on failure
        !          80520:      * @access public
1.1       misho    80521:      * @static
                   80522:      */
1.1.1.2 ! misho    80523:     function registerRoles($dir = null)
1.1       misho    80524:     {
1.1.1.2 ! misho    80525:         $GLOBALS['_PEAR_INSTALLER_ROLES'] = array();
        !          80526:         $parser = new PEAR_XMLParser;
        !          80527:         if ($dir === null) {
        !          80528:             $dir = dirname(__FILE__) . '/Role';
1.1       misho    80529:         }
1.1.1.2 ! misho    80530: 
        !          80531:         if (!file_exists($dir) || !is_dir($dir)) {
        !          80532:             return PEAR::raiseError("registerRoles: opendir($dir) failed: does not exist/is not directory");
1.1       misho    80533:         }
1.1.1.2 ! misho    80534: 
        !          80535:         $dp = @opendir($dir);
        !          80536:         if (empty($dp)) {
        !          80537:             return PEAR::raiseError("registerRoles: opendir($dir) failed: $php_errmsg");
        !          80538:         }
        !          80539: 
        !          80540:         while ($entry = readdir($dp)) {
        !          80541:             if ($entry{0} == '.' || substr($entry, -4) != '.xml') {
        !          80542:                 continue;
1.1       misho    80543:             }
1.1.1.2 ! misho    80544: 
        !          80545:             $class = "PEAR_Installer_Role_".substr($entry, 0, -4);
        !          80546:             // List of roles
        !          80547:             if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'][$class])) {
        !          80548:                 $file = "$dir/$entry";
        !          80549:                 $parser->parse(file_get_contents($file));
        !          80550:                 $data = $parser->getData();
        !          80551:                 if (!is_array($data['releasetypes'])) {
        !          80552:                     $data['releasetypes'] = array($data['releasetypes']);
1.1       misho    80553:                 }
1.1.1.2 ! misho    80554: 
        !          80555:                 $GLOBALS['_PEAR_INSTALLER_ROLES'][$class] = $data;
1.1       misho    80556:             }
                   80557:         }
1.1.1.2 ! misho    80558: 
        !          80559:         closedir($dp);
        !          80560:         ksort($GLOBALS['_PEAR_INSTALLER_ROLES']);
        !          80561:         PEAR_Installer_Role::getBaseinstallRoles(true);
        !          80562:         PEAR_Installer_Role::getInstallableRoles(true);
        !          80563:         PEAR_Installer_Role::getPhpRoles(true);
        !          80564:         PEAR_Installer_Role::getValidRoles('****', true);
        !          80565:         return true;
1.1       misho    80566:     }
1.1.1.2 ! misho    80567: }<?php
        !          80568: /**
        !          80569:  * PEAR_Installer_Role_Cfg
        !          80570:  *
        !          80571:  * PHP versions 4 and 5
        !          80572:  *
        !          80573:  * @category   pear
        !          80574:  * @package    PEAR
        !          80575:  * @author     Greg Beaver <cellog@php.net>
        !          80576:  * @copyright  2007-2009 The Authors
        !          80577:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          80578:  * @version    CVS: $Id: Cfg.php 313023 2011-07-06 19:17:11Z dufuz $
        !          80579:  * @link       http://pear.php.net/package/PEAR
        !          80580:  * @since      File available since Release 1.7.0
        !          80581:  */
        !          80582: 
        !          80583: /**
        !          80584:  * @category   pear
        !          80585:  * @package    PEAR
        !          80586:  * @author     Greg Beaver <cellog@php.net>
        !          80587:  * @copyright  2007-2009 The Authors
        !          80588:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          80589:  * @version    Release: 1.9.4
        !          80590:  * @link       http://pear.php.net/package/PEAR
        !          80591:  * @since      Class available since Release 1.7.0
        !          80592:  */
        !          80593: class PEAR_Installer_Role_Cfg extends PEAR_Installer_Role_Common
        !          80594: {
1.1       misho    80595:     /**
1.1.1.2 ! misho    80596:      * @var PEAR_Installer
1.1       misho    80597:      */
1.1.1.2 ! misho    80598:     var $installer;
        !          80599: 
1.1       misho    80600:     /**
1.1.1.2 ! misho    80601:      * the md5 of the original file
        !          80602:      *
        !          80603:      * @var unknown_type
1.1       misho    80604:      */
1.1.1.2 ! misho    80605:     var $md5 = null;
        !          80606: 
1.1       misho    80607:     /**
1.1.1.2 ! misho    80608:      * Do any unusual setup here
        !          80609:      * @param PEAR_Installer
        !          80610:      * @param PEAR_PackageFile_v2
        !          80611:      * @param array file attributes
        !          80612:      * @param string file name
1.1       misho    80613:      */
1.1.1.2 ! misho    80614:     function setup(&$installer, $pkg, $atts, $file)
1.1       misho    80615:     {
1.1.1.2 ! misho    80616:         $this->installer = &$installer;
        !          80617:         $reg = &$this->installer->config->getRegistry();
        !          80618:         $package = $reg->getPackage($pkg->getPackage(), $pkg->getChannel());
        !          80619:         if ($package) {
        !          80620:             $filelist = $package->getFilelist();
        !          80621:             if (isset($filelist[$file]) && isset($filelist[$file]['md5sum'])) {
        !          80622:                 $this->md5 = $filelist[$file]['md5sum'];
        !          80623:             }
        !          80624:         }
1.1       misho    80625:     }
1.1.1.2 ! misho    80626: 
        !          80627:     function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null)
1.1       misho    80628:     {
1.1.1.2 ! misho    80629:         $test = parent::processInstallation($pkg, $atts, $file, $tmp_path, $layer);
        !          80630:         if (@file_exists($test[2]) && @file_exists($test[3])) {
        !          80631:             $md5 = md5_file($test[2]);
        !          80632:             // configuration has already been installed, check for mods
        !          80633:             if ($md5 !== $this->md5 && $md5 !== md5_file($test[3])) {
        !          80634:                 // configuration has been modified, so save our version as
        !          80635:                 // configfile-version
        !          80636:                 $old = $test[2];
        !          80637:                 $test[2] .= '.new-' . $pkg->getVersion();
        !          80638:                 // backup original and re-install it
        !          80639:                 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          80640:                 $tmpcfg = $this->config->get('temp_dir');
        !          80641:                 $newloc = System::mkdir(array('-p', $tmpcfg));
        !          80642:                 if (!$newloc) {
        !          80643:                     // try temp_dir
        !          80644:                     $newloc = System::mktemp(array('-d'));
        !          80645:                     if (!$newloc || PEAR::isError($newloc)) {
        !          80646:                         PEAR::popErrorHandling();
        !          80647:                         return PEAR::raiseError('Could not save existing configuration file '.
        !          80648:                             $old . ', unable to install.  Please set temp_dir ' .
        !          80649:                             'configuration variable to a writeable location and try again');
        !          80650:                     }
        !          80651:                 } else {
        !          80652:                     $newloc = $tmpcfg;
        !          80653:                 }
        !          80654: 
        !          80655:                 $temp_file = $newloc . DIRECTORY_SEPARATOR . uniqid('savefile');
        !          80656:                 if (!@copy($old, $temp_file)) {
        !          80657:                     PEAR::popErrorHandling();
        !          80658:                     return PEAR::raiseError('Could not save existing configuration file '.
        !          80659:                         $old . ', unable to install.  Please set temp_dir ' .
        !          80660:                         'configuration variable to a writeable location and try again');
        !          80661:                 }
        !          80662: 
        !          80663:                 PEAR::popErrorHandling();
        !          80664:                 $this->installer->log(0, "WARNING: configuration file $old is being installed as $test[2], you should manually merge in changes to the existing configuration file");
        !          80665:                 $this->installer->addFileOperation('rename', array($temp_file, $old, false));
        !          80666:                 $this->installer->addFileOperation('delete', array($temp_file));
        !          80667:             }
        !          80668:         }
        !          80669: 
        !          80670:         return $test;
1.1       misho    80671:     }
1.1.1.2 ! misho    80672: }<role version="1.0">
        !          80673:  <releasetypes>php</releasetypes>
        !          80674:  <releasetypes>extsrc</releasetypes>
        !          80675:  <releasetypes>extbin</releasetypes>
        !          80676:  <releasetypes>zendextsrc</releasetypes>
        !          80677:  <releasetypes>zendextbin</releasetypes>
        !          80678:  <installable>1</installable>
        !          80679:  <locationconfig>cfg_dir</locationconfig>
        !          80680:  <honorsbaseinstall />
        !          80681:  <unusualbaseinstall>1</unusualbaseinstall>
        !          80682:  <phpfile />
        !          80683:  <executable />
        !          80684:  <phpextension />
        !          80685:  <config_vars />
        !          80686: </role><?php
1.1       misho    80687: /**
1.1.1.2 ! misho    80688:  * Base class for all installation roles.
1.1       misho    80689:  *
                   80690:  * PHP versions 4 and 5
                   80691:  *
                   80692:  * @category   pear
1.1.1.2 ! misho    80693:  * @package    PEAR
1.1       misho    80694:  * @author     Greg Beaver <cellog@php.net>
1.1.1.2 ! misho    80695:  * @copyright  1997-2006 The PHP Group
1.1       misho    80696:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    80697:  * @version    CVS: $Id: Common.php 313023 2011-07-06 19:17:11Z dufuz $
        !          80698:  * @link       http://pear.php.net/package/PEAR
        !          80699:  * @since      File available since Release 1.4.0a1
1.1       misho    80700:  */
                   80701: /**
1.1.1.2 ! misho    80702:  * Base class for all installation roles.
1.1       misho    80703:  *
1.1.1.2 ! misho    80704:  * This class allows extensibility of file roles.  Packages with complex
        !          80705:  * customization can now provide custom file roles along with the possibility of
        !          80706:  * adding configuration values to match.
1.1       misho    80707:  * @category   pear
1.1.1.2 ! misho    80708:  * @package    PEAR
1.1       misho    80709:  * @author     Greg Beaver <cellog@php.net>
1.1.1.2 ! misho    80710:  * @copyright  1997-2006 The PHP Group
1.1       misho    80711:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    80712:  * @version    Release: 1.9.4
        !          80713:  * @link       http://pear.php.net/package/PEAR
        !          80714:  * @since      Class available since Release 1.4.0a1
1.1       misho    80715:  */
1.1.1.2 ! misho    80716: class PEAR_Installer_Role_Common
1.1       misho    80717: {
                   80718:     /**
1.1.1.2 ! misho    80719:      * @var PEAR_Config
        !          80720:      * @access protected
1.1       misho    80721:      */
1.1.1.2 ! misho    80722:     var $config;
1.1       misho    80723: 
                   80724:     /**
1.1.1.2 ! misho    80725:      * @param PEAR_Config
1.1       misho    80726:      */
1.1.1.2 ! misho    80727:     function PEAR_Installer_Role_Common(&$config)
1.1       misho    80728:     {
1.1.1.2 ! misho    80729:         $this->config = $config;
1.1       misho    80730:     }
                   80731: 
                   80732:     /**
1.1.1.2 ! misho    80733:      * Retrieve configuration information about a file role from its XML info
        !          80734:      *
        !          80735:      * @param string $role Role Classname, as in "PEAR_Installer_Role_Data"
        !          80736:      * @return array
1.1       misho    80737:      */
1.1.1.2 ! misho    80738:     function getInfo($role)
1.1       misho    80739:     {
1.1.1.2 ! misho    80740:         if (empty($GLOBALS['_PEAR_INSTALLER_ROLES'][$role])) {
        !          80741:             return PEAR::raiseError('Unknown Role class: "' . $role . '"');
1.1       misho    80742:         }
1.1.1.2 ! misho    80743:         return $GLOBALS['_PEAR_INSTALLER_ROLES'][$role];
1.1       misho    80744:     }
                   80745: 
                   80746:     /**
1.1.1.2 ! misho    80747:      * This is called for each file to set up the directories and files
        !          80748:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
        !          80749:      * @param array attributes from the <file> tag
        !          80750:      * @param string file name
        !          80751:      * @return array an array consisting of:
1.1       misho    80752:      *
1.1.1.2 ! misho    80753:      *    1 the original, pre-baseinstalldir installation directory
        !          80754:      *    2 the final installation directory
        !          80755:      *    3 the full path to the final location of the file
        !          80756:      *    4 the location of the pre-installation file
1.1       misho    80757:      */
1.1.1.2 ! misho    80758:     function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null)
1.1       misho    80759:     {
1.1.1.2 ! misho    80760:         $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . 
        !          80761:             ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
        !          80762:         if (PEAR::isError($roleInfo)) {
        !          80763:             return $roleInfo;
        !          80764:         }
        !          80765:         if (!$roleInfo['locationconfig']) {
        !          80766:             return false;
        !          80767:         }
        !          80768:         if ($roleInfo['honorsbaseinstall']) {
        !          80769:             $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'], $layer,
        !          80770:                 $pkg->getChannel());
        !          80771:             if (!empty($atts['baseinstalldir'])) {
        !          80772:                 $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
        !          80773:             }
        !          80774:         } elseif ($roleInfo['unusualbaseinstall']) {
        !          80775:             $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'],
        !          80776:                     $layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage();
        !          80777:             if (!empty($atts['baseinstalldir'])) {
        !          80778:                 $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
        !          80779:             }
        !          80780:         } else {
        !          80781:             $dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'],
        !          80782:                     $layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage();
        !          80783:         }
        !          80784:         if (dirname($file) != '.' && empty($atts['install-as'])) {
        !          80785:             $dest_dir .= DIRECTORY_SEPARATOR . dirname($file);
        !          80786:         }
        !          80787:         if (empty($atts['install-as'])) {
        !          80788:             $dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file);
        !          80789:         } else {
        !          80790:             $dest_file = $dest_dir . DIRECTORY_SEPARATOR . $atts['install-as'];
        !          80791:         }
        !          80792:         $orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file;
        !          80793: 
        !          80794:         // Clean up the DIRECTORY_SEPARATOR mess
        !          80795:         $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
        !          80796:         
        !          80797:         list($dest_dir, $dest_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"),
        !          80798:                                                     array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR,
        !          80799:                                                           DIRECTORY_SEPARATOR),
        !          80800:                                                     array($dest_dir, $dest_file, $orig_file));
        !          80801:         return array($save_destdir, $dest_dir, $dest_file, $orig_file);
1.1       misho    80802:     }
                   80803: 
                   80804:     /**
1.1.1.2 ! misho    80805:      * Get the name of the configuration variable that specifies the location of this file
        !          80806:      * @return string|false
1.1       misho    80807:      */
1.1.1.2 ! misho    80808:     function getLocationConfig()
1.1       misho    80809:     {
1.1.1.2 ! misho    80810:         $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . 
        !          80811:             ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
        !          80812:         if (PEAR::isError($roleInfo)) {
        !          80813:             return $roleInfo;
        !          80814:         }
        !          80815:         return $roleInfo['locationconfig'];
1.1       misho    80816:     }
                   80817: 
                   80818:     /**
1.1.1.2 ! misho    80819:      * Do any unusual setup here
        !          80820:      * @param PEAR_Installer
        !          80821:      * @param PEAR_PackageFile_v2
        !          80822:      * @param array file attributes
        !          80823:      * @param string file name
1.1       misho    80824:      */
1.1.1.2 ! misho    80825:     function setup(&$installer, $pkg, $atts, $file)
1.1       misho    80826:     {
                   80827:     }
                   80828: 
1.1.1.2 ! misho    80829:     function isExecutable()
1.1       misho    80830:     {
1.1.1.2 ! misho    80831:         $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . 
        !          80832:             ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
        !          80833:         if (PEAR::isError($roleInfo)) {
        !          80834:             return $roleInfo;
1.1       misho    80835:         }
1.1.1.2 ! misho    80836:         return $roleInfo['executable'];
1.1       misho    80837:     }
                   80838: 
1.1.1.2 ! misho    80839:     function isInstallable()
1.1       misho    80840:     {
1.1.1.2 ! misho    80841:         $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . 
        !          80842:             ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
        !          80843:         if (PEAR::isError($roleInfo)) {
        !          80844:             return $roleInfo;
1.1       misho    80845:         }
1.1.1.2 ! misho    80846:         return $roleInfo['installable'];
1.1       misho    80847:     }
                   80848: 
1.1.1.2 ! misho    80849:     function isExtension()
1.1       misho    80850:     {
1.1.1.2 ! misho    80851:         $roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' . 
        !          80852:             ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
        !          80853:         if (PEAR::isError($roleInfo)) {
        !          80854:             return $roleInfo;
1.1       misho    80855:         }
1.1.1.2 ! misho    80856:         return $roleInfo['phpextension'];
1.1       misho    80857:     }
1.1.1.2 ! misho    80858: }
        !          80859: ?><?php
        !          80860: /**
        !          80861:  * PEAR_Installer_Role_Data
        !          80862:  *
        !          80863:  * PHP versions 4 and 5
        !          80864:  *
        !          80865:  * @category   pear
        !          80866:  * @package    PEAR
        !          80867:  * @author     Greg Beaver <cellog@php.net>
        !          80868:  * @copyright  1997-2009 The Authors
        !          80869:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          80870:  * @version    CVS: $Id: Data.php 313023 2011-07-06 19:17:11Z dufuz $
        !          80871:  * @link       http://pear.php.net/package/PEAR
        !          80872:  * @since      File available since Release 1.4.0a1
        !          80873:  */
        !          80874: 
        !          80875: /**
        !          80876:  * @category   pear
        !          80877:  * @package    PEAR
        !          80878:  * @author     Greg Beaver <cellog@php.net>
        !          80879:  * @copyright  1997-2009 The Authors
        !          80880:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          80881:  * @version    Release: 1.9.4
        !          80882:  * @link       http://pear.php.net/package/PEAR
        !          80883:  * @since      Class available since Release 1.4.0a1
        !          80884:  */
        !          80885: class PEAR_Installer_Role_Data extends PEAR_Installer_Role_Common {}
        !          80886: ?><role version="1.0">
        !          80887:  <releasetypes>php</releasetypes>
        !          80888:  <releasetypes>extsrc</releasetypes>
        !          80889:  <releasetypes>extbin</releasetypes>
        !          80890:  <releasetypes>zendextsrc</releasetypes>
        !          80891:  <releasetypes>zendextbin</releasetypes>
        !          80892:  <installable>1</installable>
        !          80893:  <locationconfig>data_dir</locationconfig>
        !          80894:  <honorsbaseinstall />
        !          80895:  <unusualbaseinstall />
        !          80896:  <phpfile />
        !          80897:  <executable />
        !          80898:  <phpextension />
        !          80899:  <config_vars />
        !          80900: </role><?php
        !          80901: /**
        !          80902:  * PEAR_Installer_Role_Doc
        !          80903:  *
        !          80904:  * PHP versions 4 and 5
        !          80905:  *
        !          80906:  * @category   pear
        !          80907:  * @package    PEAR
        !          80908:  * @author     Greg Beaver <cellog@php.net>
        !          80909:  * @copyright  1997-2009 The Authors
        !          80910:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          80911:  * @version    CVS: $Id: Doc.php 313023 2011-07-06 19:17:11Z dufuz $
        !          80912:  * @link       http://pear.php.net/package/PEAR
        !          80913:  * @since      File available since Release 1.4.0a1
        !          80914:  */
1.1       misho    80915: 
                   80916: /**
1.1.1.2 ! misho    80917:  * @category   pear
        !          80918:  * @package    PEAR
        !          80919:  * @author     Greg Beaver <cellog@php.net>
        !          80920:  * @copyright  1997-2009 The Authors
        !          80921:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          80922:  * @version    Release: 1.9.4
        !          80923:  * @link       http://pear.php.net/package/PEAR
        !          80924:  * @since      Class available since Release 1.4.0a1
        !          80925:  */
        !          80926: class PEAR_Installer_Role_Doc extends PEAR_Installer_Role_Common {}
        !          80927: ?><role version="1.0">
        !          80928:  <releasetypes>php</releasetypes>
        !          80929:  <releasetypes>extsrc</releasetypes>
        !          80930:  <releasetypes>extbin</releasetypes>
        !          80931:  <releasetypes>zendextsrc</releasetypes>
        !          80932:  <releasetypes>zendextbin</releasetypes>
        !          80933:  <installable>1</installable>
        !          80934:  <locationconfig>doc_dir</locationconfig>
        !          80935:  <honorsbaseinstall />
        !          80936:  <unusualbaseinstall />
        !          80937:  <phpfile />
        !          80938:  <executable />
        !          80939:  <phpextension />
        !          80940:  <config_vars />
        !          80941: </role><?php
        !          80942: /**
        !          80943:  * PEAR_Installer_Role_Ext
1.1       misho    80944:  *
                   80945:  * PHP versions 4 and 5
                   80946:  *
                   80947:  * @category   pear
                   80948:  * @package    PEAR
                   80949:  * @author     Greg Beaver <cellog@php.net>
                   80950:  * @copyright  1997-2009 The Authors
                   80951:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    80952:  * @version    CVS: $Id: Ext.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    80953:  * @link       http://pear.php.net/package/PEAR
                   80954:  * @since      File available since Release 1.4.0a1
                   80955:  */
                   80956: 
                   80957: /**
1.1.1.2 ! misho    80958:  * @category   pear
        !          80959:  * @package    PEAR
        !          80960:  * @author     Greg Beaver <cellog@php.net>
        !          80961:  * @copyright  1997-2009 The Authors
        !          80962:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          80963:  * @version    Release: 1.9.4
        !          80964:  * @link       http://pear.php.net/package/PEAR
        !          80965:  * @since      Class available since Release 1.4.0a1
1.1       misho    80966:  */
1.1.1.2 ! misho    80967: class PEAR_Installer_Role_Ext extends PEAR_Installer_Role_Common {}
        !          80968: ?><role version="1.0">
        !          80969:  <releasetypes>extbin</releasetypes>
        !          80970:  <releasetypes>zendextbin</releasetypes>
        !          80971:  <installable>1</installable>
        !          80972:  <locationconfig>ext_dir</locationconfig>
        !          80973:  <honorsbaseinstall>1</honorsbaseinstall>
        !          80974:  <unusualbaseinstall />
        !          80975:  <phpfile />
        !          80976:  <executable />
        !          80977:  <phpextension>1</phpextension>
        !          80978:  <config_vars />
        !          80979: </role><?php
1.1       misho    80980: /**
1.1.1.2 ! misho    80981:  * PEAR_Installer_Role_Php
        !          80982:  *
        !          80983:  * PHP versions 4 and 5
        !          80984:  *
        !          80985:  * @category   pear
        !          80986:  * @package    PEAR
        !          80987:  * @author     Greg Beaver <cellog@php.net>
        !          80988:  * @copyright  1997-2009 The Authors
        !          80989:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          80990:  * @version    CVS: $Id: Php.php 313023 2011-07-06 19:17:11Z dufuz $
        !          80991:  * @link       http://pear.php.net/package/PEAR
        !          80992:  * @since      File available since Release 1.4.0a1
1.1       misho    80993:  */
                   80994: 
                   80995: /**
1.1.1.2 ! misho    80996:  * @category   pear
        !          80997:  * @package    PEAR
        !          80998:  * @author     Greg Beaver <cellog@php.net>
        !          80999:  * @copyright  1997-2009 The Authors
        !          81000:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          81001:  * @version    Release: 1.9.4
        !          81002:  * @link       http://pear.php.net/package/PEAR
        !          81003:  * @since      Class available since Release 1.4.0a1
        !          81004:  */
        !          81005: class PEAR_Installer_Role_Php extends PEAR_Installer_Role_Common {}
        !          81006: ?><role version="1.0">
        !          81007:  <releasetypes>php</releasetypes>
        !          81008:  <releasetypes>extsrc</releasetypes>
        !          81009:  <releasetypes>extbin</releasetypes>
        !          81010:  <releasetypes>zendextsrc</releasetypes>
        !          81011:  <releasetypes>zendextbin</releasetypes>
        !          81012:  <installable>1</installable>
        !          81013:  <locationconfig>php_dir</locationconfig>
        !          81014:  <honorsbaseinstall>1</honorsbaseinstall>
        !          81015:  <unusualbaseinstall />
        !          81016:  <phpfile>1</phpfile>
        !          81017:  <executable />
        !          81018:  <phpextension />
        !          81019:  <config_vars />
        !          81020: </role><?php
        !          81021: /**
        !          81022:  * PEAR_Installer_Role_Script
        !          81023:  *
        !          81024:  * PHP versions 4 and 5
        !          81025:  *
        !          81026:  * @category   pear
        !          81027:  * @package    PEAR
        !          81028:  * @author     Greg Beaver <cellog@php.net>
        !          81029:  * @copyright  1997-2009 The Authors
        !          81030:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          81031:  * @version    CVS: $Id: Script.php 313023 2011-07-06 19:17:11Z dufuz $
        !          81032:  * @link       http://pear.php.net/package/PEAR
        !          81033:  * @since      File available since Release 1.4.0a1
1.1       misho    81034:  */
                   81035: 
                   81036: /**
1.1.1.2 ! misho    81037:  * @category   pear
        !          81038:  * @package    PEAR
        !          81039:  * @author     Greg Beaver <cellog@php.net>
        !          81040:  * @copyright  1997-2009 The Authors
        !          81041:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          81042:  * @version    Release: 1.9.4
        !          81043:  * @link       http://pear.php.net/package/PEAR
        !          81044:  * @since      Class available since Release 1.4.0a1
        !          81045:  */
        !          81046: class PEAR_Installer_Role_Script extends PEAR_Installer_Role_Common {}
        !          81047: ?><role version="1.0">
        !          81048:  <releasetypes>php</releasetypes>
        !          81049:  <releasetypes>extsrc</releasetypes>
        !          81050:  <releasetypes>extbin</releasetypes>
        !          81051:  <releasetypes>zendextsrc</releasetypes>
        !          81052:  <releasetypes>zendextbin</releasetypes>
        !          81053:  <installable>1</installable>
        !          81054:  <locationconfig>bin_dir</locationconfig>
        !          81055:  <honorsbaseinstall>1</honorsbaseinstall>
        !          81056:  <unusualbaseinstall />
        !          81057:  <phpfile />
        !          81058:  <executable>1</executable>
        !          81059:  <phpextension />
        !          81060:  <config_vars />
        !          81061: </role><?php
        !          81062: /**
        !          81063:  * PEAR_Installer_Role_Src
        !          81064:  *
        !          81065:  * PHP versions 4 and 5
1.1       misho    81066:  *
                   81067:  * @category   pear
                   81068:  * @package    PEAR
                   81069:  * @author     Greg Beaver <cellog@php.net>
                   81070:  * @copyright  1997-2009 The Authors
                   81071:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    81072:  * @version    CVS: $Id: Src.php 313023 2011-07-06 19:17:11Z dufuz $
        !          81073:  * @link       http://pear.php.net/package/PEAR
        !          81074:  * @since      File available since Release 1.4.0a1
        !          81075:  */
        !          81076: 
        !          81077: /**
        !          81078:  * @category   pear
        !          81079:  * @package    PEAR
        !          81080:  * @author     Greg Beaver <cellog@php.net>
        !          81081:  * @copyright  1997-2009 The Authors
        !          81082:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          81083:  * @version    Release: 1.9.4
1.1       misho    81084:  * @link       http://pear.php.net/package/PEAR
                   81085:  * @since      Class available since Release 1.4.0a1
                   81086:  */
1.1.1.2 ! misho    81087: class PEAR_Installer_Role_Src extends PEAR_Installer_Role_Common
1.1       misho    81088: {
1.1.1.2 ! misho    81089:     function setup(&$installer, $pkg, $atts, $file)
1.1       misho    81090:     {
1.1.1.2 ! misho    81091:         $installer->source_files++;
1.1       misho    81092:     }
1.1.1.2 ! misho    81093: }
        !          81094: ?><role version="1.0">
        !          81095:  <releasetypes>extsrc</releasetypes>
        !          81096:  <releasetypes>zendextsrc</releasetypes>
        !          81097:  <installable>1</installable>
        !          81098:  <locationconfig>temp_dir</locationconfig>
        !          81099:  <honorsbaseinstall />
        !          81100:  <unusualbaseinstall />
        !          81101:  <phpfile />
        !          81102:  <executable />
        !          81103:  <phpextension />
        !          81104:  <config_vars />
        !          81105: </role><?php
        !          81106: /**
        !          81107:  * PEAR_Installer_Role_Test
        !          81108:  *
        !          81109:  * PHP versions 4 and 5
        !          81110:  *
        !          81111:  * @category   pear
        !          81112:  * @package    PEAR
        !          81113:  * @author     Greg Beaver <cellog@php.net>
        !          81114:  * @copyright  1997-2009 The Authors
        !          81115:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          81116:  * @version    CVS: $Id: Test.php 313023 2011-07-06 19:17:11Z dufuz $
        !          81117:  * @link       http://pear.php.net/package/PEAR
        !          81118:  * @since      File available since Release 1.4.0a1
        !          81119:  */
1.1       misho    81120: 
1.1.1.2 ! misho    81121: /**
        !          81122:  * @category   pear
        !          81123:  * @package    PEAR
        !          81124:  * @author     Greg Beaver <cellog@php.net>
        !          81125:  * @copyright  1997-2009 The Authors
        !          81126:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          81127:  * @version    Release: 1.9.4
        !          81128:  * @link       http://pear.php.net/package/PEAR
        !          81129:  * @since      Class available since Release 1.4.0a1
        !          81130:  */
        !          81131: class PEAR_Installer_Role_Test extends PEAR_Installer_Role_Common {}
        !          81132: ?><role version="1.0">
        !          81133:  <releasetypes>php</releasetypes>
        !          81134:  <releasetypes>extsrc</releasetypes>
        !          81135:  <releasetypes>extbin</releasetypes>
        !          81136:  <releasetypes>zendextsrc</releasetypes>
        !          81137:  <releasetypes>zendextbin</releasetypes>
        !          81138:  <installable>1</installable>
        !          81139:  <locationconfig>test_dir</locationconfig>
        !          81140:  <honorsbaseinstall />
        !          81141:  <unusualbaseinstall />
        !          81142:  <phpfile />
        !          81143:  <executable />
        !          81144:  <phpextension />
        !          81145:  <config_vars />
        !          81146: </role><?php
        !          81147: /**
        !          81148:  * PEAR_Installer_Role_Www
        !          81149:  *
        !          81150:  * PHP versions 4 and 5
        !          81151:  *
        !          81152:  * @category   pear
        !          81153:  * @package    PEAR
        !          81154:  * @author     Greg Beaver <cellog@php.net>
        !          81155:  * @copyright  2007-2009 The Authors
        !          81156:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          81157:  * @version    CVS: $Id: Www.php 313023 2011-07-06 19:17:11Z dufuz $
        !          81158:  * @link       http://pear.php.net/package/PEAR
        !          81159:  * @since      File available since Release 1.7.0
        !          81160:  */
1.1       misho    81161: 
                   81162: /**
1.1.1.2 ! misho    81163:  * @category   pear
        !          81164:  * @package    PEAR
        !          81165:  * @author     Greg Beaver <cellog@php.net>
        !          81166:  * @copyright  2007-2009 The Authors
        !          81167:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          81168:  * @version    Release: 1.9.4
        !          81169:  * @link       http://pear.php.net/package/PEAR
        !          81170:  * @since      Class available since Release 1.7.0
        !          81171:  */
        !          81172: class PEAR_Installer_Role_Www extends PEAR_Installer_Role_Common {}
        !          81173: ?><role version="1.0">
        !          81174:  <releasetypes>php</releasetypes>
        !          81175:  <releasetypes>extsrc</releasetypes>
        !          81176:  <releasetypes>extbin</releasetypes>
        !          81177:  <releasetypes>zendextsrc</releasetypes>
        !          81178:  <releasetypes>zendextbin</releasetypes>
        !          81179:  <installable>1</installable>
        !          81180:  <locationconfig>www_dir</locationconfig>
        !          81181:  <honorsbaseinstall>1</honorsbaseinstall>
        !          81182:  <unusualbaseinstall />
        !          81183:  <phpfile />
        !          81184:  <executable />
        !          81185:  <phpextension />
        !          81186:  <config_vars />
        !          81187: </role><?php
        !          81188: /**
        !          81189:  * PEAR_PackageFile, package.xml parsing utility class
1.1       misho    81190:  *
                   81191:  * PHP versions 4 and 5
                   81192:  *
                   81193:  * @category   pear
                   81194:  * @package    PEAR
                   81195:  * @author     Greg Beaver <cellog@php.net>
                   81196:  * @copyright  1997-2009 The Authors
                   81197:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    81198:  * @version    CVS: $Id: PackageFile.php 313024 2011-07-06 19:51:24Z dufuz $
1.1       misho    81199:  * @link       http://pear.php.net/package/PEAR
1.1.1.2 ! misho    81200:  * @since      File available since Release 1.4.0a1
1.1       misho    81201:  */
1.1.1.2 ! misho    81202: 
1.1       misho    81203: /**
1.1.1.2 ! misho    81204:  * needed for PEAR_VALIDATE_* constants
1.1       misho    81205:  */
1.1.1.2 ! misho    81206: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Validate.php';
1.1       misho    81207: /**
1.1.1.2 ! misho    81208:  * Error code if the package.xml <package> tag does not contain a valid version
        !          81209:  */
        !          81210: define('PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION', 1);
        !          81211: /**
        !          81212:  * Error code if the package.xml <package> tag version is not supported (version 1.0 and 1.1 are the only supported versions,
        !          81213:  * currently
        !          81214:  */
        !          81215: define('PEAR_PACKAGEFILE_ERROR_INVALID_PACKAGEVERSION', 2);
        !          81216: /**
        !          81217:  * Abstraction for the package.xml package description file
        !          81218:  *
1.1       misho    81219:  * @category   pear
                   81220:  * @package    PEAR
                   81221:  * @author     Greg Beaver <cellog@php.net>
                   81222:  * @copyright  1997-2009 The Authors
                   81223:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    81224:  * @version    Release: 1.9.4
1.1       misho    81225:  * @link       http://pear.php.net/package/PEAR
1.1.1.2 ! misho    81226:  * @since      Class available since Release 1.4.0a1
1.1       misho    81227:  */
1.1.1.2 ! misho    81228: class PEAR_PackageFile
1.1       misho    81229: {
                   81230:     /**
1.1.1.2 ! misho    81231:      * @var PEAR_Config
1.1       misho    81232:      */
1.1.1.2 ! misho    81233:     var $_config;
        !          81234:     var $_debug;
1.1       misho    81235: 
1.1.1.2 ! misho    81236:     var $_logger = false;
        !          81237:     /**
        !          81238:      * @var boolean
        !          81239:      */
        !          81240:     var $_rawReturn = false;
1.1       misho    81241: 
                   81242:     /**
1.1.1.2 ! misho    81243:      * helper for extracting Archive_Tar errors
        !          81244:      * @var array
        !          81245:      * @access private
1.1       misho    81246:      */
1.1.1.2 ! misho    81247:     var $_extractErrors = array();
1.1       misho    81248: 
                   81249:     /**
1.1.1.2 ! misho    81250:      *
        !          81251:      * @param   PEAR_Config $config
        !          81252:      * @param   ?   $debug
        !          81253:      * @param   string @tmpdir Optional temporary directory for uncompressing
        !          81254:      *          files
1.1       misho    81255:      */
1.1.1.2 ! misho    81256:     function PEAR_PackageFile(&$config, $debug = false)
1.1       misho    81257:     {
1.1.1.2 ! misho    81258:         $this->_config = $config;
        !          81259:         $this->_debug = $debug;
1.1       misho    81260:     }
                   81261: 
                   81262:     /**
1.1.1.2 ! misho    81263:      * Turn off validation - return a parsed package.xml without checking it
1.1       misho    81264:      *
1.1.1.2 ! misho    81265:      * This is used by the package-validate command
1.1       misho    81266:      */
1.1.1.2 ! misho    81267:     function rawReturn()
1.1       misho    81268:     {
1.1.1.2 ! misho    81269:         $this->_rawReturn = true;
1.1       misho    81270:     }
                   81271: 
1.1.1.2 ! misho    81272:     function setLogger(&$l)
1.1       misho    81273:     {
1.1.1.2 ! misho    81274:         $this->_logger = &$l;
1.1       misho    81275:     }
                   81276: 
                   81277:     /**
1.1.1.2 ! misho    81278:      * Create a PEAR_PackageFile_Parser_v* of a given version.
        !          81279:      * @param   int $version
        !          81280:      * @return  PEAR_PackageFile_Parser_v1|PEAR_PackageFile_Parser_v1
1.1       misho    81281:      */
1.1.1.2 ! misho    81282:     function &parserFactory($version)
1.1       misho    81283:     {
1.1.1.2 ! misho    81284:         if (!in_array($version{0}, array('1', '2'))) {
        !          81285:             $a = false;
        !          81286:             return $a;
1.1       misho    81287:         }
                   81288: 
1.1.1.2 ! misho    81289:         include_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/Parser/v' . $version{0} . '.php';
        !          81290:         $version = $version{0};
        !          81291:         $class = "PEAR_PackageFile_Parser_v$version";
        !          81292:         $a = new $class;
        !          81293:         return $a;
1.1       misho    81294:     }
                   81295: 
                   81296:     /**
1.1.1.2 ! misho    81297:      * For simpler unit-testing
        !          81298:      * @return string
1.1       misho    81299:      */
1.1.1.2 ! misho    81300:     function getClassPrefix()
1.1       misho    81301:     {
1.1.1.2 ! misho    81302:         return 'PEAR_PackageFile_v';
1.1       misho    81303:     }
                   81304: 
1.1.1.2 ! misho    81305:     /**
        !          81306:      * Create a PEAR_PackageFile_v* of a given version.
        !          81307:      * @param   int $version
        !          81308:      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v1
        !          81309:      */
        !          81310:     function &factory($version)
1.1       misho    81311:     {
1.1.1.2 ! misho    81312:         if (!in_array($version{0}, array('1', '2'))) {
        !          81313:             $a = false;
        !          81314:             return $a;
1.1       misho    81315:         }
                   81316: 
1.1.1.2 ! misho    81317:         include_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v' . $version{0} . '.php';
        !          81318:         $version = $version{0};
        !          81319:         $class = $this->getClassPrefix() . $version;
        !          81320:         $a = new $class;
        !          81321:         return $a;
1.1       misho    81322:     }
                   81323: 
1.1.1.2 ! misho    81324:     /**
        !          81325:      * Create a PEAR_PackageFile_v* from its toArray() method
        !          81326:      *
        !          81327:      * WARNING: no validation is performed, the array is assumed to be valid,
        !          81328:      * always parse from xml if you want validation.
        !          81329:      * @param   array $arr
        !          81330:      * @return PEAR_PackageFileManager_v1|PEAR_PackageFileManager_v2
        !          81331:      * @uses    factory() to construct the returned object.
        !          81332:      */
        !          81333:     function &fromArray($arr)
1.1       misho    81334:     {
1.1.1.2 ! misho    81335:         if (isset($arr['xsdversion'])) {
        !          81336:             $obj = &$this->factory($arr['xsdversion']);
        !          81337:             if ($this->_logger) {
        !          81338:                 $obj->setLogger($this->_logger);
1.1       misho    81339:             }
                   81340: 
1.1.1.2 ! misho    81341:             $obj->setConfig($this->_config);
        !          81342:             $obj->fromArray($arr);
        !          81343:             return $obj;
1.1       misho    81344:         }
                   81345: 
1.1.1.2 ! misho    81346:         if (isset($arr['package']['attribs']['version'])) {
        !          81347:             $obj = &$this->factory($arr['package']['attribs']['version']);
        !          81348:         } else {
        !          81349:             $obj = &$this->factory('1.0');
        !          81350:         }
1.1       misho    81351: 
1.1.1.2 ! misho    81352:         if ($this->_logger) {
        !          81353:             $obj->setLogger($this->_logger);
1.1       misho    81354:         }
                   81355: 
1.1.1.2 ! misho    81356:         $obj->setConfig($this->_config);
        !          81357:         $obj->fromArray($arr);
        !          81358:         return $obj;
1.1       misho    81359:     }
                   81360: 
1.1.1.2 ! misho    81361:     /**
        !          81362:      * Create a PEAR_PackageFile_v* from an XML string.
        !          81363:      * @access  public
        !          81364:      * @param   string $data contents of package.xml file
        !          81365:      * @param   int $state package state (one of PEAR_VALIDATE_* constants)
        !          81366:      * @param   string $file full path to the package.xml file (and the files
        !          81367:      *          it references)
        !          81368:      * @param   string $archive optional name of the archive that the XML was
        !          81369:      *          extracted from, if any
        !          81370:      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
        !          81371:      * @uses    parserFactory() to construct a parser to load the package.
        !          81372:      */
        !          81373:     function &fromXmlString($data, $state, $file, $archive = false)
1.1       misho    81374:     {
1.1.1.2 ! misho    81375:         if (preg_match('/<package[^>]+version=[\'"]([0-9]+\.[0-9]+)[\'"]/', $data, $packageversion)) {
        !          81376:             if (!in_array($packageversion[1], array('1.0', '2.0', '2.1'))) {
        !          81377:                 return PEAR::raiseError('package.xml version "' . $packageversion[1] .
        !          81378:                     '" is not supported, only 1.0, 2.0, and 2.1 are supported.');
        !          81379:             }
1.1       misho    81380: 
1.1.1.2 ! misho    81381:             $object = &$this->parserFactory($packageversion[1]);
        !          81382:             if ($this->_logger) {
        !          81383:                 $object->setLogger($this->_logger);
        !          81384:             }
1.1       misho    81385: 
1.1.1.2 ! misho    81386:             $object->setConfig($this->_config);
        !          81387:             $pf = $object->parse($data, $file, $archive);
        !          81388:             if (PEAR::isError($pf)) {
        !          81389:                 return $pf;
1.1       misho    81390:             }
                   81391: 
1.1.1.2 ! misho    81392:             if ($this->_rawReturn) {
        !          81393:                 return $pf;
        !          81394:             }
        !          81395: 
        !          81396:             if (!$pf->validate($state)) {;
        !          81397:                 if ($this->_config->get('verbose') > 0
        !          81398:                     && $this->_logger && $pf->getValidationWarnings(false)
        !          81399:                 ) {
        !          81400:                     foreach ($pf->getValidationWarnings(false) as $warning) {
        !          81401:                         $this->_logger->log(0, 'ERROR: ' . $warning['message']);
1.1       misho    81402:                     }
                   81403:                 }
1.1.1.2 ! misho    81404: 
        !          81405:                 $a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed',
        !          81406:                     2, null, null, $pf->getValidationWarnings());
        !          81407:                 return $a;
1.1       misho    81408:             }
                   81409: 
1.1.1.2 ! misho    81410:             if ($this->_logger && $pf->getValidationWarnings(false)) {
        !          81411:                 foreach ($pf->getValidationWarnings() as $warning) {
        !          81412:                     $this->_logger->log(0, 'WARNING: ' . $warning['message']);
1.1       misho    81413:                 }
                   81414:             }
                   81415: 
1.1.1.2 ! misho    81416:             if (method_exists($pf, 'flattenFilelist')) {
        !          81417:                 $pf->flattenFilelist(); // for v2
1.1       misho    81418:             }
                   81419: 
1.1.1.2 ! misho    81420:             return $pf;
        !          81421:         } elseif (preg_match('/<package[^>]+version=[\'"]([^"\']+)[\'"]/', $data, $packageversion)) {
        !          81422:             $a = PEAR::raiseError('package.xml file "' . $file .
        !          81423:                 '" has unsupported package.xml <package> version "' . $packageversion[1] . '"');
        !          81424:             return $a;
        !          81425:         } else {
        !          81426:             if (!class_exists('PEAR_ErrorStack')) {
        !          81427:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ErrorStack.php';
        !          81428:             }
        !          81429: 
        !          81430:             PEAR_ErrorStack::staticPush('PEAR_PackageFile',
        !          81431:                 PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION,
        !          81432:                 'warning', array('xml' => $data), 'package.xml "' . $file .
        !          81433:                     '" has no package.xml <package> version');
        !          81434:             $object = &$this->parserFactory('1.0');
        !          81435:             $object->setConfig($this->_config);
        !          81436:             $pf = $object->parse($data, $file, $archive);
        !          81437:             if (PEAR::isError($pf)) {
        !          81438:                 return $pf;
        !          81439:             }
        !          81440: 
        !          81441:             if ($this->_rawReturn) {
        !          81442:                 return $pf;
        !          81443:             }
        !          81444: 
        !          81445:             if (!$pf->validate($state)) {
        !          81446:                 $a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed',
        !          81447:                     2, null, null, $pf->getValidationWarnings());
        !          81448:                 return $a;
        !          81449:             }
        !          81450: 
        !          81451:             if ($this->_logger && $pf->getValidationWarnings(false)) {
        !          81452:                 foreach ($pf->getValidationWarnings() as $warning) {
        !          81453:                     $this->_logger->log(0, 'WARNING: ' . $warning['message']);
        !          81454:                 }
        !          81455:             }
        !          81456: 
        !          81457:             if (method_exists($pf, 'flattenFilelist')) {
        !          81458:                 $pf->flattenFilelist(); // for v2
        !          81459:             }
        !          81460: 
        !          81461:             return $pf;
1.1       misho    81462:         }
1.1.1.2 ! misho    81463:     }
1.1       misho    81464: 
1.1.1.2 ! misho    81465:     /**
        !          81466:      * Register a temporary file or directory.  When the destructor is
        !          81467:      * executed, all registered temporary files and directories are
        !          81468:      * removed.
        !          81469:      *
        !          81470:      * @param string  $file  name of file or directory
        !          81471:      * @return  void
        !          81472:      */
        !          81473:     function addTempFile($file)
        !          81474:     {
        !          81475:         $GLOBALS['_PEAR_Common_tempfiles'][] = $file;
1.1       misho    81476:     }
                   81477: 
1.1.1.2 ! misho    81478:     /**
        !          81479:      * Create a PEAR_PackageFile_v* from a compresed Tar or Tgz file.
        !          81480:      * @access  public
        !          81481:      * @param string contents of package.xml file
        !          81482:      * @param int package state (one of PEAR_VALIDATE_* constants)
        !          81483:      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
        !          81484:      * @using   Archive_Tar to extract the files
        !          81485:      * @using   fromPackageFile() to load the package after the package.xml
        !          81486:      *          file is extracted.
        !          81487:      */
        !          81488:     function &fromTgzFile($file, $state)
1.1       misho    81489:     {
1.1.1.2 ! misho    81490:         if (!class_exists('Archive_Tar')) {
        !          81491:             require_once 'phar://install-pear-nozlib.phar/' . 'Archive/Tar.php';
1.1       misho    81492:         }
                   81493: 
1.1.1.2 ! misho    81494:         $tar = new Archive_Tar($file);
        !          81495:         if ($this->_debug <= 1) {
        !          81496:             $tar->pushErrorHandling(PEAR_ERROR_RETURN);
1.1       misho    81497:         }
                   81498: 
1.1.1.2 ! misho    81499:         $content = $tar->listContent();
        !          81500:         if ($this->_debug <= 1) {
        !          81501:             $tar->popErrorHandling();
1.1       misho    81502:         }
                   81503: 
1.1.1.2 ! misho    81504:         if (!is_array($content)) {
        !          81505:             if (is_string($file) && strlen($file < 255) &&
        !          81506:                   (!file_exists($file) || !@is_file($file))) {
        !          81507:                 $ret = PEAR::raiseError("could not open file \"$file\"");
        !          81508:                 return $ret;
1.1       misho    81509:             }
                   81510: 
1.1.1.2 ! misho    81511:             $file = realpath($file);
        !          81512:             $ret = PEAR::raiseError("Could not get contents of package \"$file\"".
        !          81513:                                      '. Invalid tgz file.');
        !          81514:             return $ret;
1.1       misho    81515:         }
                   81516: 
1.1.1.2 ! misho    81517:         if (!count($content) && !@is_file($file)) {
        !          81518:             $ret = PEAR::raiseError("could not open file \"$file\"");
        !          81519:             return $ret;
        !          81520:         }
1.1       misho    81521: 
1.1.1.2 ! misho    81522:         $xml      = null;
        !          81523:         $origfile = $file;
        !          81524:         foreach ($content as $file) {
        !          81525:             $name = $file['filename'];
        !          81526:             if ($name == 'package2.xml') { // allow a .tgz to distribute both versions
        !          81527:                 $xml = $name;
        !          81528:                 break;
1.1       misho    81529:             }
                   81530: 
1.1.1.2 ! misho    81531:             if ($name == 'package.xml') {
        !          81532:                 $xml = $name;
        !          81533:                 break;
        !          81534:             } elseif (preg_match('/package.xml$/', $name, $match)) {
        !          81535:                 $xml = $name;
        !          81536:                 break;
1.1       misho    81537:             }
1.1.1.2 ! misho    81538:         }
1.1       misho    81539: 
1.1.1.2 ! misho    81540:         $tmpdir = System::mktemp('-t "' . $this->_config->get('temp_dir') . '" -d pear');
        !          81541:         if ($tmpdir === false) {
        !          81542:             $ret = PEAR::raiseError("there was a problem with getting the configured temp directory");
        !          81543:             return $ret;
        !          81544:         }
1.1       misho    81545: 
1.1.1.2 ! misho    81546:         PEAR_PackageFile::addTempFile($tmpdir);
1.1       misho    81547: 
1.1.1.2 ! misho    81548:         $this->_extractErrors();
        !          81549:         PEAR::staticPushErrorHandling(PEAR_ERROR_CALLBACK, array($this, '_extractErrors'));
1.1       misho    81550: 
1.1.1.2 ! misho    81551:         if (!$xml || !$tar->extractList(array($xml), $tmpdir)) {
        !          81552:             $extra = implode("\n", $this->_extractErrors());
        !          81553:             if ($extra) {
        !          81554:                 $extra = ' ' . $extra;
1.1       misho    81555:             }
1.1.1.2 ! misho    81556: 
        !          81557:             PEAR::staticPopErrorHandling();
        !          81558:             $ret = PEAR::raiseError('could not extract the package.xml file from "' .
        !          81559:                 $origfile . '"' . $extra);
        !          81560:             return $ret;
1.1       misho    81561:         }
                   81562: 
1.1.1.2 ! misho    81563:         PEAR::staticPopErrorHandling();
        !          81564:         $ret = &PEAR_PackageFile::fromPackageFile("$tmpdir/$xml", $state, $origfile);
        !          81565:         return $ret;
        !          81566:     }
        !          81567: 
        !          81568:     /**
        !          81569:      * helper callback for extracting Archive_Tar errors
        !          81570:      *
        !          81571:      * @param PEAR_Error|null $err
        !          81572:      * @return array
        !          81573:      * @access private
        !          81574:      */
        !          81575:     function _extractErrors($err = null)
        !          81576:     {
        !          81577:         static $errors = array();
        !          81578:         if ($err === null) {
        !          81579:             $e = $errors;
        !          81580:             $errors = array();
        !          81581:             return $e;
1.1       misho    81582:         }
1.1.1.2 ! misho    81583:         $errors[] = $err->getMessage();
1.1       misho    81584:     }
                   81585: 
1.1.1.2 ! misho    81586:     /**
        !          81587:      * Create a PEAR_PackageFile_v* from a package.xml file.
        !          81588:      *
        !          81589:      * @access public
        !          81590:      * @param   string  $descfile  name of package xml file
        !          81591:      * @param   int     $state package state (one of PEAR_VALIDATE_* constants)
        !          81592:      * @param   string|false $archive name of the archive this package.xml came
        !          81593:      *          from, if any
        !          81594:      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
        !          81595:      * @uses    PEAR_PackageFile::fromXmlString to create the oject after the
        !          81596:      *          XML is loaded from the package.xml file.
        !          81597:      */
        !          81598:     function &fromPackageFile($descfile, $state, $archive = false)
1.1       misho    81599:     {
1.1.1.2 ! misho    81600:         $fp = false;
        !          81601:         if (is_string($descfile) && strlen($descfile) < 255 &&
        !          81602:              (
        !          81603:               !file_exists($descfile) || !is_file($descfile) || !is_readable($descfile)
        !          81604:               || (!$fp = @fopen($descfile, 'r'))
        !          81605:              )
        !          81606:         ) {
        !          81607:             $a = PEAR::raiseError("Unable to open $descfile");
        !          81608:             return $a;
        !          81609:         }
        !          81610: 
        !          81611:         // read the whole thing so we only get one cdata callback
        !          81612:         // for each block of cdata
        !          81613:         fclose($fp);
        !          81614:         $data = file_get_contents($descfile);
        !          81615:         $ret = &PEAR_PackageFile::fromXmlString($data, $state, $descfile, $archive);
        !          81616:         return $ret;
1.1       misho    81617:     }
                   81618: 
1.1.1.2 ! misho    81619:     /**
        !          81620:      * Create a PEAR_PackageFile_v* from a .tgz archive or package.xml file.
        !          81621:      *
        !          81622:      * This method is able to extract information about a package from a .tgz
        !          81623:      * archive or from a XML package definition file.
        !          81624:      *
        !          81625:      * @access public
        !          81626:      * @param   string  $info file name
        !          81627:      * @param   int     $state package state (one of PEAR_VALIDATE_* constants)
        !          81628:      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
        !          81629:      * @uses    fromPackageFile() if the file appears to be XML
        !          81630:      * @uses    fromTgzFile() to load all non-XML files
        !          81631:      */
        !          81632:     function &fromAnyFile($info, $state)
1.1       misho    81633:     {
1.1.1.2 ! misho    81634:         if (is_dir($info)) {
        !          81635:             $dir_name = realpath($info);
        !          81636:             if (file_exists($dir_name . '/package.xml')) {
        !          81637:                 $info = PEAR_PackageFile::fromPackageFile($dir_name .  '/package.xml', $state);
        !          81638:             } elseif (file_exists($dir_name .  '/package2.xml')) {
        !          81639:                 $info = PEAR_PackageFile::fromPackageFile($dir_name .  '/package2.xml', $state);
        !          81640:             } else {
        !          81641:                 $info = PEAR::raiseError("No package definition found in '$info' directory");
        !          81642:             }
        !          81643: 
        !          81644:             return $info;
        !          81645:         }
        !          81646: 
        !          81647:         $fp = false;
        !          81648:         if (is_string($info) && strlen($info) < 255 &&
        !          81649:              (file_exists($info) || ($fp = @fopen($info, 'r')))
        !          81650:         ) {
        !          81651: 
        !          81652:             if ($fp) {
        !          81653:                 fclose($fp);
        !          81654:             }
        !          81655: 
        !          81656:             $tmp = substr($info, -4);
        !          81657:             if ($tmp == '.xml') {
        !          81658:                 $info = &PEAR_PackageFile::fromPackageFile($info, $state);
        !          81659:             } elseif ($tmp == '.tar' || $tmp == '.tgz') {
        !          81660:                 $info = &PEAR_PackageFile::fromTgzFile($info, $state);
        !          81661:             } else {
        !          81662:                 $fp   = fopen($info, 'r');
        !          81663:                 $test = fread($fp, 5);
        !          81664:                 fclose($fp);
        !          81665:                 if ($test == '<?xml') {
        !          81666:                     $info = &PEAR_PackageFile::fromPackageFile($info, $state);
        !          81667:                 } else {
        !          81668:                     $info = &PEAR_PackageFile::fromTgzFile($info, $state);
        !          81669:                 }
        !          81670:             }
        !          81671: 
        !          81672:             return $info;
        !          81673:         }
        !          81674: 
        !          81675:         $info = PEAR::raiseError("Cannot open '$info' for parsing");
        !          81676:         return $info;
1.1       misho    81677:     }
                   81678: }<?php
                   81679: /**
1.1.1.2 ! misho    81680:  * package.xml generation class, package.xml version 1.0
1.1       misho    81681:  *
                   81682:  * PHP versions 4 and 5
                   81683:  *
                   81684:  * @category   pear
                   81685:  * @package    PEAR
                   81686:  * @author     Greg Beaver <cellog@php.net>
                   81687:  * @copyright  1997-2009 The Authors
                   81688:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    81689:  * @version    CVS: $Id: v1.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    81690:  * @link       http://pear.php.net/package/PEAR
1.1.1.2 ! misho    81691:  * @since      File available since Release 1.4.0a1
1.1       misho    81692:  */
                   81693: /**
1.1.1.2 ! misho    81694:  * needed for PEAR_VALIDATE_* constants
1.1       misho    81695:  */
1.1.1.2 ! misho    81696: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Validate.php';
        !          81697: require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
        !          81698: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2.php';
1.1       misho    81699: /**
1.1.1.2 ! misho    81700:  * This class converts a PEAR_PackageFile_v1 object into any output format.
1.1       misho    81701:  *
1.1.1.2 ! misho    81702:  * Supported output formats include array, XML string, and a PEAR_PackageFile_v2
        !          81703:  * object, for converting package.xml 1.0 into package.xml 2.0 with no sweat.
1.1       misho    81704:  * @category   pear
                   81705:  * @package    PEAR
                   81706:  * @author     Greg Beaver <cellog@php.net>
                   81707:  * @copyright  1997-2009 The Authors
                   81708:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    81709:  * @version    Release: 1.9.4
1.1       misho    81710:  * @link       http://pear.php.net/package/PEAR
1.1.1.2 ! misho    81711:  * @since      Class available since Release 1.4.0a1
1.1       misho    81712:  */
1.1.1.2 ! misho    81713: class PEAR_PackageFile_Generator_v1
1.1       misho    81714: {
                   81715:     /**
1.1.1.2 ! misho    81716:      * @var PEAR_PackageFile_v1
1.1       misho    81717:      */
1.1.1.2 ! misho    81718:     var $_packagefile;
        !          81719:     function PEAR_PackageFile_Generator_v1(&$packagefile)
1.1       misho    81720:     {
1.1.1.2 ! misho    81721:         $this->_packagefile = &$packagefile;
1.1       misho    81722:     }
                   81723: 
1.1.1.2 ! misho    81724:     function getPackagerVersion()
1.1       misho    81725:     {
1.1.1.2 ! misho    81726:         return '1.9.4';
1.1       misho    81727:     }
                   81728: 
                   81729:     /**
1.1.1.2 ! misho    81730:      * @param PEAR_Packager
        !          81731:      * @param bool if true, a .tgz is written, otherwise a .tar is written
        !          81732:      * @param string|null directory in which to save the .tgz
        !          81733:      * @return string|PEAR_Error location of package or error object
1.1       misho    81734:      */
1.1.1.2 ! misho    81735:     function toTgz(&$packager, $compress = true, $where = null)
1.1       misho    81736:     {
1.1.1.2 ! misho    81737:         require_once 'phar://install-pear-nozlib.phar/' . 'Archive/Tar.php';
        !          81738:         if ($where === null) {
        !          81739:             if (!($where = System::mktemp(array('-d')))) {
        !          81740:                 return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: mktemp failed');
        !          81741:             }
        !          81742:         } elseif (!@System::mkDir(array('-p', $where))) {
        !          81743:             return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: "' . $where . '" could' .
        !          81744:                 ' not be created');
1.1       misho    81745:         }
1.1.1.2 ! misho    81746:         if (file_exists($where . DIRECTORY_SEPARATOR . 'package.xml') &&
        !          81747:               !is_file($where . DIRECTORY_SEPARATOR . 'package.xml')) {
        !          81748:             return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: unable to save package.xml as' .
        !          81749:                 ' "' . $where . DIRECTORY_SEPARATOR . 'package.xml"');
1.1       misho    81750:         }
1.1.1.2 ! misho    81751:         if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) {
        !          81752:             return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: invalid package file');
1.1       misho    81753:         }
1.1.1.2 ! misho    81754:         $pkginfo = $this->_packagefile->getArray();
        !          81755:         $ext = $compress ? '.tgz' : '.tar';
        !          81756:         $pkgver = $pkginfo['package'] . '-' . $pkginfo['version'];
        !          81757:         $dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext;
        !          81758:         if (file_exists(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext) &&
        !          81759:               !is_file(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext)) {
        !          81760:             return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: cannot create tgz file "' .
        !          81761:                 getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext . '"');
        !          81762:         }
        !          81763:         if ($pkgfile = $this->_packagefile->getPackageFile()) {
        !          81764:             $pkgdir = dirname(realpath($pkgfile));
        !          81765:             $pkgfile = basename($pkgfile);
        !          81766:         } else {
        !          81767:             return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: package file object must ' .
        !          81768:                 'be created from a real file');
1.1       misho    81769:         }
1.1.1.2 ! misho    81770:         // {{{ Create the package file list
        !          81771:         $filelist = array();
        !          81772:         $i = 0;
1.1       misho    81773: 
1.1.1.2 ! misho    81774:         foreach ($this->_packagefile->getFilelist() as $fname => $atts) {
        !          81775:             $file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
        !          81776:             if (!file_exists($file)) {
        !          81777:                 return PEAR::raiseError("File does not exist: $fname");
        !          81778:             } else {
        !          81779:                 $filelist[$i++] = $file;
        !          81780:                 if (!isset($atts['md5sum'])) {
        !          81781:                     $this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($file));
        !          81782:                 }
        !          81783:                 $packager->log(2, "Adding file $fname");
1.1       misho    81784:             }
1.1.1.2 ! misho    81785:         }
        !          81786:         // }}}
        !          81787:         $packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, 'package.xml', true);
        !          81788:         if ($packagexml) {
        !          81789:             $tar =& new Archive_Tar($dest_package, $compress);
        !          81790:             $tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors
        !          81791:             // ----- Creates with the package.xml file
        !          81792:             $ok = $tar->createModify(array($packagexml), '', $where);
        !          81793:             if (PEAR::isError($ok)) {
        !          81794:                 return $ok;
        !          81795:             } elseif (!$ok) {
        !          81796:                 return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed');
1.1       misho    81797:             }
1.1.1.2 ! misho    81798:             // ----- Add the content of the package
        !          81799:             if (!$tar->addModify($filelist, $pkgver, $pkgdir)) {
        !          81800:                 return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed');
        !          81801:             }
        !          81802:             return $dest_package;
1.1       misho    81803:         }
1.1.1.2 ! misho    81804:     }
1.1       misho    81805: 
1.1.1.2 ! misho    81806:     /**
        !          81807:      * @param string|null directory to place the package.xml in, or null for a temporary dir
        !          81808:      * @param int one of the PEAR_VALIDATE_* constants
        !          81809:      * @param string name of the generated file
        !          81810:      * @param bool if true, then no analysis will be performed on role="php" files
        !          81811:      * @return string|PEAR_Error path to the created file on success
        !          81812:      */
        !          81813:     function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml',
        !          81814:                            $nofilechecking = false)
        !          81815:     {
        !          81816:         if (!$this->_packagefile->validate($state, $nofilechecking)) {
        !          81817:             return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: invalid package.xml',
        !          81818:                 null, null, null, $this->_packagefile->getValidationWarnings());
1.1       misho    81819:         }
1.1.1.2 ! misho    81820:         if ($where === null) {
        !          81821:             if (!($where = System::mktemp(array('-d')))) {
        !          81822:                 return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: mktemp failed');
        !          81823:             }
        !          81824:         } elseif (!@System::mkDir(array('-p', $where))) {
        !          81825:             return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: "' . $where . '" could' .
        !          81826:                 ' not be created');
        !          81827:         }
        !          81828:         $newpkgfile = $where . DIRECTORY_SEPARATOR . $name;
        !          81829:         $np = @fopen($newpkgfile, 'wb');
        !          81830:         if (!$np) {
        !          81831:             return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: unable to save ' .
        !          81832:                "$name as $newpkgfile");
        !          81833:         }
        !          81834:         fwrite($np, $this->toXml($state, true));
        !          81835:         fclose($np);
        !          81836:         return $newpkgfile;
1.1       misho    81837:     }
                   81838: 
                   81839:     /**
1.1.1.2 ! misho    81840:      * fix both XML encoding to be UTF8, and replace standard XML entities < > " & '
        !          81841:      *
        !          81842:      * @param string $string
        !          81843:      * @return string
1.1       misho    81844:      * @access private
                   81845:      */
1.1.1.2 ! misho    81846:     function _fixXmlEncoding($string)
1.1       misho    81847:     {
1.1.1.2 ! misho    81848:         if (version_compare(phpversion(), '5.0.0', 'lt')) {
        !          81849:             $string = utf8_encode($string);
1.1       misho    81850:         }
1.1.1.2 ! misho    81851:         return strtr($string, array(
        !          81852:                                           '&'  => '&amp;',
        !          81853:                                           '>'  => '&gt;',
        !          81854:                                           '<'  => '&lt;',
        !          81855:                                           '"'  => '&quot;',
        !          81856:                                           '\'' => '&apos;' ));
        !          81857:     }
1.1       misho    81858: 
1.1.1.2 ! misho    81859:     /**
        !          81860:      * Return an XML document based on the package info (as returned
        !          81861:      * by the PEAR_Common::infoFrom* methods).
        !          81862:      *
        !          81863:      * @return string XML data
        !          81864:      */
        !          81865:     function toXml($state = PEAR_VALIDATE_NORMAL, $nofilevalidation = false)
        !          81866:     {
        !          81867:         $this->_packagefile->setDate(date('Y-m-d'));
        !          81868:         if (!$this->_packagefile->validate($state, $nofilevalidation)) {
        !          81869:             return false;
        !          81870:         }
        !          81871:         $pkginfo = $this->_packagefile->getArray();
        !          81872:         static $maint_map = array(
        !          81873:             "handle" => "user",
        !          81874:             "name" => "name",
        !          81875:             "email" => "email",
        !          81876:             "role" => "role",
        !          81877:             );
        !          81878:         $ret = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
        !          81879:         $ret .= "<!DOCTYPE package SYSTEM \"http://pear.php.net/dtd/package-1.0\">\n";
        !          81880:         $ret .= "<package version=\"1.0\" packagerversion=\"1.9.4\">\n" .
        !          81881: " <name>$pkginfo[package]</name>";
        !          81882:         if (isset($pkginfo['extends'])) {
        !          81883:             $ret .= "\n<extends>$pkginfo[extends]</extends>";
        !          81884:         }
        !          81885:         $ret .=
        !          81886:  "\n <summary>".$this->_fixXmlEncoding($pkginfo['summary'])."</summary>\n" .
        !          81887: " <description>".trim($this->_fixXmlEncoding($pkginfo['description']))."\n </description>\n" .
        !          81888: " <maintainers>\n";
        !          81889:         foreach ($pkginfo['maintainers'] as $maint) {
        !          81890:             $ret .= "  <maintainer>\n";
        !          81891:             foreach ($maint_map as $idx => $elm) {
        !          81892:                 $ret .= "   <$elm>";
        !          81893:                 $ret .= $this->_fixXmlEncoding($maint[$idx]);
        !          81894:                 $ret .= "</$elm>\n";
1.1       misho    81895:             }
1.1.1.2 ! misho    81896:             $ret .= "  </maintainer>\n";
        !          81897:         }
        !          81898:         $ret .= "  </maintainers>\n";
        !          81899:         $ret .= $this->_makeReleaseXml($pkginfo, false, $state);
        !          81900:         if (isset($pkginfo['changelog']) && count($pkginfo['changelog']) > 0) {
        !          81901:             $ret .= " <changelog>\n";
        !          81902:             foreach ($pkginfo['changelog'] as $oldrelease) {
        !          81903:                 $ret .= $this->_makeReleaseXml($oldrelease, true);
1.1       misho    81904:             }
1.1.1.2 ! misho    81905:             $ret .= " </changelog>\n";
1.1       misho    81906:         }
1.1.1.2 ! misho    81907:         $ret .= "</package>\n";
        !          81908:         return $ret;
        !          81909:     }
1.1       misho    81910: 
1.1.1.2 ! misho    81911:     // }}}
        !          81912:     // {{{ _makeReleaseXml()
1.1       misho    81913: 
1.1.1.2 ! misho    81914:     /**
        !          81915:      * Generate part of an XML description with release information.
        !          81916:      *
        !          81917:      * @param array  $pkginfo    array with release information
        !          81918:      * @param bool   $changelog  whether the result will be in a changelog element
        !          81919:      *
        !          81920:      * @return string XML data
        !          81921:      *
        !          81922:      * @access private
        !          81923:      */
        !          81924:     function _makeReleaseXml($pkginfo, $changelog = false, $state = PEAR_VALIDATE_NORMAL)
        !          81925:     {
        !          81926:         // XXX QUOTE ENTITIES IN PCDATA, OR EMBED IN CDATA BLOCKS!!
        !          81927:         $indent = $changelog ? "  " : "";
        !          81928:         $ret = "$indent <release>\n";
        !          81929:         if (!empty($pkginfo['version'])) {
        !          81930:             $ret .= "$indent  <version>$pkginfo[version]</version>\n";
1.1       misho    81931:         }
1.1.1.2 ! misho    81932:         if (!empty($pkginfo['release_date'])) {
        !          81933:             $ret .= "$indent  <date>$pkginfo[release_date]</date>\n";
1.1       misho    81934:         }
1.1.1.2 ! misho    81935:         if (!empty($pkginfo['release_license'])) {
        !          81936:             $ret .= "$indent  <license>$pkginfo[release_license]</license>\n";
1.1       misho    81937:         }
1.1.1.2 ! misho    81938:         if (!empty($pkginfo['release_state'])) {
        !          81939:             $ret .= "$indent  <state>$pkginfo[release_state]</state>\n";
1.1       misho    81940:         }
1.1.1.2 ! misho    81941:         if (!empty($pkginfo['release_notes'])) {
        !          81942:             $ret .= "$indent  <notes>".trim($this->_fixXmlEncoding($pkginfo['release_notes']))
        !          81943:             ."\n$indent  </notes>\n";
1.1       misho    81944:         }
1.1.1.2 ! misho    81945:         if (!empty($pkginfo['release_warnings'])) {
        !          81946:             $ret .= "$indent  <warnings>".$this->_fixXmlEncoding($pkginfo['release_warnings'])."</warnings>\n";
1.1       misho    81947:         }
1.1.1.2 ! misho    81948:         if (isset($pkginfo['release_deps']) && sizeof($pkginfo['release_deps']) > 0) {
        !          81949:             $ret .= "$indent  <deps>\n";
        !          81950:             foreach ($pkginfo['release_deps'] as $dep) {
        !          81951:                 $ret .= "$indent   <dep type=\"$dep[type]\" rel=\"$dep[rel]\"";
        !          81952:                 if (isset($dep['version'])) {
        !          81953:                     $ret .= " version=\"$dep[version]\"";
1.1       misho    81954:                 }
1.1.1.2 ! misho    81955:                 if (isset($dep['optional'])) {
        !          81956:                     $ret .= " optional=\"$dep[optional]\"";
1.1       misho    81957:                 }
1.1.1.2 ! misho    81958:                 if (isset($dep['name'])) {
        !          81959:                     $ret .= ">$dep[name]</dep>\n";
        !          81960:                 } else {
        !          81961:                     $ret .= "/>\n";
1.1       misho    81962:                 }
1.1.1.2 ! misho    81963:             }
        !          81964:             $ret .= "$indent  </deps>\n";
        !          81965:         }
        !          81966:         if (isset($pkginfo['configure_options'])) {
        !          81967:             $ret .= "$indent  <configureoptions>\n";
        !          81968:             foreach ($pkginfo['configure_options'] as $c) {
        !          81969:                 $ret .= "$indent   <configureoption name=\"".
        !          81970:                     $this->_fixXmlEncoding($c['name']) . "\"";
        !          81971:                 if (isset($c['default'])) {
        !          81972:                     $ret .= " default=\"" . $this->_fixXmlEncoding($c['default']) . "\"";
1.1       misho    81973:                 }
1.1.1.2 ! misho    81974:                 $ret .= " prompt=\"" . $this->_fixXmlEncoding($c['prompt']) . "\"";
        !          81975:                 $ret .= "/>\n";
        !          81976:             }
        !          81977:             $ret .= "$indent  </configureoptions>\n";
        !          81978:         }
        !          81979:         if (isset($pkginfo['provides'])) {
        !          81980:             foreach ($pkginfo['provides'] as $key => $what) {
        !          81981:                 $ret .= "$indent  <provides type=\"$what[type]\" ";
        !          81982:                 $ret .= "name=\"$what[name]\" ";
        !          81983:                 if (isset($what['extends'])) {
        !          81984:                     $ret .= "extends=\"$what[extends]\" ";
1.1       misho    81985:                 }
1.1.1.2 ! misho    81986:                 $ret .= "/>\n";
        !          81987:             }
        !          81988:         }
        !          81989:         if (isset($pkginfo['filelist'])) {
        !          81990:             $ret .= "$indent  <filelist>\n";
        !          81991:             if ($state ^ PEAR_VALIDATE_PACKAGING) {
        !          81992:                 $ret .= $this->recursiveXmlFilelist($pkginfo['filelist']);
        !          81993:             } else {
        !          81994:                 foreach ($pkginfo['filelist'] as $file => $fa) {
        !          81995:                     if (!isset($fa['role'])) {
        !          81996:                         $fa['role'] = '';
1.1       misho    81997:                     }
1.1.1.2 ! misho    81998:                     $ret .= "$indent   <file role=\"$fa[role]\"";
        !          81999:                     if (isset($fa['baseinstalldir'])) {
        !          82000:                         $ret .= ' baseinstalldir="' .
        !          82001:                             $this->_fixXmlEncoding($fa['baseinstalldir']) . '"';
1.1       misho    82002:                     }
1.1.1.2 ! misho    82003:                     if (isset($fa['md5sum'])) {
        !          82004:                         $ret .= " md5sum=\"$fa[md5sum]\"";
        !          82005:                     }
        !          82006:                     if (isset($fa['platform'])) {
        !          82007:                         $ret .= " platform=\"$fa[platform]\"";
        !          82008:                     }
        !          82009:                     if (!empty($fa['install-as'])) {
        !          82010:                         $ret .= ' install-as="' .
        !          82011:                             $this->_fixXmlEncoding($fa['install-as']) . '"';
1.1       misho    82012:                     }
1.1.1.2 ! misho    82013:                     $ret .= ' name="' . $this->_fixXmlEncoding($file) . '"';
        !          82014:                     if (empty($fa['replacements'])) {
        !          82015:                         $ret .= "/>\n";
        !          82016:                     } else {
        !          82017:                         $ret .= ">\n";
        !          82018:                         foreach ($fa['replacements'] as $r) {
        !          82019:                             $ret .= "$indent    <replace";
        !          82020:                             foreach ($r as $k => $v) {
        !          82021:                                 $ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"';
        !          82022:                             }
        !          82023:                             $ret .= "/>\n";
1.1       misho    82024:                         }
1.1.1.2 ! misho    82025:                         $ret .= "$indent   </file>\n";
1.1       misho    82026:                     }
                   82027:                 }
                   82028:             }
1.1.1.2 ! misho    82029:             $ret .= "$indent  </filelist>\n";
1.1       misho    82030:         }
1.1.1.2 ! misho    82031:         $ret .= "$indent </release>\n";
        !          82032:         return $ret;
        !          82033:     }
1.1       misho    82034: 
1.1.1.2 ! misho    82035:     /**
        !          82036:      * @param array
        !          82037:      * @access protected
        !          82038:      */
        !          82039:     function recursiveXmlFilelist($list)
        !          82040:     {
        !          82041:         $this->_dirs = array();
        !          82042:         foreach ($list as $file => $attributes) {
        !          82043:             $this->_addDir($this->_dirs, explode('/', dirname($file)), $file, $attributes);
1.1       misho    82044:         }
1.1.1.2 ! misho    82045:         return $this->_formatDir($this->_dirs);
        !          82046:     }
1.1       misho    82047: 
1.1.1.2 ! misho    82048:     /**
        !          82049:      * @param array
        !          82050:      * @param array
        !          82051:      * @param string|null
        !          82052:      * @param array|null
        !          82053:      * @access private
        !          82054:      */
        !          82055:     function _addDir(&$dirs, $dir, $file = null, $attributes = null)
        !          82056:     {
        !          82057:         if ($dir == array() || $dir == array('.')) {
        !          82058:             $dirs['files'][basename($file)] = $attributes;
        !          82059:             return;
1.1       misho    82060:         }
1.1.1.2 ! misho    82061:         $curdir = array_shift($dir);
        !          82062:         if (!isset($dirs['dirs'][$curdir])) {
        !          82063:             $dirs['dirs'][$curdir] = array();
        !          82064:         }
        !          82065:         $this->_addDir($dirs['dirs'][$curdir], $dir, $file, $attributes);
1.1       misho    82066:     }
                   82067: 
                   82068:     /**
1.1.1.2 ! misho    82069:      * @param array
        !          82070:      * @param string
        !          82071:      * @param string
1.1       misho    82072:      * @access private
                   82073:      */
1.1.1.2 ! misho    82074:     function _formatDir($dirs, $indent = '', $curdir = '')
1.1       misho    82075:     {
1.1.1.2 ! misho    82076:         $ret = '';
        !          82077:         if (!count($dirs)) {
        !          82078:             return '';
1.1       misho    82079:         }
1.1.1.2 ! misho    82080:         if (isset($dirs['dirs'])) {
        !          82081:             uksort($dirs['dirs'], 'strnatcasecmp');
        !          82082:             foreach ($dirs['dirs'] as $dir => $contents) {
        !          82083:                 $usedir = "$curdir/$dir";
        !          82084:                 $ret .= "$indent   <dir name=\"$dir\">\n";
        !          82085:                 $ret .= $this->_formatDir($contents, "$indent ", $usedir);
        !          82086:                 $ret .= "$indent   </dir> <!-- $usedir -->\n";
        !          82087:             }
1.1       misho    82088:         }
1.1.1.2 ! misho    82089:         if (isset($dirs['files'])) {
        !          82090:             uksort($dirs['files'], 'strnatcasecmp');
        !          82091:             foreach ($dirs['files'] as $file => $attribs) {
        !          82092:                 $ret .= $this->_formatFile($file, $attribs, $indent);
        !          82093:             }
1.1       misho    82094:         }
1.1.1.2 ! misho    82095:         return $ret;
        !          82096:     }
1.1       misho    82097: 
1.1.1.2 ! misho    82098:     /**
        !          82099:      * @param string
        !          82100:      * @param array
        !          82101:      * @param string
        !          82102:      * @access private
        !          82103:      */
        !          82104:     function _formatFile($file, $attributes, $indent)
        !          82105:     {
        !          82106:         $ret = "$indent   <file role=\"$attributes[role]\"";
        !          82107:         if (isset($attributes['baseinstalldir'])) {
        !          82108:             $ret .= ' baseinstalldir="' .
        !          82109:                 $this->_fixXmlEncoding($attributes['baseinstalldir']) . '"';
1.1       misho    82110:         }
1.1.1.2 ! misho    82111:         if (isset($attributes['md5sum'])) {
        !          82112:             $ret .= " md5sum=\"$attributes[md5sum]\"";
1.1       misho    82113:         }
1.1.1.2 ! misho    82114:         if (isset($attributes['platform'])) {
        !          82115:             $ret .= " platform=\"$attributes[platform]\"";
1.1       misho    82116:         }
1.1.1.2 ! misho    82117:         if (!empty($attributes['install-as'])) {
        !          82118:             $ret .= ' install-as="' .
        !          82119:                 $this->_fixXmlEncoding($attributes['install-as']) . '"';
1.1       misho    82120:         }
1.1.1.2 ! misho    82121:         $ret .= ' name="' . $this->_fixXmlEncoding($file) . '"';
        !          82122:         if (empty($attributes['replacements'])) {
        !          82123:             $ret .= "/>\n";
        !          82124:         } else {
        !          82125:             $ret .= ">\n";
        !          82126:             foreach ($attributes['replacements'] as $r) {
        !          82127:                 $ret .= "$indent    <replace";
        !          82128:                 foreach ($r as $k => $v) {
        !          82129:                     $ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"';
1.1       misho    82130:                 }
1.1.1.2 ! misho    82131:                 $ret .= "/>\n";
1.1       misho    82132:             }
1.1.1.2 ! misho    82133:             $ret .= "$indent   </file>\n";
1.1       misho    82134:         }
1.1.1.2 ! misho    82135:         return $ret;
        !          82136:     }
1.1       misho    82137: 
1.1.1.2 ! misho    82138:     // {{{ _unIndent()
1.1       misho    82139: 
1.1.1.2 ! misho    82140:     /**
        !          82141:      * Unindent given string (?)
        !          82142:      *
        !          82143:      * @param string $str The string that has to be unindented.
        !          82144:      * @return string
        !          82145:      * @access private
        !          82146:      */
        !          82147:     function _unIndent($str)
        !          82148:     {
        !          82149:         // remove leading newlines
        !          82150:         $str = preg_replace('/^[\r\n]+/', '', $str);
        !          82151:         // find whitespace at the beginning of the first line
        !          82152:         $indent_len = strspn($str, " \t");
        !          82153:         $indent = substr($str, 0, $indent_len);
        !          82154:         $data = '';
        !          82155:         // remove the same amount of whitespace from following lines
        !          82156:         foreach (explode("\n", $str) as $line) {
        !          82157:             if (substr($line, 0, $indent_len) == $indent) {
        !          82158:                 $data .= substr($line, $indent_len) . "\n";
        !          82159:             }
        !          82160:         }
        !          82161:         return $data;
        !          82162:     }
1.1       misho    82163: 
1.1.1.2 ! misho    82164:     /**
        !          82165:      * @return array
        !          82166:      */
        !          82167:     function dependenciesToV2()
        !          82168:     {
        !          82169:         $arr = array();
        !          82170:         $this->_convertDependencies2_0($arr);
        !          82171:         return $arr['dependencies'];
        !          82172:     }
1.1       misho    82173: 
1.1.1.2 ! misho    82174:     /**
        !          82175:      * Convert a package.xml version 1.0 into version 2.0
        !          82176:      *
        !          82177:      * Note that this does a basic conversion, to allow more advanced
        !          82178:      * features like bundles and multiple releases
        !          82179:      * @param string the classname to instantiate and return.  This must be
        !          82180:      *               PEAR_PackageFile_v2 or a descendant
        !          82181:      * @param boolean if true, only valid, deterministic package.xml 1.0 as defined by the
        !          82182:      *                strictest parameters will be converted
        !          82183:      * @return PEAR_PackageFile_v2|PEAR_Error
        !          82184:      */
        !          82185:     function &toV2($class = 'PEAR_PackageFile_v2', $strict = false)
        !          82186:     {
        !          82187:         if ($strict) {
        !          82188:             if (!$this->_packagefile->validate()) {
        !          82189:                 $a = PEAR::raiseError('invalid package.xml version 1.0 cannot be converted' .
        !          82190:                     ' to version 2.0', null, null, null,
        !          82191:                     $this->_packagefile->getValidationWarnings(true));
        !          82192:                 return $a;
        !          82193:             }
        !          82194:         }
1.1       misho    82195: 
1.1.1.2 ! misho    82196:         $arr = array(
        !          82197:             'attribs' => array(
        !          82198:                              'version' => '2.0',
        !          82199:                              'xmlns' => 'http://pear.php.net/dtd/package-2.0',
        !          82200:                              'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
        !          82201:                              'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
        !          82202:                              'xsi:schemaLocation' => "http://pear.php.net/dtd/tasks-1.0\n" .
        !          82203: "http://pear.php.net/dtd/tasks-1.0.xsd\n" .
        !          82204: "http://pear.php.net/dtd/package-2.0\n" .
        !          82205: 'http://pear.php.net/dtd/package-2.0.xsd',
        !          82206:                          ),
        !          82207:             'name' => $this->_packagefile->getPackage(),
        !          82208:             'channel' => 'pear.php.net',
        !          82209:         );
        !          82210:         $arr['summary'] = $this->_packagefile->getSummary();
        !          82211:         $arr['description'] = $this->_packagefile->getDescription();
        !          82212:         $maintainers = $this->_packagefile->getMaintainers();
        !          82213:         foreach ($maintainers as $maintainer) {
        !          82214:             if ($maintainer['role'] != 'lead') {
        !          82215:                 continue;
        !          82216:             }
        !          82217:             $new = array(
        !          82218:                 'name' => $maintainer['name'],
        !          82219:                 'user' => $maintainer['handle'],
        !          82220:                 'email' => $maintainer['email'],
        !          82221:                 'active' => 'yes',
        !          82222:             );
        !          82223:             $arr['lead'][] = $new;
        !          82224:         }
1.1       misho    82225: 
1.1.1.2 ! misho    82226:         if (!isset($arr['lead'])) { // some people... you know?
        !          82227:             $arr['lead'] = array(
        !          82228:                 'name' => 'unknown',
        !          82229:                 'user' => 'unknown',
        !          82230:                 'email' => 'noleadmaintainer@example.com',
        !          82231:                 'active' => 'no',
        !          82232:             );
        !          82233:         }
1.1       misho    82234: 
1.1.1.2 ! misho    82235:         if (count($arr['lead']) == 1) {
        !          82236:             $arr['lead'] = $arr['lead'][0];
        !          82237:         }
1.1       misho    82238: 
1.1.1.2 ! misho    82239:         foreach ($maintainers as $maintainer) {
        !          82240:             if ($maintainer['role'] == 'lead') {
        !          82241:                 continue;
1.1       misho    82242:             }
1.1.1.2 ! misho    82243:             $new = array(
        !          82244:                 'name' => $maintainer['name'],
        !          82245:                 'user' => $maintainer['handle'],
        !          82246:                 'email' => $maintainer['email'],
        !          82247:                 'active' => 'yes',
        !          82248:             );
        !          82249:             $arr[$maintainer['role']][] = $new;
        !          82250:         }
1.1       misho    82251: 
1.1.1.2 ! misho    82252:         if (isset($arr['developer']) && count($arr['developer']) == 1) {
        !          82253:             $arr['developer'] = $arr['developer'][0];
        !          82254:         }
1.1       misho    82255: 
1.1.1.2 ! misho    82256:         if (isset($arr['contributor']) && count($arr['contributor']) == 1) {
        !          82257:             $arr['contributor'] = $arr['contributor'][0];
        !          82258:         }
1.1       misho    82259: 
1.1.1.2 ! misho    82260:         if (isset($arr['helper']) && count($arr['helper']) == 1) {
        !          82261:             $arr['helper'] = $arr['helper'][0];
        !          82262:         }
1.1       misho    82263: 
1.1.1.2 ! misho    82264:         $arr['date'] = $this->_packagefile->getDate();
        !          82265:         $arr['version'] =
        !          82266:             array(
        !          82267:                 'release' => $this->_packagefile->getVersion(),
        !          82268:                 'api' => $this->_packagefile->getVersion(),
        !          82269:             );
        !          82270:         $arr['stability'] =
        !          82271:             array(
        !          82272:                 'release' => $this->_packagefile->getState(),
        !          82273:                 'api' => $this->_packagefile->getState(),
        !          82274:             );
        !          82275:         $licensemap =
        !          82276:             array(
        !          82277:                 'php' => 'http://www.php.net/license',
        !          82278:                 'php license' => 'http://www.php.net/license',
        !          82279:                 'lgpl' => 'http://www.gnu.org/copyleft/lesser.html',
        !          82280:                 'bsd' => 'http://www.opensource.org/licenses/bsd-license.php',
        !          82281:                 'bsd style' => 'http://www.opensource.org/licenses/bsd-license.php',
        !          82282:                 'bsd-style' => 'http://www.opensource.org/licenses/bsd-license.php',
        !          82283:                 'mit' => 'http://www.opensource.org/licenses/mit-license.php',
        !          82284:                 'gpl' => 'http://www.gnu.org/copyleft/gpl.html',
        !          82285:                 'apache' => 'http://www.opensource.org/licenses/apache2.0.php'
        !          82286:             );
1.1       misho    82287: 
1.1.1.2 ! misho    82288:         if (isset($licensemap[strtolower($this->_packagefile->getLicense())])) {
        !          82289:             $arr['license'] = array(
        !          82290:                 'attribs' => array('uri' =>
        !          82291:                     $licensemap[strtolower($this->_packagefile->getLicense())]),
        !          82292:                 '_content' => $this->_packagefile->getLicense()
        !          82293:                 );
        !          82294:         } else {
        !          82295:             // don't use bogus uri
        !          82296:             $arr['license'] = $this->_packagefile->getLicense();
        !          82297:         }
1.1       misho    82298: 
1.1.1.2 ! misho    82299:         $arr['notes'] = $this->_packagefile->getNotes();
        !          82300:         $temp = array();
        !          82301:         $arr['contents'] = $this->_convertFilelist2_0($temp);
        !          82302:         $this->_convertDependencies2_0($arr);
        !          82303:         $release = ($this->_packagefile->getConfigureOptions() || $this->_isExtension) ?
        !          82304:             'extsrcrelease' : 'phprelease';
        !          82305:         if ($release == 'extsrcrelease') {
        !          82306:             $arr['channel'] = 'pecl.php.net';
        !          82307:             $arr['providesextension'] = $arr['name']; // assumption
        !          82308:         }
1.1       misho    82309: 
1.1.1.2 ! misho    82310:         $arr[$release] = array();
        !          82311:         if ($this->_packagefile->getConfigureOptions()) {
        !          82312:             $arr[$release]['configureoption'] = $this->_packagefile->getConfigureOptions();
        !          82313:             foreach ($arr[$release]['configureoption'] as $i => $opt) {
        !          82314:                 $arr[$release]['configureoption'][$i] = array('attribs' => $opt);
        !          82315:             }
        !          82316:             if (count($arr[$release]['configureoption']) == 1) {
        !          82317:                 $arr[$release]['configureoption'] = $arr[$release]['configureoption'][0];
1.1       misho    82318:             }
                   82319:         }
                   82320: 
1.1.1.2 ! misho    82321:         $this->_convertRelease2_0($arr[$release], $temp);
        !          82322:         if ($release == 'extsrcrelease' && count($arr[$release]) > 1) {
        !          82323:             // multiple extsrcrelease tags added in PEAR 1.4.1
        !          82324:             $arr['dependencies']['required']['pearinstaller']['min'] = '1.4.1';
1.1       misho    82325:         }
                   82326: 
1.1.1.2 ! misho    82327:         if ($cl = $this->_packagefile->getChangelog()) {
        !          82328:             foreach ($cl as $release) {
        !          82329:                 $rel = array();
        !          82330:                 $rel['version'] =
        !          82331:                     array(
        !          82332:                         'release' => $release['version'],
        !          82333:                         'api' => $release['version'],
        !          82334:                     );
        !          82335:                 if (!isset($release['release_state'])) {
        !          82336:                     $release['release_state'] = 'stable';
        !          82337:                 }
1.1       misho    82338: 
1.1.1.2 ! misho    82339:                 $rel['stability'] =
        !          82340:                     array(
        !          82341:                         'release' => $release['release_state'],
        !          82342:                         'api' => $release['release_state'],
        !          82343:                     );
        !          82344:                 if (isset($release['release_date'])) {
        !          82345:                     $rel['date'] = $release['release_date'];
        !          82346:                 } else {
        !          82347:                     $rel['date'] = date('Y-m-d');
        !          82348:                 }
1.1       misho    82349: 
1.1.1.2 ! misho    82350:                 if (isset($release['release_license'])) {
        !          82351:                     if (isset($licensemap[strtolower($release['release_license'])])) {
        !          82352:                         $uri = $licensemap[strtolower($release['release_license'])];
        !          82353:                     } else {
        !          82354:                         $uri = 'http://www.example.com';
        !          82355:                     }
        !          82356:                     $rel['license'] = array(
        !          82357:                             'attribs' => array('uri' => $uri),
        !          82358:                             '_content' => $release['release_license']
        !          82359:                         );
        !          82360:                 } else {
        !          82361:                     $rel['license'] = $arr['license'];
        !          82362:                 }
        !          82363: 
        !          82364:                 if (!isset($release['release_notes'])) {
        !          82365:                     $release['release_notes'] = 'no release notes';
        !          82366:                 }
        !          82367: 
        !          82368:                 $rel['notes'] = $release['release_notes'];
        !          82369:                 $arr['changelog']['release'][] = $rel;
        !          82370:             }
1.1       misho    82371:         }
                   82372: 
1.1.1.2 ! misho    82373:         $ret = new $class;
        !          82374:         $ret->setConfig($this->_packagefile->_config);
        !          82375:         if (isset($this->_packagefile->_logger) && is_object($this->_packagefile->_logger)) {
        !          82376:             $ret->setLogger($this->_packagefile->_logger);
1.1       misho    82377:         }
1.1.1.2 ! misho    82378: 
        !          82379:         $ret->fromArray($arr);
        !          82380:         return $ret;
1.1       misho    82381:     }
                   82382: 
1.1.1.2 ! misho    82383:     /**
        !          82384:      * @param array
        !          82385:      * @param bool
        !          82386:      * @access private
        !          82387:      */
        !          82388:     function _convertDependencies2_0(&$release, $internal = false)
1.1       misho    82389:     {
1.1.1.2 ! misho    82390:         $peardep = array('pearinstaller' =>
        !          82391:             array('min' => '1.4.0b1')); // this is a lot safer
        !          82392:         $required = $optional = array();
        !          82393:         $release['dependencies'] = array('required' => array());
        !          82394:         if ($this->_packagefile->hasDeps()) {
        !          82395:             foreach ($this->_packagefile->getDeps() as $dep) {
        !          82396:                 if (!isset($dep['optional']) || $dep['optional'] == 'no') {
        !          82397:                     $required[] = $dep;
        !          82398:                 } else {
        !          82399:                     $optional[] = $dep;
        !          82400:                 }
        !          82401:             }
        !          82402:             foreach (array('required', 'optional') as $arr) {
        !          82403:                 $deps = array();
        !          82404:                 foreach ($$arr as $dep) {
        !          82405:                     // organize deps by dependency type and name
        !          82406:                     if (!isset($deps[$dep['type']])) {
        !          82407:                         $deps[$dep['type']] = array();
1.1       misho    82408:                     }
1.1.1.2 ! misho    82409:                     if (isset($dep['name'])) {
        !          82410:                         $deps[$dep['type']][$dep['name']][] = $dep;
        !          82411:                     } else {
        !          82412:                         $deps[$dep['type']][] = $dep;
1.1       misho    82413:                     }
1.1.1.2 ! misho    82414:                 }
        !          82415:                 do {
        !          82416:                     if (isset($deps['php'])) {
        !          82417:                         $php = array();
        !          82418:                         if (count($deps['php']) > 1) {
        !          82419:                             $php = $this->_processPhpDeps($deps['php']);
1.1       misho    82420:                         } else {
1.1.1.2 ! misho    82421:                             if (!isset($deps['php'][0])) {
        !          82422:                                 list($key, $blah) = each ($deps['php']); // stupid buggy versions
        !          82423:                                 $deps['php'] = array($blah[0]);
1.1       misho    82424:                             }
1.1.1.2 ! misho    82425:                             $php = $this->_processDep($deps['php'][0]);
        !          82426:                             if (!$php) {
        !          82427:                                 break; // poor mans throw
1.1       misho    82428:                             }
                   82429:                         }
1.1.1.2 ! misho    82430:                         $release['dependencies'][$arr]['php'] = $php;
1.1       misho    82431:                     }
1.1.1.2 ! misho    82432:                 } while (false);
        !          82433:                 do {
        !          82434:                     if (isset($deps['pkg'])) {
        !          82435:                         $pkg = array();
        !          82436:                         $pkg = $this->_processMultipleDepsName($deps['pkg']);
        !          82437:                         if (!$pkg) {
        !          82438:                             break; // poor mans throw
        !          82439:                         }
        !          82440:                         $release['dependencies'][$arr]['package'] = $pkg;
        !          82441:                     }
        !          82442:                 } while (false);
        !          82443:                 do {
        !          82444:                     if (isset($deps['ext'])) {
        !          82445:                         $pkg = array();
        !          82446:                         $pkg = $this->_processMultipleDepsName($deps['ext']);
        !          82447:                         $release['dependencies'][$arr]['extension'] = $pkg;
        !          82448:                     }
        !          82449:                 } while (false);
        !          82450:                 // skip sapi - it's not supported so nobody will have used it
        !          82451:                 // skip os - it's not supported in 1.0
1.1       misho    82452:             }
                   82453:         }
1.1.1.2 ! misho    82454:         if (isset($release['dependencies']['required'])) {
        !          82455:             $release['dependencies']['required'] =
        !          82456:                 array_merge($peardep, $release['dependencies']['required']);
        !          82457:         } else {
        !          82458:             $release['dependencies']['required'] = $peardep;
        !          82459:         }
        !          82460:         if (!isset($release['dependencies']['required']['php'])) {
        !          82461:             $release['dependencies']['required']['php'] =
        !          82462:                 array('min' => '4.0.0');
        !          82463:         }
        !          82464:         $order = array();
        !          82465:         $bewm = $release['dependencies']['required'];
        !          82466:         $order['php'] = $bewm['php'];
        !          82467:         $order['pearinstaller'] = $bewm['pearinstaller'];
        !          82468:         isset($bewm['package']) ? $order['package'] = $bewm['package'] :0;
        !          82469:         isset($bewm['extension']) ? $order['extension'] = $bewm['extension'] :0;
        !          82470:         $release['dependencies']['required'] = $order;
        !          82471:     }
1.1       misho    82472: 
1.1.1.2 ! misho    82473:     /**
        !          82474:      * @param array
        !          82475:      * @access private
        !          82476:      */
        !          82477:     function _convertFilelist2_0(&$package)
        !          82478:     {
        !          82479:         $ret = array('dir' =>
        !          82480:                     array(
        !          82481:                         'attribs' => array('name' => '/'),
        !          82482:                         'file' => array()
        !          82483:                         )
        !          82484:                     );
        !          82485:         $package['platform'] =
        !          82486:         $package['install-as'] = array();
        !          82487:         $this->_isExtension = false;
        !          82488:         foreach ($this->_packagefile->getFilelist() as $name => $file) {
        !          82489:             $file['name'] = $name;
        !          82490:             if (isset($file['role']) && $file['role'] == 'src') {
        !          82491:                 $this->_isExtension = true;
1.1       misho    82492:             }
1.1.1.2 ! misho    82493:             if (isset($file['replacements'])) {
        !          82494:                 $repl = $file['replacements'];
        !          82495:                 unset($file['replacements']);
        !          82496:             } else {
        !          82497:                 unset($repl);
        !          82498:             }
        !          82499:             if (isset($file['install-as'])) {
        !          82500:                 $package['install-as'][$name] = $file['install-as'];
        !          82501:                 unset($file['install-as']);
        !          82502:             }
        !          82503:             if (isset($file['platform'])) {
        !          82504:                 $package['platform'][$name] = $file['platform'];
        !          82505:                 unset($file['platform']);
        !          82506:             }
        !          82507:             $file = array('attribs' => $file);
        !          82508:             if (isset($repl)) {
        !          82509:                 foreach ($repl as $replace ) {
        !          82510:                     $file['tasks:replace'][] = array('attribs' => $replace);
        !          82511:                 }
        !          82512:                 if (count($repl) == 1) {
        !          82513:                     $file['tasks:replace'] = $file['tasks:replace'][0];
        !          82514:                 }
1.1       misho    82515:             }
1.1.1.2 ! misho    82516:             $ret['dir']['file'][] = $file;
1.1       misho    82517:         }
1.1.1.2 ! misho    82518:         return $ret;
        !          82519:     }
1.1       misho    82520: 
1.1.1.2 ! misho    82521:     /**
        !          82522:      * Post-process special files with install-as/platform attributes and
        !          82523:      * make the release tag.
        !          82524:      *
        !          82525:      * This complex method follows this work-flow to create the release tags:
        !          82526:      *
        !          82527:      * <pre>
        !          82528:      * - if any install-as/platform exist, create a generic release and fill it with
        !          82529:      *   o <install as=..> tags for <file name=... install-as=...>
        !          82530:      *   o <install as=..> tags for <file name=... platform=!... install-as=..>
        !          82531:      *   o <ignore> tags for <file name=... platform=...>
        !          82532:      *   o <ignore> tags for <file name=... platform=... install-as=..>
        !          82533:      * - create a release for each platform encountered and fill with
        !          82534:      *   o <install as..> tags for <file name=... install-as=...>
        !          82535:      *   o <install as..> tags for <file name=... platform=this platform install-as=..>
        !          82536:      *   o <install as..> tags for <file name=... platform=!other platform install-as=..>
        !          82537:      *   o <ignore> tags for <file name=... platform=!this platform>
        !          82538:      *   o <ignore> tags for <file name=... platform=other platform>
        !          82539:      *   o <ignore> tags for <file name=... platform=other platform install-as=..>
        !          82540:      *   o <ignore> tags for <file name=... platform=!this platform install-as=..>
        !          82541:      * </pre>
        !          82542:      *
        !          82543:      * It does this by accessing the $package parameter, which contains an array with
        !          82544:      * indices:
        !          82545:      *
        !          82546:      *  - platform: mapping of file => OS the file should be installed on
        !          82547:      *  - install-as: mapping of file => installed name
        !          82548:      *  - osmap: mapping of OS => list of files that should be installed
        !          82549:      *    on that OS
        !          82550:      *  - notosmap: mapping of OS => list of files that should not be
        !          82551:      *    installed on that OS
        !          82552:      *
        !          82553:      * @param array
        !          82554:      * @param array
        !          82555:      * @access private
        !          82556:      */
        !          82557:     function _convertRelease2_0(&$release, $package)
        !          82558:     {
        !          82559:         //- if any install-as/platform exist, create a generic release and fill it with
        !          82560:         if (count($package['platform']) || count($package['install-as'])) {
        !          82561:             $generic = array();
        !          82562:             $genericIgnore = array();
        !          82563:             foreach ($package['install-as'] as $file => $as) {
        !          82564:                 //o <install as=..> tags for <file name=... install-as=...>
        !          82565:                 if (!isset($package['platform'][$file])) {
        !          82566:                     $generic[] = $file;
        !          82567:                     continue;
        !          82568:                 }
        !          82569:                 //o <install as=..> tags for <file name=... platform=!... install-as=..>
        !          82570:                 if (isset($package['platform'][$file]) &&
        !          82571:                       $package['platform'][$file]{0} == '!') {
        !          82572:                     $generic[] = $file;
        !          82573:                     continue;
        !          82574:                 }
        !          82575:                 //o <ignore> tags for <file name=... platform=... install-as=..>
        !          82576:                 if (isset($package['platform'][$file]) &&
        !          82577:                       $package['platform'][$file]{0} != '!') {
        !          82578:                     $genericIgnore[] = $file;
        !          82579:                     continue;
        !          82580:                 }
1.1       misho    82581:             }
1.1.1.2 ! misho    82582:             foreach ($package['platform'] as $file => $platform) {
        !          82583:                 if (isset($package['install-as'][$file])) {
        !          82584:                     continue;
        !          82585:                 }
        !          82586:                 if ($platform{0} != '!') {
        !          82587:                     //o <ignore> tags for <file name=... platform=...>
        !          82588:                     $genericIgnore[] = $file;
        !          82589:                 }
        !          82590:             }
        !          82591:             if (count($package['platform'])) {
        !          82592:                 $oses = $notplatform = $platform = array();
        !          82593:                 foreach ($package['platform'] as $file => $os) {
        !          82594:                     // get a list of oses
        !          82595:                     if ($os{0} == '!') {
        !          82596:                         if (isset($oses[substr($os, 1)])) {
        !          82597:                             continue;
        !          82598:                         }
        !          82599:                         $oses[substr($os, 1)] = count($oses);
        !          82600:                     } else {
        !          82601:                         if (isset($oses[$os])) {
        !          82602:                             continue;
        !          82603:                         }
        !          82604:                         $oses[$os] = count($oses);
1.1       misho    82605:                     }
1.1.1.2 ! misho    82606:                 }
        !          82607:                 //- create a release for each platform encountered and fill with
        !          82608:                 foreach ($oses as $os => $releaseNum) {
        !          82609:                     $release[$releaseNum]['installconditions']['os']['name'] = $os;
        !          82610:                     $release[$releaseNum]['filelist'] = array('install' => array(),
        !          82611:                         'ignore' => array());
        !          82612:                     foreach ($package['install-as'] as $file => $as) {
        !          82613:                         //o <install as=..> tags for <file name=... install-as=...>
        !          82614:                         if (!isset($package['platform'][$file])) {
        !          82615:                             $release[$releaseNum]['filelist']['install'][] =
        !          82616:                                 array(
        !          82617:                                     'attribs' => array(
        !          82618:                                         'name' => $file,
        !          82619:                                         'as' => $as,
        !          82620:                                     ),
        !          82621:                                 );
        !          82622:                             continue;
1.1       misho    82623:                         }
1.1.1.2 ! misho    82624:                         //o <install as..> tags for
        !          82625:                         //  <file name=... platform=this platform install-as=..>
        !          82626:                         if (isset($package['platform'][$file]) &&
        !          82627:                               $package['platform'][$file] == $os) {
        !          82628:                             $release[$releaseNum]['filelist']['install'][] =
        !          82629:                                 array(
        !          82630:                                     'attribs' => array(
        !          82631:                                         'name' => $file,
        !          82632:                                         'as' => $as,
        !          82633:                                     ),
        !          82634:                                 );
        !          82635:                             continue;
1.1       misho    82636:                         }
1.1.1.2 ! misho    82637:                         //o <install as..> tags for
        !          82638:                         //  <file name=... platform=!other platform install-as=..>
        !          82639:                         if (isset($package['platform'][$file]) &&
        !          82640:                               $package['platform'][$file] != "!$os" &&
        !          82641:                               $package['platform'][$file]{0} == '!') {
        !          82642:                             $release[$releaseNum]['filelist']['install'][] =
        !          82643:                                 array(
        !          82644:                                     'attribs' => array(
        !          82645:                                         'name' => $file,
        !          82646:                                         'as' => $as,
        !          82647:                                     ),
        !          82648:                                 );
        !          82649:                             continue;
        !          82650:                         }
        !          82651:                         //o <ignore> tags for
        !          82652:                         //  <file name=... platform=!this platform install-as=..>
        !          82653:                         if (isset($package['platform'][$file]) &&
        !          82654:                               $package['platform'][$file] == "!$os") {
        !          82655:                             $release[$releaseNum]['filelist']['ignore'][] =
        !          82656:                                 array(
        !          82657:                                     'attribs' => array(
        !          82658:                                         'name' => $file,
        !          82659:                                     ),
        !          82660:                                 );
        !          82661:                             continue;
        !          82662:                         }
        !          82663:                         //o <ignore> tags for
        !          82664:                         //  <file name=... platform=other platform install-as=..>
        !          82665:                         if (isset($package['platform'][$file]) &&
        !          82666:                               $package['platform'][$file]{0} != '!' &&
        !          82667:                               $package['platform'][$file] != $os) {
        !          82668:                             $release[$releaseNum]['filelist']['ignore'][] =
        !          82669:                                 array(
        !          82670:                                     'attribs' => array(
        !          82671:                                         'name' => $file,
        !          82672:                                     ),
        !          82673:                                 );
        !          82674:                             continue;
1.1       misho    82675:                         }
                   82676:                     }
1.1.1.2 ! misho    82677:                     foreach ($package['platform'] as $file => $platform) {
        !          82678:                         if (isset($package['install-as'][$file])) {
        !          82679:                             continue;
        !          82680:                         }
        !          82681:                         //o <ignore> tags for <file name=... platform=!this platform>
        !          82682:                         if ($platform == "!$os") {
        !          82683:                             $release[$releaseNum]['filelist']['ignore'][] =
        !          82684:                                 array(
        !          82685:                                     'attribs' => array(
        !          82686:                                         'name' => $file,
        !          82687:                                     ),
        !          82688:                                 );
        !          82689:                             continue;
        !          82690:                         }
        !          82691:                         //o <ignore> tags for <file name=... platform=other platform>
        !          82692:                         if ($platform{0} != '!' && $platform != $os) {
        !          82693:                             $release[$releaseNum]['filelist']['ignore'][] =
        !          82694:                                 array(
        !          82695:                                     'attribs' => array(
        !          82696:                                         'name' => $file,
        !          82697:                                     ),
        !          82698:                                 );
        !          82699:                         }
1.1       misho    82700:                     }
1.1.1.2 ! misho    82701:                     if (!count($release[$releaseNum]['filelist']['install'])) {
        !          82702:                         unset($release[$releaseNum]['filelist']['install']);
1.1       misho    82703:                     }
1.1.1.2 ! misho    82704:                     if (!count($release[$releaseNum]['filelist']['ignore'])) {
        !          82705:                         unset($release[$releaseNum]['filelist']['ignore']);
1.1       misho    82706:                     }
1.1.1.2 ! misho    82707:                 }
        !          82708:                 if (count($generic) || count($genericIgnore)) {
        !          82709:                     $release[count($oses)] = array();
        !          82710:                     if (count($generic)) {
        !          82711:                         foreach ($generic as $file) {
        !          82712:                             if (isset($package['install-as'][$file])) {
        !          82713:                                 $installas = $package['install-as'][$file];
        !          82714:                             } else {
        !          82715:                                 $installas = $file;
1.1       misho    82716:                             }
1.1.1.2 ! misho    82717:                             $release[count($oses)]['filelist']['install'][] =
        !          82718:                                 array(
        !          82719:                                     'attribs' => array(
        !          82720:                                         'name' => $file,
        !          82721:                                         'as' => $installas,
        !          82722:                                     )
        !          82723:                                 );
        !          82724:                         }
1.1       misho    82725:                     }
1.1.1.2 ! misho    82726:                     if (count($genericIgnore)) {
        !          82727:                         foreach ($genericIgnore as $file) {
        !          82728:                             $release[count($oses)]['filelist']['ignore'][] =
        !          82729:                                 array(
        !          82730:                                     'attribs' => array(
        !          82731:                                         'name' => $file,
        !          82732:                                     )
        !          82733:                                 );
1.1       misho    82734:                         }
                   82735:                     }
1.1.1.2 ! misho    82736:                 }
        !          82737:                 // cleanup
        !          82738:                 foreach ($release as $i => $rel) {
        !          82739:                     if (isset($rel['filelist']['install']) &&
        !          82740:                           count($rel['filelist']['install']) == 1) {
        !          82741:                         $release[$i]['filelist']['install'] =
        !          82742:                             $release[$i]['filelist']['install'][0];
        !          82743:                     }
        !          82744:                     if (isset($rel['filelist']['ignore']) &&
        !          82745:                           count($rel['filelist']['ignore']) == 1) {
        !          82746:                         $release[$i]['filelist']['ignore'] =
        !          82747:                             $release[$i]['filelist']['ignore'][0];
        !          82748:                     }
        !          82749:                 }
        !          82750:                 if (count($release) == 1) {
        !          82751:                     $release = $release[0];
        !          82752:                 }
        !          82753:             } else {
        !          82754:                 // no platform atts, but some install-as atts
        !          82755:                 foreach ($package['install-as'] as $file => $value) {
        !          82756:                     $release['filelist']['install'][] =
        !          82757:                         array(
        !          82758:                             'attribs' => array(
        !          82759:                                 'name' => $file,
        !          82760:                                 'as' => $value
        !          82761:                             )
        !          82762:                         );
        !          82763:                 }
        !          82764:                 if (count($release['filelist']['install']) == 1) {
        !          82765:                     $release['filelist']['install'] = $release['filelist']['install'][0];
        !          82766:                 }
1.1       misho    82767:             }
                   82768:         }
                   82769:     }
                   82770: 
1.1.1.2 ! misho    82771:     /**
        !          82772:      * @param array
        !          82773:      * @return array
        !          82774:      * @access private
        !          82775:      */
        !          82776:     function _processDep($dep)
1.1       misho    82777:     {
1.1.1.2 ! misho    82778:         if ($dep['type'] == 'php') {
        !          82779:             if ($dep['rel'] == 'has') {
        !          82780:                 // come on - everyone has php!
        !          82781:                 return false;
        !          82782:             }
        !          82783:         }
        !          82784:         $php = array();
        !          82785:         if ($dep['type'] != 'php') {
        !          82786:             $php['name'] = $dep['name'];
        !          82787:             if ($dep['type'] == 'pkg') {
        !          82788:                 $php['channel'] = 'pear.php.net';
        !          82789:             }
        !          82790:         }
        !          82791:         switch ($dep['rel']) {
        !          82792:             case 'gt' :
        !          82793:                 $php['min'] = $dep['version'];
        !          82794:                 $php['exclude'] = $dep['version'];
        !          82795:             break;
        !          82796:             case 'ge' :
        !          82797:                 if (!isset($dep['version'])) {
        !          82798:                     if ($dep['type'] == 'php') {
        !          82799:                         if (isset($dep['name'])) {
        !          82800:                             $dep['version'] = $dep['name'];
1.1       misho    82801:                         }
                   82802:                     }
1.1.1.2 ! misho    82803:                 }
        !          82804:                 $php['min'] = $dep['version'];
        !          82805:             break;
        !          82806:             case 'lt' :
        !          82807:                 $php['max'] = $dep['version'];
        !          82808:                 $php['exclude'] = $dep['version'];
        !          82809:             break;
        !          82810:             case 'le' :
        !          82811:                 $php['max'] = $dep['version'];
        !          82812:             break;
        !          82813:             case 'eq' :
        !          82814:                 $php['min'] = $dep['version'];
        !          82815:                 $php['max'] = $dep['version'];
        !          82816:             break;
        !          82817:             case 'ne' :
        !          82818:                 $php['exclude'] = $dep['version'];
        !          82819:             break;
        !          82820:             case 'not' :
        !          82821:                 $php['conflicts'] = 'yes';
        !          82822:             break;
1.1       misho    82823:         }
1.1.1.2 ! misho    82824:         return $php;
1.1       misho    82825:     }
                   82826: 
1.1.1.2 ! misho    82827:     /**
        !          82828:      * @param array
        !          82829:      * @return array
        !          82830:      */
        !          82831:     function _processPhpDeps($deps)
1.1       misho    82832:     {
1.1.1.2 ! misho    82833:         $test = array();
        !          82834:         foreach ($deps as $dep) {
        !          82835:             $test[] = $this->_processDep($dep);
        !          82836:         }
        !          82837:         $min = array();
        !          82838:         $max = array();
        !          82839:         foreach ($test as $dep) {
        !          82840:             if (!$dep) {
        !          82841:                 continue;
        !          82842:             }
        !          82843:             if (isset($dep['min'])) {
        !          82844:                 $min[$dep['min']] = count($min);
        !          82845:             }
        !          82846:             if (isset($dep['max'])) {
        !          82847:                 $max[$dep['max']] = count($max);
        !          82848:             }
        !          82849:         }
        !          82850:         if (count($min) > 0) {
        !          82851:             uksort($min, 'version_compare');
        !          82852:         }
        !          82853:         if (count($max) > 0) {
        !          82854:             uksort($max, 'version_compare');
        !          82855:         }
        !          82856:         if (count($min)) {
        !          82857:             // get the highest minimum
        !          82858:             $min = array_pop($a = array_flip($min));
        !          82859:         } else {
        !          82860:             $min = false;
        !          82861:         }
        !          82862:         if (count($max)) {
        !          82863:             // get the lowest maximum
        !          82864:             $max = array_shift($a = array_flip($max));
        !          82865:         } else {
        !          82866:             $max = false;
        !          82867:         }
        !          82868:         if ($min) {
        !          82869:             $php['min'] = $min;
        !          82870:         }
        !          82871:         if ($max) {
        !          82872:             $php['max'] = $max;
        !          82873:         }
        !          82874:         $exclude = array();
        !          82875:         foreach ($test as $dep) {
        !          82876:             if (!isset($dep['exclude'])) {
        !          82877:                 continue;
        !          82878:             }
        !          82879:             $exclude[] = $dep['exclude'];
        !          82880:         }
        !          82881:         if (count($exclude)) {
        !          82882:             $php['exclude'] = $exclude;
        !          82883:         }
        !          82884:         return $php;
1.1       misho    82885:     }
                   82886: 
                   82887:     /**
1.1.1.2 ! misho    82888:      * process multiple dependencies that have a name, like package deps
        !          82889:      * @param array
        !          82890:      * @return array
        !          82891:      * @access private
1.1       misho    82892:      */
1.1.1.2 ! misho    82893:     function _processMultipleDepsName($deps)
1.1       misho    82894:     {
1.1.1.2 ! misho    82895:         $ret = $tests = array();
        !          82896:         foreach ($deps as $name => $dep) {
        !          82897:             foreach ($dep as $d) {
        !          82898:                 $tests[$name][] = $this->_processDep($d);
        !          82899:             }
        !          82900:         }
1.1       misho    82901: 
1.1.1.2 ! misho    82902:         foreach ($tests as $name => $test) {
        !          82903:             $max = $min = $php = array();
        !          82904:             $php['name'] = $name;
        !          82905:             foreach ($test as $dep) {
        !          82906:                 if (!$dep) {
        !          82907:                     continue;
        !          82908:                 }
        !          82909:                 if (isset($dep['channel'])) {
        !          82910:                     $php['channel'] = 'pear.php.net';
        !          82911:                 }
        !          82912:                 if (isset($dep['conflicts']) && $dep['conflicts'] == 'yes') {
        !          82913:                     $php['conflicts'] = 'yes';
        !          82914:                 }
        !          82915:                 if (isset($dep['min'])) {
        !          82916:                     $min[$dep['min']] = count($min);
        !          82917:                 }
        !          82918:                 if (isset($dep['max'])) {
        !          82919:                     $max[$dep['max']] = count($max);
1.1       misho    82920:                 }
                   82921:             }
1.1.1.2 ! misho    82922:             if (count($min) > 0) {
        !          82923:                 uksort($min, 'version_compare');
        !          82924:             }
        !          82925:             if (count($max) > 0) {
        !          82926:                 uksort($max, 'version_compare');
        !          82927:             }
        !          82928:             if (count($min)) {
        !          82929:                 // get the highest minimum
        !          82930:                 $min = array_pop($a = array_flip($min));
        !          82931:             } else {
        !          82932:                 $min = false;
        !          82933:             }
        !          82934:             if (count($max)) {
        !          82935:                 // get the lowest maximum
        !          82936:                 $max = array_shift($a = array_flip($max));
        !          82937:             } else {
        !          82938:                 $max = false;
        !          82939:             }
        !          82940:             if ($min) {
        !          82941:                 $php['min'] = $min;
        !          82942:             }
        !          82943:             if ($max) {
        !          82944:                 $php['max'] = $max;
        !          82945:             }
        !          82946:             $exclude = array();
        !          82947:             foreach ($test as $dep) {
        !          82948:                 if (!isset($dep['exclude'])) {
        !          82949:                     continue;
        !          82950:                 }
        !          82951:                 $exclude[] = $dep['exclude'];
        !          82952:             }
        !          82953:             if (count($exclude)) {
        !          82954:                 $php['exclude'] = $exclude;
        !          82955:             }
        !          82956:             $ret[] = $php;
1.1       misho    82957:         }
1.1.1.2 ! misho    82958:         return $ret;
1.1       misho    82959:     }
1.1.1.2 ! misho    82960: }
        !          82961: ?><?php
        !          82962: /**
        !          82963:  * package.xml generation class, package.xml version 2.0
        !          82964:  *
        !          82965:  * PHP versions 4 and 5
        !          82966:  *
        !          82967:  * @category   pear
        !          82968:  * @package    PEAR
        !          82969:  * @author     Greg Beaver <cellog@php.net>
        !          82970:  * @author     Stephan Schmidt (original XML_Serializer code)
        !          82971:  * @copyright  1997-2009 The Authors
        !          82972:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          82973:  * @version    CVS: $Id: v2.php 313023 2011-07-06 19:17:11Z dufuz $
        !          82974:  * @link       http://pear.php.net/package/PEAR
        !          82975:  * @since      File available since Release 1.4.0a1
        !          82976:  */
        !          82977: /**
        !          82978:  * file/dir manipulation routines
        !          82979:  */
        !          82980: require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
        !          82981: require_once 'phar://install-pear-nozlib.phar/' . 'XML/Util.php';
        !          82982: 
        !          82983: /**
        !          82984:  * This class converts a PEAR_PackageFile_v2 object into any output format.
        !          82985:  *
        !          82986:  * Supported output formats include array, XML string (using S. Schmidt's
        !          82987:  * XML_Serializer, slightly customized)
        !          82988:  * @category   pear
        !          82989:  * @package    PEAR
        !          82990:  * @author     Greg Beaver <cellog@php.net>
        !          82991:  * @author     Stephan Schmidt (original XML_Serializer code)
        !          82992:  * @copyright  1997-2009 The Authors
        !          82993:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          82994:  * @version    Release: 1.9.4
        !          82995:  * @link       http://pear.php.net/package/PEAR
        !          82996:  * @since      Class available since Release 1.4.0a1
        !          82997:  */
        !          82998: class PEAR_PackageFile_Generator_v2
        !          82999: {
        !          83000:    /**
        !          83001:     * default options for the serialization
        !          83002:     * @access private
        !          83003:     * @var array $_defaultOptions
        !          83004:     */
        !          83005:     var $_defaultOptions = array(
        !          83006:         'indent'             => ' ',                    // string used for indentation
        !          83007:         'linebreak'          => "\n",                  // string used for newlines
        !          83008:         'typeHints'          => false,                 // automatically add type hin attributes
        !          83009:         'addDecl'            => true,                 // add an XML declaration
        !          83010:         'defaultTagName'     => 'XML_Serializer_Tag',  // tag used for indexed arrays or invalid names
        !          83011:         'classAsTagName'     => false,                 // use classname for objects in indexed arrays
        !          83012:         'keyAttribute'       => '_originalKey',        // attribute where original key is stored
        !          83013:         'typeAttribute'      => '_type',               // attribute for type (only if typeHints => true)
        !          83014:         'classAttribute'     => '_class',              // attribute for class of objects (only if typeHints => true)
        !          83015:         'scalarAsAttributes' => false,                 // scalar values (strings, ints,..) will be serialized as attribute
        !          83016:         'prependAttributes'  => '',                    // prepend string for attributes
        !          83017:         'indentAttributes'   => false,                 // indent the attributes, if set to '_auto', it will indent attributes so they all start at the same column
        !          83018:         'mode'               => 'simplexml',             // use 'simplexml' to use parent name as tagname if transforming an indexed array
        !          83019:         'addDoctype'         => false,                 // add a doctype declaration
        !          83020:         'doctype'            => null,                  // supply a string or an array with id and uri ({@see XML_Util::getDoctypeDeclaration()}
        !          83021:         'rootName'           => 'package',                  // name of the root tag
        !          83022:         'rootAttributes'     => array(
        !          83023:             'version' => '2.0',
        !          83024:             'xmlns' => 'http://pear.php.net/dtd/package-2.0',
        !          83025:             'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
        !          83026:             'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
        !          83027:             'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
        !          83028: http://pear.php.net/dtd/tasks-1.0.xsd
        !          83029: http://pear.php.net/dtd/package-2.0
        !          83030: http://pear.php.net/dtd/package-2.0.xsd',
        !          83031:         ),               // attributes of the root tag
        !          83032:         'attributesArray'    => 'attribs',                  // all values in this key will be treated as attributes
        !          83033:         'contentName'        => '_content',                   // this value will be used directly as content, instead of creating a new tag, may only be used in conjuction with attributesArray
        !          83034:         'beautifyFilelist'   => false,
        !          83035:         'encoding' => 'UTF-8',
        !          83036:     );
        !          83037: 
        !          83038:    /**
        !          83039:     * options for the serialization
        !          83040:     * @access private
        !          83041:     * @var array $options
        !          83042:     */
        !          83043:     var $options = array();
        !          83044: 
        !          83045:    /**
        !          83046:     * current tag depth
        !          83047:     * @var integer $_tagDepth
        !          83048:     */
        !          83049:     var $_tagDepth = 0;
1.1       misho    83050: 
1.1.1.2 ! misho    83051:    /**
        !          83052:     * serilialized representation of the data
        !          83053:     * @var string $_serializedData
        !          83054:     */
        !          83055:     var $_serializedData = null;
1.1       misho    83056:     /**
1.1.1.2 ! misho    83057:      * @var PEAR_PackageFile_v2
1.1       misho    83058:      */
1.1.1.2 ! misho    83059:     var $_packagefile;
        !          83060:     /**
        !          83061:      * @param PEAR_PackageFile_v2
        !          83062:      */
        !          83063:     function PEAR_PackageFile_Generator_v2(&$packagefile)
1.1       misho    83064:     {
1.1.1.2 ! misho    83065:         $this->_packagefile = &$packagefile;
        !          83066:         if (isset($this->_packagefile->encoding)) {
        !          83067:             $this->_defaultOptions['encoding'] = $this->_packagefile->encoding;
1.1       misho    83068:         }
                   83069:     }
                   83070: 
                   83071:     /**
1.1.1.2 ! misho    83072:      * @return string
1.1       misho    83073:      */
1.1.1.2 ! misho    83074:     function getPackagerVersion()
1.1       misho    83075:     {
1.1.1.2 ! misho    83076:         return '1.9.4';
1.1       misho    83077:     }
                   83078: 
1.1.1.2 ! misho    83079:     /**
        !          83080:      * @param PEAR_Packager
        !          83081:      * @param bool generate a .tgz or a .tar
        !          83082:      * @param string|null temporary directory to package in
        !          83083:      */
        !          83084:     function toTgz(&$packager, $compress = true, $where = null)
1.1       misho    83085:     {
1.1.1.2 ! misho    83086:         $a = null;
        !          83087:         return $this->toTgz2($packager, $a, $compress, $where);
1.1       misho    83088:     }
                   83089: 
                   83090:     /**
1.1.1.2 ! misho    83091:      * Package up both a package.xml and package2.xml for the same release
        !          83092:      * @param PEAR_Packager
        !          83093:      * @param PEAR_PackageFile_v1
        !          83094:      * @param bool generate a .tgz or a .tar
        !          83095:      * @param string|null temporary directory to package in
1.1       misho    83096:      */
1.1.1.2 ! misho    83097:     function toTgz2(&$packager, &$pf1, $compress = true, $where = null)
1.1       misho    83098:     {
1.1.1.2 ! misho    83099:         require_once 'phar://install-pear-nozlib.phar/' . 'Archive/Tar.php';
        !          83100:         if (!$this->_packagefile->isEquivalent($pf1)) {
        !          83101:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' .
        !          83102:                 basename($pf1->getPackageFile()) .
        !          83103:                 '" is not equivalent to "' . basename($this->_packagefile->getPackageFile())
        !          83104:                 . '"');
1.1       misho    83105:         }
                   83106: 
1.1.1.2 ! misho    83107:         if ($where === null) {
        !          83108:             if (!($where = System::mktemp(array('-d')))) {
        !          83109:                 return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: mktemp failed');
1.1       misho    83110:             }
1.1.1.2 ! misho    83111:         } elseif (!@System::mkDir(array('-p', $where))) {
        !          83112:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' . $where . '" could' .
        !          83113:                 ' not be created');
        !          83114:         }
        !          83115: 
        !          83116:         $file = $where . DIRECTORY_SEPARATOR . 'package.xml';
        !          83117:         if (file_exists($file) && !is_file($file)) {
        !          83118:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: unable to save package.xml as' .
        !          83119:                 ' "' . $file  .'"');
1.1       misho    83120:         }
                   83121: 
1.1.1.2 ! misho    83122:         if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) {
        !          83123:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: invalid package.xml');
        !          83124:         }
1.1       misho    83125: 
1.1.1.2 ! misho    83126:         $ext = $compress ? '.tgz' : '.tar';
        !          83127:         $pkgver = $this->_packagefile->getPackage() . '-' . $this->_packagefile->getVersion();
        !          83128:         $dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext;
        !          83129:         if (file_exists($dest_package) && !is_file($dest_package)) {
        !          83130:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: cannot create tgz file "' .
        !          83131:                 $dest_package . '"');
1.1       misho    83132:         }
                   83133: 
1.1.1.2 ! misho    83134:         $pkgfile = $this->_packagefile->getPackageFile();
        !          83135:         if (!$pkgfile) {
        !          83136:             return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: package file object must ' .
        !          83137:                 'be created from a real file');
1.1       misho    83138:         }
                   83139: 
1.1.1.2 ! misho    83140:         $pkgdir  = dirname(realpath($pkgfile));
        !          83141:         $pkgfile = basename($pkgfile);
1.1       misho    83142: 
1.1.1.2 ! misho    83143:         // {{{ Create the package file list
        !          83144:         $filelist = array();
        !          83145:         $i = 0;
        !          83146:         $this->_packagefile->flattenFilelist();
        !          83147:         $contents = $this->_packagefile->getContents();
        !          83148:         if (isset($contents['bundledpackage'])) { // bundles of packages
        !          83149:             $contents = $contents['bundledpackage'];
        !          83150:             if (!isset($contents[0])) {
        !          83151:                 $contents = array($contents);
1.1       misho    83152:             }
                   83153: 
1.1.1.2 ! misho    83154:             $packageDir = $where;
        !          83155:             foreach ($contents as $i => $package) {
        !          83156:                 $fname = $package;
        !          83157:                 $file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
        !          83158:                 if (!file_exists($file)) {
        !          83159:                     return $packager->raiseError("File does not exist: $fname");
1.1       misho    83160:                 }
                   83161: 
1.1.1.2 ! misho    83162:                 $tfile = $packageDir . DIRECTORY_SEPARATOR . $fname;
        !          83163:                 System::mkdir(array('-p', dirname($tfile)));
        !          83164:                 copy($file, $tfile);
        !          83165:                 $filelist[$i++] = $tfile;
        !          83166:                 $packager->log(2, "Adding package $fname");
        !          83167:             }
        !          83168:         } else { // normal packages
        !          83169:             $contents = $contents['dir']['file'];
        !          83170:             if (!isset($contents[0])) {
        !          83171:                 $contents = array($contents);
        !          83172:             }
1.1       misho    83173: 
1.1.1.2 ! misho    83174:             $packageDir = $where;
        !          83175:             foreach ($contents as $i => $file) {
        !          83176:                 $fname = $file['attribs']['name'];
        !          83177:                 $atts = $file['attribs'];
        !          83178:                 $orig = $file;
        !          83179:                 $file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
        !          83180:                 if (!file_exists($file)) {
        !          83181:                     return $packager->raiseError("File does not exist: $fname");
1.1       misho    83182:                 }
                   83183: 
1.1.1.2 ! misho    83184:                 $origperms = fileperms($file);
        !          83185:                 $tfile = $packageDir . DIRECTORY_SEPARATOR . $fname;
        !          83186:                 unset($orig['attribs']);
        !          83187:                 if (count($orig)) { // file with tasks
        !          83188:                     // run any package-time tasks
        !          83189:                     $contents = file_get_contents($file);
        !          83190:                     foreach ($orig as $tag => $raw) {
        !          83191:                         $tag = str_replace(
        !          83192:                             array($this->_packagefile->getTasksNs() . ':', '-'),
        !          83193:                             array('', '_'), $tag);
        !          83194:                         $task = "PEAR_Task_$tag";
        !          83195:                         $task = &new $task($this->_packagefile->_config,
        !          83196:                             $this->_packagefile->_logger,
        !          83197:                             PEAR_TASK_PACKAGE);
        !          83198:                         $task->init($raw, $atts, null);
        !          83199:                         $res = $task->startSession($this->_packagefile, $contents, $tfile);
        !          83200:                         if (!$res) {
        !          83201:                             continue; // skip this task
1.1       misho    83202:                         }
                   83203: 
1.1.1.2 ! misho    83204:                         if (PEAR::isError($res)) {
        !          83205:                             return $res;
1.1       misho    83206:                         }
                   83207: 
1.1.1.2 ! misho    83208:                         $contents = $res; // save changes
        !          83209:                         System::mkdir(array('-p', dirname($tfile)));
        !          83210:                         $wp = fopen($tfile, "wb");
        !          83211:                         fwrite($wp, $contents);
        !          83212:                         fclose($wp);
1.1       misho    83213:                     }
1.1.1.2 ! misho    83214:                 }
1.1       misho    83215: 
1.1.1.2 ! misho    83216:                 if (!file_exists($tfile)) {
        !          83217:                     System::mkdir(array('-p', dirname($tfile)));
        !          83218:                     copy($file, $tfile);
1.1       misho    83219:                 }
1.1.1.2 ! misho    83220: 
        !          83221:                 chmod($tfile, $origperms);
        !          83222:                 $filelist[$i++] = $tfile;
        !          83223:                 $this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($tfile), $i - 1);
        !          83224:                 $packager->log(2, "Adding file $fname");
1.1       misho    83225:             }
                   83226:         }
1.1.1.2 ! misho    83227:             // }}}
1.1       misho    83228: 
1.1.1.2 ! misho    83229:         $name       = $pf1 !== null ? 'package2.xml' : 'package.xml';
        !          83230:         $packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, $name);
        !          83231:         if ($packagexml) {
        !          83232:             $tar =& new Archive_Tar($dest_package, $compress);
        !          83233:             $tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors
        !          83234:             // ----- Creates with the package.xml file
        !          83235:             $ok = $tar->createModify(array($packagexml), '', $where);
        !          83236:             if (PEAR::isError($ok)) {
        !          83237:                 return $packager->raiseError($ok);
        !          83238:             } elseif (!$ok) {
        !          83239:                 return $packager->raiseError('PEAR_Packagefile_v2::toTgz(): adding ' . $name .
        !          83240:                     ' failed');
1.1       misho    83241:             }
                   83242: 
1.1.1.2 ! misho    83243:             // ----- Add the content of the package
        !          83244:             if (!$tar->addModify($filelist, $pkgver, $where)) {
        !          83245:                 return $packager->raiseError(
        !          83246:                     'PEAR_Packagefile_v2::toTgz(): tarball creation failed');
1.1       misho    83247:             }
1.1.1.2 ! misho    83248: 
        !          83249:             // add the package.xml version 1.0
        !          83250:             if ($pf1 !== null) {
        !          83251:                 $pfgen = &$pf1->getDefaultGenerator();
        !          83252:                 $packagexml1 = $pfgen->toPackageFile($where, PEAR_VALIDATE_PACKAGING, 'package.xml', true);
        !          83253:                 if (!$tar->addModify(array($packagexml1), '', $where)) {
        !          83254:                     return $packager->raiseError(
        !          83255:                         'PEAR_Packagefile_v2::toTgz(): adding package.xml failed');
1.1       misho    83256:                 }
                   83257:             }
1.1.1.2 ! misho    83258: 
        !          83259:             return $dest_package;
1.1       misho    83260:         }
1.1.1.2 ! misho    83261:     }
1.1       misho    83262: 
1.1.1.2 ! misho    83263:     function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml')
        !          83264:     {
        !          83265:         if (!$this->_packagefile->validate($state)) {
        !          83266:             return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: invalid package.xml',
        !          83267:                 null, null, null, $this->_packagefile->getValidationWarnings());
        !          83268:         }
1.1       misho    83269: 
1.1.1.2 ! misho    83270:         if ($where === null) {
        !          83271:             if (!($where = System::mktemp(array('-d')))) {
        !          83272:                 return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: mktemp failed');
1.1       misho    83273:             }
1.1.1.2 ! misho    83274:         } elseif (!@System::mkDir(array('-p', $where))) {
        !          83275:             return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: "' . $where . '" could' .
        !          83276:                 ' not be created');
1.1       misho    83277:         }
                   83278: 
1.1.1.2 ! misho    83279:         $newpkgfile = $where . DIRECTORY_SEPARATOR . $name;
        !          83280:         $np = @fopen($newpkgfile, 'wb');
        !          83281:         if (!$np) {
        !          83282:             return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: unable to save ' .
        !          83283:                "$name as $newpkgfile");
        !          83284:         }
        !          83285:         fwrite($np, $this->toXml($state));
        !          83286:         fclose($np);
        !          83287:         return $newpkgfile;
        !          83288:     }
1.1       misho    83289: 
1.1.1.2 ! misho    83290:     function &toV2()
        !          83291:     {
        !          83292:         return $this->_packagefile;
        !          83293:     }
1.1       misho    83294: 
1.1.1.2 ! misho    83295:     /**
        !          83296:      * Return an XML document based on the package info (as returned
        !          83297:      * by the PEAR_Common::infoFrom* methods).
        !          83298:      *
        !          83299:      * @return string XML data
        !          83300:      */
        !          83301:     function toXml($state = PEAR_VALIDATE_NORMAL, $options = array())
        !          83302:     {
        !          83303:         $this->_packagefile->setDate(date('Y-m-d'));
        !          83304:         $this->_packagefile->setTime(date('H:i:s'));
        !          83305:         if (!$this->_packagefile->validate($state)) {
        !          83306:             return false;
1.1       misho    83307:         }
                   83308: 
1.1.1.2 ! misho    83309:         if (is_array($options)) {
        !          83310:             $this->options = array_merge($this->_defaultOptions, $options);
        !          83311:         } else {
        !          83312:             $this->options = $this->_defaultOptions;
1.1       misho    83313:         }
                   83314: 
1.1.1.2 ! misho    83315:         $arr = $this->_packagefile->getArray();
        !          83316:         if (isset($arr['filelist'])) {
        !          83317:             unset($arr['filelist']);
        !          83318:         }
1.1       misho    83319: 
1.1.1.2 ! misho    83320:         if (isset($arr['_lastversion'])) {
        !          83321:             unset($arr['_lastversion']);
1.1       misho    83322:         }
                   83323: 
1.1.1.2 ! misho    83324:         // Fix the notes a little bit
        !          83325:         if (isset($arr['notes'])) {
        !          83326:             // This trims out the indenting, needs fixing
        !          83327:             $arr['notes'] = "\n" . trim($arr['notes']) . "\n";
        !          83328:         }
1.1       misho    83329: 
1.1.1.2 ! misho    83330:         if (isset($arr['changelog']) && !empty($arr['changelog'])) {
        !          83331:             // Fix for inconsistency how the array is filled depending on the changelog release amount
        !          83332:             if (!isset($arr['changelog']['release'][0])) {
        !          83333:                 $release = $arr['changelog']['release'];
        !          83334:                 unset($arr['changelog']['release']);
1.1       misho    83335: 
1.1.1.2 ! misho    83336:                 $arr['changelog']['release']    = array();
        !          83337:                 $arr['changelog']['release'][0] = $release;
        !          83338:             }
1.1       misho    83339: 
1.1.1.2 ! misho    83340:             foreach (array_keys($arr['changelog']['release']) as $key) {
        !          83341:                 $c =& $arr['changelog']['release'][$key];
        !          83342:                 if (isset($c['notes'])) {
        !          83343:                     // This trims out the indenting, needs fixing
        !          83344:                     $c['notes'] = "\n" . trim($c['notes']) . "\n";
1.1       misho    83345:                 }
1.1.1.2 ! misho    83346:             }
        !          83347:         }
1.1       misho    83348: 
1.1.1.2 ! misho    83349:         if ($state ^ PEAR_VALIDATE_PACKAGING && !isset($arr['bundle'])) {
        !          83350:             $use = $this->_recursiveXmlFilelist($arr['contents']['dir']['file']);
        !          83351:             unset($arr['contents']['dir']['file']);
        !          83352:             if (isset($use['dir'])) {
        !          83353:                 $arr['contents']['dir']['dir'] = $use['dir'];
        !          83354:             }
        !          83355:             if (isset($use['file'])) {
        !          83356:                 $arr['contents']['dir']['file'] = $use['file'];
1.1       misho    83357:             }
1.1.1.2 ! misho    83358:             $this->options['beautifyFilelist'] = true;
        !          83359:         }
1.1       misho    83360: 
1.1.1.2 ! misho    83361:         $arr['attribs']['packagerversion'] = '1.9.4';
        !          83362:         if ($this->serialize($arr, $options)) {
        !          83363:             return $this->_serializedData . "\n";
        !          83364:         }
        !          83365: 
        !          83366:         return false;
        !          83367:     }
        !          83368: 
        !          83369: 
        !          83370:     function _recursiveXmlFilelist($list)
        !          83371:     {
        !          83372:         $dirs = array();
        !          83373:         if (isset($list['attribs'])) {
        !          83374:             $file = $list['attribs']['name'];
        !          83375:             unset($list['attribs']['name']);
        !          83376:             $attributes = $list['attribs'];
        !          83377:             $this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes);
        !          83378:         } else {
        !          83379:             foreach ($list as $a) {
        !          83380:                 $file = $a['attribs']['name'];
        !          83381:                 $attributes = $a['attribs'];
        !          83382:                 unset($a['attribs']);
        !          83383:                 $this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes, $a);
1.1       misho    83384:             }
                   83385:         }
1.1.1.2 ! misho    83386:         $this->_formatDir($dirs);
        !          83387:         $this->_deFormat($dirs);
        !          83388:         return $dirs;
        !          83389:     }
1.1       misho    83390: 
1.1.1.2 ! misho    83391:     function _addDir(&$dirs, $dir, $file = null, $attributes = null, $tasks = null)
        !          83392:     {
        !          83393:         if (!$tasks) {
        !          83394:             $tasks = array();
        !          83395:         }
        !          83396:         if ($dir == array() || $dir == array('.')) {
        !          83397:             $dirs['file'][basename($file)] = $tasks;
        !          83398:             $attributes['name'] = basename($file);
        !          83399:             $dirs['file'][basename($file)]['attribs'] = $attributes;
        !          83400:             return;
        !          83401:         }
        !          83402:         $curdir = array_shift($dir);
        !          83403:         if (!isset($dirs['dir'][$curdir])) {
        !          83404:             $dirs['dir'][$curdir] = array();
        !          83405:         }
        !          83406:         $this->_addDir($dirs['dir'][$curdir], $dir, $file, $attributes, $tasks);
        !          83407:     }
        !          83408: 
        !          83409:     function _formatDir(&$dirs)
        !          83410:     {
        !          83411:         if (!count($dirs)) {
        !          83412:             return array();
        !          83413:         }
        !          83414:         $newdirs = array();
        !          83415:         if (isset($dirs['dir'])) {
        !          83416:             $newdirs['dir'] = $dirs['dir'];
        !          83417:         }
        !          83418:         if (isset($dirs['file'])) {
        !          83419:             $newdirs['file'] = $dirs['file'];
        !          83420:         }
        !          83421:         $dirs = $newdirs;
        !          83422:         if (isset($dirs['dir'])) {
        !          83423:             uksort($dirs['dir'], 'strnatcasecmp');
        !          83424:             foreach ($dirs['dir'] as $dir => $contents) {
        !          83425:                 $this->_formatDir($dirs['dir'][$dir]);
        !          83426:             }
        !          83427:         }
        !          83428:         if (isset($dirs['file'])) {
        !          83429:             uksort($dirs['file'], 'strnatcasecmp');
        !          83430:         };
        !          83431:     }
        !          83432: 
        !          83433:     function _deFormat(&$dirs)
        !          83434:     {
        !          83435:         if (!count($dirs)) {
        !          83436:             return array();
        !          83437:         }
        !          83438:         $newdirs = array();
        !          83439:         if (isset($dirs['dir'])) {
        !          83440:             foreach ($dirs['dir'] as $dir => $contents) {
        !          83441:                 $newdir = array();
        !          83442:                 $newdir['attribs']['name'] = $dir;
        !          83443:                 $this->_deFormat($contents);
        !          83444:                 foreach ($contents as $tag => $val) {
        !          83445:                     $newdir[$tag] = $val;
        !          83446:                 }
        !          83447:                 $newdirs['dir'][] = $newdir;
        !          83448:             }
        !          83449:             if (count($newdirs['dir']) == 1) {
        !          83450:                 $newdirs['dir'] = $newdirs['dir'][0];
        !          83451:             }
        !          83452:         }
        !          83453:         if (isset($dirs['file'])) {
        !          83454:             foreach ($dirs['file'] as $name => $file) {
        !          83455:                 $newdirs['file'][] = $file;
        !          83456:             }
        !          83457:             if (count($newdirs['file']) == 1) {
        !          83458:                 $newdirs['file'] = $newdirs['file'][0];
1.1       misho    83459:             }
1.1.1.2 ! misho    83460:         }
        !          83461:         $dirs = $newdirs;
        !          83462:     }
        !          83463: 
        !          83464:     /**
        !          83465:     * reset all options to default options
        !          83466:     *
        !          83467:     * @access   public
        !          83468:     * @see      setOption(), XML_Unserializer()
        !          83469:     */
        !          83470:     function resetOptions()
        !          83471:     {
        !          83472:         $this->options = $this->_defaultOptions;
        !          83473:     }
        !          83474: 
        !          83475:    /**
        !          83476:     * set an option
        !          83477:     *
        !          83478:     * You can use this method if you do not want to set all options in the constructor
        !          83479:     *
        !          83480:     * @access   public
        !          83481:     * @see      resetOption(), XML_Serializer()
        !          83482:     */
        !          83483:     function setOption($name, $value)
        !          83484:     {
        !          83485:         $this->options[$name] = $value;
        !          83486:     }
        !          83487: 
        !          83488:    /**
        !          83489:     * sets several options at once
        !          83490:     *
        !          83491:     * You can use this method if you do not want to set all options in the constructor
        !          83492:     *
        !          83493:     * @access   public
        !          83494:     * @see      resetOption(), XML_Unserializer(), setOption()
        !          83495:     */
        !          83496:     function setOptions($options)
        !          83497:     {
        !          83498:         $this->options = array_merge($this->options, $options);
        !          83499:     }
1.1       misho    83500: 
1.1.1.2 ! misho    83501:    /**
        !          83502:     * serialize data
        !          83503:     *
        !          83504:     * @access   public
        !          83505:     * @param    mixed    $data data to serialize
        !          83506:     * @return   boolean  true on success, pear error on failure
        !          83507:     */
        !          83508:     function serialize($data, $options = null)
        !          83509:     {
        !          83510:         // if options have been specified, use them instead
        !          83511:         // of the previously defined ones
        !          83512:         if (is_array($options)) {
        !          83513:             $optionsBak = $this->options;
        !          83514:             if (isset($options['overrideOptions']) && $options['overrideOptions'] == true) {
        !          83515:                 $this->options = array_merge($this->_defaultOptions, $options);
        !          83516:             } else {
        !          83517:                 $this->options = array_merge($this->options, $options);
1.1       misho    83518:             }
1.1.1.2 ! misho    83519:         } else {
        !          83520:             $optionsBak = null;
1.1       misho    83521:         }
                   83522: 
1.1.1.2 ! misho    83523:         //  start depth is zero
        !          83524:         $this->_tagDepth = 0;
        !          83525:         $this->_serializedData = '';
        !          83526:         // serialize an array
        !          83527:         if (is_array($data)) {
        !          83528:             $tagName = isset($this->options['rootName']) ? $this->options['rootName'] : 'array';
        !          83529:             $this->_serializedData .= $this->_serializeArray($data, $tagName, $this->options['rootAttributes']);
1.1       misho    83530:         }
                   83531: 
1.1.1.2 ! misho    83532:         // add doctype declaration
        !          83533:         if ($this->options['addDoctype'] === true) {
        !          83534:             $this->_serializedData = XML_Util::getDoctypeDeclaration($tagName, $this->options['doctype'])
        !          83535:                                    . $this->options['linebreak']
        !          83536:                                    . $this->_serializedData;
1.1       misho    83537:         }
                   83538: 
1.1.1.2 ! misho    83539:         //  build xml declaration
        !          83540:         if ($this->options['addDecl']) {
        !          83541:             $atts = array();
        !          83542:             $encoding = isset($this->options['encoding']) ? $this->options['encoding'] : null;
        !          83543:             $this->_serializedData = XML_Util::getXMLDeclaration('1.0', $encoding)
        !          83544:                                    . $this->options['linebreak']
        !          83545:                                    . $this->_serializedData;
1.1       misho    83546:         }
                   83547: 
                   83548: 
1.1.1.2 ! misho    83549:         if ($optionsBak !== null) {
        !          83550:             $this->options = $optionsBak;
1.1       misho    83551:         }
                   83552: 
1.1.1.2 ! misho    83553:         return  true;
        !          83554:     }
1.1       misho    83555: 
1.1.1.2 ! misho    83556:    /**
        !          83557:     * get the result of the serialization
        !          83558:     *
        !          83559:     * @access public
        !          83560:     * @return string serialized XML
        !          83561:     */
        !          83562:     function getSerializedData()
        !          83563:     {
        !          83564:         if ($this->_serializedData === null) {
        !          83565:             return  $this->raiseError('No serialized data available. Use XML_Serializer::serialize() first.', XML_SERIALIZER_ERROR_NO_SERIALIZATION);
1.1       misho    83566:         }
1.1.1.2 ! misho    83567:         return $this->_serializedData;
1.1       misho    83568:     }
                   83569: 
1.1.1.2 ! misho    83570:    /**
        !          83571:     * serialize any value
        !          83572:     *
        !          83573:     * This method checks for the type of the value and calls the appropriate method
        !          83574:     *
        !          83575:     * @access private
        !          83576:     * @param  mixed     $value
        !          83577:     * @param  string    $tagName
        !          83578:     * @param  array     $attributes
        !          83579:     * @return string
        !          83580:     */
        !          83581:     function _serializeValue($value, $tagName = null, $attributes = array())
1.1       misho    83582:     {
1.1.1.2 ! misho    83583:         if (is_array($value)) {
        !          83584:             $xml = $this->_serializeArray($value, $tagName, $attributes);
        !          83585:         } elseif (is_object($value)) {
        !          83586:             $xml = $this->_serializeObject($value, $tagName);
        !          83587:         } else {
        !          83588:             $tag = array(
        !          83589:                           'qname'      => $tagName,
        !          83590:                           'attributes' => $attributes,
        !          83591:                           'content'    => $value
        !          83592:                         );
        !          83593:             $xml = $this->_createXMLTag($tag);
1.1       misho    83594:         }
1.1.1.2 ! misho    83595:         return $xml;
        !          83596:     }
1.1       misho    83597: 
1.1.1.2 ! misho    83598:    /**
        !          83599:     * serialize an array
        !          83600:     *
        !          83601:     * @access   private
        !          83602:     * @param    array   $array       array to serialize
        !          83603:     * @param    string  $tagName     name of the root tag
        !          83604:     * @param    array   $attributes  attributes for the root tag
        !          83605:     * @return   string  $string      serialized data
        !          83606:     * @uses     XML_Util::isValidName() to check, whether key has to be substituted
        !          83607:     */
        !          83608:     function _serializeArray(&$array, $tagName = null, $attributes = array())
        !          83609:     {
        !          83610:         $_content = null;
        !          83611: 
        !          83612:         /**
        !          83613:          * check for special attributes
        !          83614:          */
        !          83615:         if ($this->options['attributesArray'] !== null) {
        !          83616:             if (isset($array[$this->options['attributesArray']])) {
        !          83617:                 $attributes = $array[$this->options['attributesArray']];
        !          83618:                 unset($array[$this->options['attributesArray']]);
        !          83619:             }
        !          83620:             /**
        !          83621:              * check for special content
        !          83622:              */
        !          83623:             if ($this->options['contentName'] !== null) {
        !          83624:                 if (isset($array[$this->options['contentName']])) {
        !          83625:                     $_content = $array[$this->options['contentName']];
        !          83626:                     unset($array[$this->options['contentName']]);
1.1       misho    83627:                 }
                   83628:             }
1.1.1.2 ! misho    83629:         }
1.1       misho    83630: 
1.1.1.2 ! misho    83631:         /*
        !          83632:         * if mode is set to simpleXML, check whether
        !          83633:         * the array is associative or indexed
        !          83634:         */
        !          83635:         if (is_array($array) && $this->options['mode'] == 'simplexml') {
        !          83636:             $indexed = true;
        !          83637:             if (!count($array)) {
        !          83638:                 $indexed = false;
1.1       misho    83639:             }
1.1.1.2 ! misho    83640:             foreach ($array as $key => $val) {
        !          83641:                 if (!is_int($key)) {
        !          83642:                     $indexed = false;
        !          83643:                     break;
1.1       misho    83644:                 }
1.1.1.2 ! misho    83645:             }
1.1       misho    83646: 
1.1.1.2 ! misho    83647:             if ($indexed && $this->options['mode'] == 'simplexml') {
        !          83648:                 $string = '';
        !          83649:                 foreach ($array as $key => $val) {
        !          83650:                     if ($this->options['beautifyFilelist'] && $tagName == 'dir') {
        !          83651:                         if (!isset($this->_curdir)) {
        !          83652:                             $this->_curdir = '';
        !          83653:                         }
        !          83654:                         $savedir = $this->_curdir;
        !          83655:                         if (isset($val['attribs'])) {
        !          83656:                             if ($val['attribs']['name'] == '/') {
        !          83657:                                 $this->_curdir = '/';
        !          83658:                             } else {
        !          83659:                                 if ($this->_curdir == '/') {
        !          83660:                                     $this->_curdir = '';
        !          83661:                                 }
        !          83662:                                 $this->_curdir .= '/' . $val['attribs']['name'];
        !          83663:                             }
        !          83664:                         }
        !          83665:                     }
        !          83666:                     $string .= $this->_serializeValue( $val, $tagName, $attributes);
        !          83667:                     if ($this->options['beautifyFilelist'] && $tagName == 'dir') {
        !          83668:                         $string .= ' <!-- ' . $this->_curdir . ' -->';
        !          83669:                         if (empty($savedir)) {
        !          83670:                             unset($this->_curdir);
        !          83671:                         } else {
        !          83672:                             $this->_curdir = $savedir;
        !          83673:                         }
        !          83674:                     }
1.1       misho    83675: 
1.1.1.2 ! misho    83676:                     $string .= $this->options['linebreak'];
        !          83677:                     // do indentation
        !          83678:                     if ($this->options['indent'] !== null && $this->_tagDepth > 0) {
        !          83679:                         $string .= str_repeat($this->options['indent'], $this->_tagDepth);
1.1       misho    83680:                     }
                   83681:                 }
1.1.1.2 ! misho    83682:                 return rtrim($string);
1.1       misho    83683:             }
1.1.1.2 ! misho    83684:         }
1.1       misho    83685: 
1.1.1.2 ! misho    83686:         if ($this->options['scalarAsAttributes'] === true) {
        !          83687:             foreach ($array as $key => $value) {
        !          83688:                 if (is_scalar($value) && (XML_Util::isValidName($key) === true)) {
        !          83689:                     unset($array[$key]);
        !          83690:                     $attributes[$this->options['prependAttributes'].$key] = $value;
        !          83691:                 }
1.1       misho    83692:             }
                   83693:         }
                   83694: 
1.1.1.2 ! misho    83695:         // check for empty array => create empty tag
        !          83696:         if (empty($array)) {
        !          83697:             $tag = array(
        !          83698:                             'qname'      => $tagName,
        !          83699:                             'content'    => $_content,
        !          83700:                             'attributes' => $attributes
        !          83701:                         );
1.1       misho    83702: 
                   83703:         } else {
1.1.1.2 ! misho    83704:             $this->_tagDepth++;
        !          83705:             $tmp = $this->options['linebreak'];
        !          83706:             foreach ($array as $key => $value) {
        !          83707:                 // do indentation
        !          83708:                 if ($this->options['indent'] !== null && $this->_tagDepth > 0) {
        !          83709:                     $tmp .= str_repeat($this->options['indent'], $this->_tagDepth);
        !          83710:                 }
1.1       misho    83711: 
1.1.1.2 ! misho    83712:                 // copy key
        !          83713:                 $origKey = $key;
        !          83714:                 // key cannot be used as tagname => use default tag
        !          83715:                 $valid = XML_Util::isValidName($key);
        !          83716:                 if (PEAR::isError($valid)) {
        !          83717:                     if ($this->options['classAsTagName'] && is_object($value)) {
        !          83718:                         $key = get_class($value);
        !          83719:                     } else {
        !          83720:                         $key = $this->options['defaultTagName'];
        !          83721:                     }
        !          83722:                 }
        !          83723:                 $atts = array();
        !          83724:                 if ($this->options['typeHints'] === true) {
        !          83725:                     $atts[$this->options['typeAttribute']] = gettype($value);
        !          83726:                     if ($key !== $origKey) {
        !          83727:                         $atts[$this->options['keyAttribute']] = (string)$origKey;
        !          83728:                     }
1.1       misho    83729: 
1.1.1.2 ! misho    83730:                 }
        !          83731:                 if ($this->options['beautifyFilelist'] && $key == 'dir') {
        !          83732:                     if (!isset($this->_curdir)) {
        !          83733:                         $this->_curdir = '';
        !          83734:                     }
        !          83735:                     $savedir = $this->_curdir;
        !          83736:                     if (isset($value['attribs'])) {
        !          83737:                         if ($value['attribs']['name'] == '/') {
        !          83738:                             $this->_curdir = '/';
        !          83739:                         } else {
        !          83740:                             $this->_curdir .= '/' . $value['attribs']['name'];
        !          83741:                         }
        !          83742:                     }
        !          83743:                 }
1.1       misho    83744: 
1.1.1.2 ! misho    83745:                 if (is_string($value) && $value && ($value{strlen($value) - 1} == "\n")) {
        !          83746:                     $value .= str_repeat($this->options['indent'], $this->_tagDepth);
        !          83747:                 }
        !          83748:                 $tmp .= $this->_createXMLTag(array(
        !          83749:                                                     'qname'      => $key,
        !          83750:                                                     'attributes' => $atts,
        !          83751:                                                     'content'    => $value )
        !          83752:                                             );
        !          83753:                 if ($this->options['beautifyFilelist'] && $key == 'dir') {
        !          83754:                     if (isset($value['attribs'])) {
        !          83755:                         $tmp .= ' <!-- ' . $this->_curdir . ' -->';
        !          83756:                         if (empty($savedir)) {
        !          83757:                             unset($this->_curdir);
        !          83758:                         } else {
        !          83759:                             $this->_curdir = $savedir;
        !          83760:                         }
        !          83761:                     }
        !          83762:                 }
        !          83763:                 $tmp .= $this->options['linebreak'];
        !          83764:             }
1.1       misho    83765: 
1.1.1.2 ! misho    83766:             $this->_tagDepth--;
        !          83767:             if ($this->options['indent']!==null && $this->_tagDepth>0) {
        !          83768:                 $tmp .= str_repeat($this->options['indent'], $this->_tagDepth);
1.1       misho    83769:             }
                   83770: 
1.1.1.2 ! misho    83771:             if (trim($tmp) === '') {
        !          83772:                 $tmp = null;
1.1       misho    83773:             }
1.1.1.2 ! misho    83774: 
        !          83775:             $tag = array(
        !          83776:                 'qname'      => $tagName,
        !          83777:                 'content'    => $tmp,
        !          83778:                 'attributes' => $attributes
        !          83779:             );
        !          83780:         }
        !          83781:         if ($this->options['typeHints'] === true) {
        !          83782:             if (!isset($tag['attributes'][$this->options['typeAttribute']])) {
        !          83783:                 $tag['attributes'][$this->options['typeAttribute']] = 'array';
1.1       misho    83784:             }
                   83785:         }
                   83786: 
1.1.1.2 ! misho    83787:         $string = $this->_createXMLTag($tag, false);
        !          83788:         return $string;
        !          83789:     }
1.1       misho    83790: 
1.1.1.2 ! misho    83791:    /**
        !          83792:     * create a tag from an array
        !          83793:     * this method awaits an array in the following format
        !          83794:     * array(
        !          83795:     *       'qname'        => $tagName,
        !          83796:     *       'attributes'   => array(),
        !          83797:     *       'content'      => $content,      // optional
        !          83798:     *       'namespace'    => $namespace     // optional
        !          83799:     *       'namespaceUri' => $namespaceUri  // optional
        !          83800:     *   )
        !          83801:     *
        !          83802:     * @access   private
        !          83803:     * @param    array   $tag tag definition
        !          83804:     * @param    boolean $replaceEntities whether to replace XML entities in content or not
        !          83805:     * @return   string  $string XML tag
        !          83806:     */
        !          83807:     function _createXMLTag($tag, $replaceEntities = true)
        !          83808:     {
        !          83809:         if ($this->options['indentAttributes'] !== false) {
        !          83810:             $multiline = true;
        !          83811:             $indent    = str_repeat($this->options['indent'], $this->_tagDepth);
1.1       misho    83812: 
1.1.1.2 ! misho    83813:             if ($this->options['indentAttributes'] == '_auto') {
        !          83814:                 $indent .= str_repeat(' ', (strlen($tag['qname'])+2));
1.1       misho    83815: 
                   83816:             } else {
1.1.1.2 ! misho    83817:                 $indent .= $this->options['indentAttributes'];
1.1       misho    83818:             }
1.1.1.2 ! misho    83819:         } else {
        !          83820:             $indent = $multiline = false;
1.1       misho    83821:         }
                   83822: 
1.1.1.2 ! misho    83823:         if (is_array($tag['content'])) {
        !          83824:             if (empty($tag['content'])) {
        !          83825:                 $tag['content'] = '';
        !          83826:             }
        !          83827:         } elseif(is_scalar($tag['content']) && (string)$tag['content'] == '') {
        !          83828:             $tag['content'] = '';
1.1       misho    83829:         }
                   83830: 
1.1.1.2 ! misho    83831:         if (is_scalar($tag['content']) || is_null($tag['content'])) {
        !          83832:             if ($this->options['encoding'] == 'UTF-8' &&
        !          83833:                   version_compare(phpversion(), '5.0.0', 'lt')
        !          83834:             ) {
        !          83835:                 $tag['content'] = utf8_encode($tag['content']);
        !          83836:             }
1.1       misho    83837: 
1.1.1.2 ! misho    83838:             if ($replaceEntities === true) {
        !          83839:                 $replaceEntities = XML_UTIL_ENTITIES_XML;
        !          83840:             }
1.1       misho    83841: 
1.1.1.2 ! misho    83842:             $tag = XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $this->options['linebreak']);
        !          83843:         } elseif (is_array($tag['content'])) {
        !          83844:             $tag = $this->_serializeArray($tag['content'], $tag['qname'], $tag['attributes']);
        !          83845:         } elseif (is_object($tag['content'])) {
        !          83846:             $tag = $this->_serializeObject($tag['content'], $tag['qname'], $tag['attributes']);
        !          83847:         } elseif (is_resource($tag['content'])) {
        !          83848:             settype($tag['content'], 'string');
        !          83849:             $tag = XML_Util::createTagFromArray($tag, $replaceEntities);
1.1       misho    83850:         }
1.1.1.2 ! misho    83851:         return  $tag;
1.1       misho    83852:     }
                   83853: }<?php
                   83854: /**
1.1.1.2 ! misho    83855:  * package.xml parsing class, package.xml version 1.0
1.1       misho    83856:  *
                   83857:  * PHP versions 4 and 5
                   83858:  *
                   83859:  * @category   pear
                   83860:  * @package    PEAR
                   83861:  * @author     Greg Beaver <cellog@php.net>
                   83862:  * @copyright  1997-2009 The Authors
                   83863:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    83864:  * @version    CVS: $Id: v1.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    83865:  * @link       http://pear.php.net/package/PEAR
                   83866:  * @since      File available since Release 1.4.0a1
                   83867:  */
                   83868: /**
1.1.1.2 ! misho    83869:  * package.xml abstraction class
1.1       misho    83870:  */
1.1.1.2 ! misho    83871: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v1.php';
1.1       misho    83872: /**
1.1.1.2 ! misho    83873:  * Parser for package.xml version 1.0
1.1       misho    83874:  * @category   pear
                   83875:  * @package    PEAR
                   83876:  * @author     Greg Beaver <cellog@php.net>
                   83877:  * @copyright  1997-2009 The Authors
                   83878:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   83879:  * @version    Release: 1.10.0beta1
                   83880:  * @link       http://pear.php.net/package/PEAR
                   83881:  * @since      Class available since Release 1.4.0a1
                   83882:  */
1.1.1.2 ! misho    83883: class PEAR_PackageFile_Parser_v1
1.1       misho    83884: {
1.1.1.2 ! misho    83885:     var $_registry;
        !          83886:     var $_config;
        !          83887:     var $_logger;
1.1       misho    83888:     /**
1.1.1.2 ! misho    83889:      * BC hack to allow PEAR_Common::infoFromString() to sort of
        !          83890:      * work with the version 2.0 format - there's no filelist though
        !          83891:      * @param PEAR_PackageFile_v2
1.1       misho    83892:      */
1.1.1.2 ! misho    83893:     function fromV2($packagefile)
1.1       misho    83894:     {
1.1.1.2 ! misho    83895:         $info = $packagefile->getArray(true);
        !          83896:         $ret = new PEAR_PackageFile_v1;
        !          83897:         $ret->fromArray($info['old']);
        !          83898:     }
1.1       misho    83899: 
1.1.1.2 ! misho    83900:     function setConfig(&$c)
        !          83901:     {
        !          83902:         $this->_config = &$c;
        !          83903:         $this->_registry = &$c->getRegistry();
        !          83904:     }
1.1       misho    83905: 
1.1.1.2 ! misho    83906:     function setLogger(&$l)
        !          83907:     {
        !          83908:         $this->_logger = &$l;
1.1       misho    83909:     }
                   83910: 
                   83911:     /**
1.1.1.2 ! misho    83912:      * @param string contents of package.xml file, version 1.0
        !          83913:      * @return bool success of parsing
1.1       misho    83914:      */
1.1.1.2 ! misho    83915:     function &parse($data, $file, $archive = false)
1.1       misho    83916:     {
1.1.1.2 ! misho    83917:         if (!extension_loaded('xml')) {
        !          83918:             return PEAR::raiseError('Cannot create xml parser for parsing package.xml, no xml extension');
1.1       misho    83919:         }
1.1.1.2 ! misho    83920:         $xp = xml_parser_create();
        !          83921:         if (!$xp) {
        !          83922:             $a = &PEAR::raiseError('Cannot create xml parser for parsing package.xml');
1.1       misho    83923:             return $a;
                   83924:         }
1.1.1.2 ! misho    83925:         xml_set_object($xp, $this);
        !          83926:         xml_set_element_handler($xp, '_element_start_1_0', '_element_end_1_0');
        !          83927:         xml_set_character_data_handler($xp, '_pkginfo_cdata_1_0');
        !          83928:         xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, false);
1.1       misho    83929: 
1.1.1.2 ! misho    83930:         $this->element_stack = array();
        !          83931:         $this->_packageInfo = array('provides' => array());
        !          83932:         $this->current_element = false;
        !          83933:         unset($this->dir_install);
        !          83934:         $this->_packageInfo['filelist'] = array();
        !          83935:         $this->filelist =& $this->_packageInfo['filelist'];
        !          83936:         $this->dir_names = array();
        !          83937:         $this->in_changelog = false;
        !          83938:         $this->d_i = 0;
        !          83939:         $this->cdata = '';
        !          83940:         $this->_isValid = true;
        !          83941: 
        !          83942:         if (!xml_parse($xp, $data, 1)) {
        !          83943:             $code = xml_get_error_code($xp);
        !          83944:             $line = xml_get_current_line_number($xp);
        !          83945:             xml_parser_free($xp);
        !          83946:             $a = &PEAR::raiseError(sprintf("XML error: %s at line %d",
        !          83947:                            $str = xml_error_string($code), $line), 2);
        !          83948:             return $a;
1.1       misho    83949:         }
                   83950: 
1.1.1.2 ! misho    83951:         xml_parser_free($xp);
        !          83952: 
        !          83953:         $pf = new PEAR_PackageFile_v1;
        !          83954:         $pf->setConfig($this->_config);
        !          83955:         if (isset($this->_logger)) {
        !          83956:             $pf->setLogger($this->_logger);
        !          83957:         }
        !          83958:         $pf->setPackagefile($file, $archive);
        !          83959:         $pf->fromArray($this->_packageInfo);
        !          83960:         return $pf;
1.1       misho    83961:     }
1.1.1.2 ! misho    83962:     // {{{ _unIndent()
1.1       misho    83963: 
                   83964:     /**
1.1.1.2 ! misho    83965:      * Unindent given string
1.1       misho    83966:      *
1.1.1.2 ! misho    83967:      * @param string $str The string that has to be unindented.
        !          83968:      * @return string
        !          83969:      * @access private
1.1       misho    83970:      */
1.1.1.2 ! misho    83971:     function _unIndent($str)
1.1       misho    83972:     {
1.1.1.2 ! misho    83973:         // remove leading newlines
        !          83974:         $str = preg_replace('/^[\r\n]+/', '', $str);
        !          83975:         // find whitespace at the beginning of the first line
        !          83976:         $indent_len = strspn($str, " \t");
        !          83977:         $indent = substr($str, 0, $indent_len);
        !          83978:         $data = '';
        !          83979:         // remove the same amount of whitespace from following lines
        !          83980:         foreach (explode("\n", $str) as $line) {
        !          83981:             if (substr($line, 0, $indent_len) == $indent) {
        !          83982:                 $data .= substr($line, $indent_len) . "\n";
        !          83983:             } elseif (trim(substr($line, 0, $indent_len))) {
        !          83984:                 $data .= ltrim($line);
1.1       misho    83985:             }
                   83986:         }
1.1.1.2 ! misho    83987:         return $data;
1.1       misho    83988:     }
                   83989: 
1.1.1.2 ! misho    83990:     // Support for package DTD v1.0:
        !          83991:     // {{{ _element_start_1_0()
        !          83992: 
1.1       misho    83993:     /**
1.1.1.2 ! misho    83994:      * XML parser callback for ending elements.  Used for version 1.0
        !          83995:      * packages.
1.1       misho    83996:      *
1.1.1.2 ! misho    83997:      * @param resource  $xp    XML parser resource
        !          83998:      * @param string    $name  name of ending element
        !          83999:      *
        !          84000:      * @return void
        !          84001:      *
        !          84002:      * @access private
1.1       misho    84003:      */
1.1.1.2 ! misho    84004:     function _element_start_1_0($xp, $name, $attribs)
1.1       misho    84005:     {
1.1.1.2 ! misho    84006:         array_push($this->element_stack, $name);
        !          84007:         $this->current_element = $name;
        !          84008:         $spos = sizeof($this->element_stack) - 2;
        !          84009:         $this->prev_element = ($spos >= 0) ? $this->element_stack[$spos] : '';
        !          84010:         $this->current_attributes = $attribs;
        !          84011:         $this->cdata = '';
        !          84012:         switch ($name) {
        !          84013:             case 'dir':
        !          84014:                 if ($this->in_changelog) {
        !          84015:                     break;
        !          84016:                 }
        !          84017:                 if (array_key_exists('name', $attribs) && $attribs['name'] != '/') {
        !          84018:                     $attribs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
        !          84019:                         $attribs['name']);
        !          84020:                     if (strrpos($attribs['name'], '/') === strlen($attribs['name']) - 1) {
        !          84021:                         $attribs['name'] = substr($attribs['name'], 0,
        !          84022:                             strlen($attribs['name']) - 1);
        !          84023:                     }
        !          84024:                     if (strpos($attribs['name'], '/') === 0) {
        !          84025:                         $attribs['name'] = substr($attribs['name'], 1);
        !          84026:                     }
        !          84027:                     $this->dir_names[] = $attribs['name'];
        !          84028:                 }
        !          84029:                 if (isset($attribs['baseinstalldir'])) {
        !          84030:                     $this->dir_install = $attribs['baseinstalldir'];
        !          84031:                 }
        !          84032:                 if (isset($attribs['role'])) {
        !          84033:                     $this->dir_role = $attribs['role'];
        !          84034:                 }
        !          84035:                 break;
        !          84036:             case 'file':
        !          84037:                 if ($this->in_changelog) {
        !          84038:                     break;
        !          84039:                 }
        !          84040:                 if (isset($attribs['name'])) {
        !          84041:                     $path = '';
        !          84042:                     if (count($this->dir_names)) {
        !          84043:                         foreach ($this->dir_names as $dir) {
        !          84044:                             $path .= $dir . '/';
        !          84045:                         }
        !          84046:                     }
        !          84047:                     $path .= preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
        !          84048:                         $attribs['name']);
        !          84049:                     unset($attribs['name']);
        !          84050:                     $this->current_path = $path;
        !          84051:                     $this->filelist[$path] = $attribs;
        !          84052:                     // Set the baseinstalldir only if the file don't have this attrib
        !          84053:                     if (!isset($this->filelist[$path]['baseinstalldir']) &&
        !          84054:                         isset($this->dir_install))
        !          84055:                     {
        !          84056:                         $this->filelist[$path]['baseinstalldir'] = $this->dir_install;
        !          84057:                     }
        !          84058:                     // Set the Role
        !          84059:                     if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) {
        !          84060:                         $this->filelist[$path]['role'] = $this->dir_role;
        !          84061:                     }
        !          84062:                 }
        !          84063:                 break;
        !          84064:             case 'replace':
        !          84065:                 if (!$this->in_changelog) {
        !          84066:                     $this->filelist[$this->current_path]['replacements'][] = $attribs;
        !          84067:                 }
        !          84068:                 break;
        !          84069:             case 'maintainers':
        !          84070:                 $this->_packageInfo['maintainers'] = array();
        !          84071:                 $this->m_i = 0; // maintainers array index
        !          84072:                 break;
        !          84073:             case 'maintainer':
        !          84074:                 // compatibility check
        !          84075:                 if (!isset($this->_packageInfo['maintainers'])) {
        !          84076:                     $this->_packageInfo['maintainers'] = array();
        !          84077:                     $this->m_i = 0;
        !          84078:                 }
        !          84079:                 $this->_packageInfo['maintainers'][$this->m_i] = array();
        !          84080:                 $this->current_maintainer =& $this->_packageInfo['maintainers'][$this->m_i];
        !          84081:                 break;
        !          84082:             case 'changelog':
        !          84083:                 $this->_packageInfo['changelog'] = array();
        !          84084:                 $this->c_i = 0; // changelog array index
        !          84085:                 $this->in_changelog = true;
        !          84086:                 break;
        !          84087:             case 'release':
        !          84088:                 if ($this->in_changelog) {
        !          84089:                     $this->_packageInfo['changelog'][$this->c_i] = array();
        !          84090:                     $this->current_release = &$this->_packageInfo['changelog'][$this->c_i];
        !          84091:                 } else {
        !          84092:                     $this->current_release = &$this->_packageInfo;
        !          84093:                 }
        !          84094:                 break;
        !          84095:             case 'deps':
        !          84096:                 if (!$this->in_changelog) {
        !          84097:                     $this->_packageInfo['release_deps'] = array();
        !          84098:                 }
        !          84099:                 break;
        !          84100:             case 'dep':
        !          84101:                 // dependencies array index
        !          84102:                 if (!$this->in_changelog) {
        !          84103:                     $this->d_i++;
        !          84104:                     isset($attribs['type']) ? ($attribs['type'] = strtolower($attribs['type'])) : false;
        !          84105:                     $this->_packageInfo['release_deps'][$this->d_i] = $attribs;
        !          84106:                 }
        !          84107:                 break;
        !          84108:             case 'configureoptions':
        !          84109:                 if (!$this->in_changelog) {
        !          84110:                     $this->_packageInfo['configure_options'] = array();
        !          84111:                 }
        !          84112:                 break;
        !          84113:             case 'configureoption':
        !          84114:                 if (!$this->in_changelog) {
        !          84115:                     $this->_packageInfo['configure_options'][] = $attribs;
        !          84116:                 }
        !          84117:                 break;
        !          84118:             case 'provides':
        !          84119:                 if (empty($attribs['type']) || empty($attribs['name'])) {
        !          84120:                     break;
        !          84121:                 }
        !          84122:                 $attribs['explicit'] = true;
        !          84123:                 $this->_packageInfo['provides']["$attribs[type];$attribs[name]"] = $attribs;
        !          84124:                 break;
        !          84125:             case 'package' :
        !          84126:                 if (isset($attribs['version'])) {
        !          84127:                     $this->_packageInfo['xsdversion'] = trim($attribs['version']);
        !          84128:                 } else {
        !          84129:                     $this->_packageInfo['xsdversion'] = '1.0';
        !          84130:                 }
        !          84131:                 if (isset($attribs['packagerversion'])) {
        !          84132:                     $this->_packageInfo['packagerversion'] = $attribs['packagerversion'];
        !          84133:                 }
        !          84134:                 break;
1.1       misho    84135:         }
                   84136:     }
                   84137: 
1.1.1.2 ! misho    84138:     // }}}
        !          84139:     // {{{ _element_end_1_0()
        !          84140: 
1.1       misho    84141:     /**
1.1.1.2 ! misho    84142:      * XML parser callback for ending elements.  Used for version 1.0
        !          84143:      * packages.
1.1       misho    84144:      *
1.1.1.2 ! misho    84145:      * @param resource  $xp    XML parser resource
        !          84146:      * @param string    $name  name of ending element
        !          84147:      *
        !          84148:      * @return void
        !          84149:      *
        !          84150:      * @access private
1.1       misho    84151:      */
1.1.1.2 ! misho    84152:     function _element_end_1_0($xp, $name)
1.1       misho    84153:     {
1.1.1.2 ! misho    84154:         $data = trim($this->cdata);
        !          84155:         switch ($name) {
        !          84156:             case 'name':
        !          84157:                 switch ($this->prev_element) {
        !          84158:                     case 'package':
        !          84159:                         $this->_packageInfo['package'] = $data;
        !          84160:                         break;
        !          84161:                     case 'maintainer':
        !          84162:                         $this->current_maintainer['name'] = $data;
        !          84163:                         break;
        !          84164:                 }
        !          84165:                 break;
        !          84166:             case 'extends' :
        !          84167:                 $this->_packageInfo['extends'] = $data;
        !          84168:                 break;
        !          84169:             case 'summary':
        !          84170:                 $this->_packageInfo['summary'] = $data;
        !          84171:                 break;
        !          84172:             case 'description':
        !          84173:                 $data = $this->_unIndent($this->cdata);
        !          84174:                 $this->_packageInfo['description'] = $data;
        !          84175:                 break;
        !          84176:             case 'user':
        !          84177:                 $this->current_maintainer['handle'] = $data;
        !          84178:                 break;
        !          84179:             case 'email':
        !          84180:                 $this->current_maintainer['email'] = $data;
        !          84181:                 break;
        !          84182:             case 'role':
        !          84183:                 $this->current_maintainer['role'] = $data;
        !          84184:                 break;
        !          84185:             case 'version':
        !          84186:                 if ($this->in_changelog) {
        !          84187:                     $this->current_release['version'] = $data;
        !          84188:                 } else {
        !          84189:                     $this->_packageInfo['version'] = $data;
        !          84190:                 }
        !          84191:                 break;
        !          84192:             case 'date':
        !          84193:                 if ($this->in_changelog) {
        !          84194:                     $this->current_release['release_date'] = $data;
        !          84195:                 } else {
        !          84196:                     $this->_packageInfo['release_date'] = $data;
        !          84197:                 }
        !          84198:                 break;
        !          84199:             case 'notes':
        !          84200:                 // try to "de-indent" release notes in case someone
        !          84201:                 // has been over-indenting their xml ;-)
        !          84202:                 // Trim only on the right side
        !          84203:                 $data = rtrim($this->_unIndent($this->cdata));
        !          84204:                 if ($this->in_changelog) {
        !          84205:                     $this->current_release['release_notes'] = $data;
        !          84206:                 } else {
        !          84207:                     $this->_packageInfo['release_notes'] = $data;
        !          84208:                 }
        !          84209:                 break;
        !          84210:             case 'warnings':
        !          84211:                 if ($this->in_changelog) {
        !          84212:                     $this->current_release['release_warnings'] = $data;
        !          84213:                 } else {
        !          84214:                     $this->_packageInfo['release_warnings'] = $data;
        !          84215:                 }
        !          84216:                 break;
        !          84217:             case 'state':
        !          84218:                 if ($this->in_changelog) {
        !          84219:                     $this->current_release['release_state'] = $data;
        !          84220:                 } else {
        !          84221:                     $this->_packageInfo['release_state'] = $data;
        !          84222:                 }
        !          84223:                 break;
        !          84224:             case 'license':
        !          84225:                 if ($this->in_changelog) {
        !          84226:                     $this->current_release['release_license'] = $data;
        !          84227:                 } else {
        !          84228:                     $this->_packageInfo['release_license'] = $data;
        !          84229:                 }
        !          84230:                 break;
        !          84231:             case 'dep':
        !          84232:                 if ($data && !$this->in_changelog) {
        !          84233:                     $this->_packageInfo['release_deps'][$this->d_i]['name'] = $data;
        !          84234:                 }
        !          84235:                 break;
        !          84236:             case 'dir':
        !          84237:                 if ($this->in_changelog) {
        !          84238:                     break;
        !          84239:                 }
        !          84240:                 array_pop($this->dir_names);
        !          84241:                 break;
        !          84242:             case 'file':
        !          84243:                 if ($this->in_changelog) {
        !          84244:                     break;
        !          84245:                 }
        !          84246:                 if ($data) {
        !          84247:                     $path = '';
        !          84248:                     if (count($this->dir_names)) {
        !          84249:                         foreach ($this->dir_names as $dir) {
        !          84250:                             $path .= $dir . '/';
        !          84251:                         }
        !          84252:                     }
        !          84253:                     $path .= $data;
        !          84254:                     $this->filelist[$path] = $this->current_attributes;
        !          84255:                     // Set the baseinstalldir only if the file don't have this attrib
        !          84256:                     if (!isset($this->filelist[$path]['baseinstalldir']) &&
        !          84257:                         isset($this->dir_install))
        !          84258:                     {
        !          84259:                         $this->filelist[$path]['baseinstalldir'] = $this->dir_install;
        !          84260:                     }
        !          84261:                     // Set the Role
        !          84262:                     if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) {
        !          84263:                         $this->filelist[$path]['role'] = $this->dir_role;
        !          84264:                     }
        !          84265:                 }
        !          84266:                 break;
        !          84267:             case 'maintainer':
        !          84268:                 if (empty($this->_packageInfo['maintainers'][$this->m_i]['role'])) {
        !          84269:                     $this->_packageInfo['maintainers'][$this->m_i]['role'] = 'lead';
        !          84270:                 }
        !          84271:                 $this->m_i++;
        !          84272:                 break;
        !          84273:             case 'release':
        !          84274:                 if ($this->in_changelog) {
        !          84275:                     $this->c_i++;
        !          84276:                 }
        !          84277:                 break;
        !          84278:             case 'changelog':
        !          84279:                 $this->in_changelog = false;
        !          84280:                 break;
1.1       misho    84281:         }
1.1.1.2 ! misho    84282:         array_pop($this->element_stack);
        !          84283:         $spos = sizeof($this->element_stack) - 1;
        !          84284:         $this->current_element = ($spos > 0) ? $this->element_stack[$spos] : '';
        !          84285:         $this->cdata = '';
1.1       misho    84286:     }
                   84287: 
1.1.1.2 ! misho    84288:     // }}}
        !          84289:     // {{{ _pkginfo_cdata_1_0()
1.1       misho    84290: 
                   84291:     /**
1.1.1.2 ! misho    84292:      * XML parser callback for character data.  Used for version 1.0
        !          84293:      * packages.
1.1       misho    84294:      *
1.1.1.2 ! misho    84295:      * @param resource  $xp    XML parser resource
        !          84296:      * @param string    $name  character data
        !          84297:      *
        !          84298:      * @return void
        !          84299:      *
        !          84300:      * @access private
1.1       misho    84301:      */
1.1.1.2 ! misho    84302:     function _pkginfo_cdata_1_0($xp, $data)
1.1       misho    84303:     {
1.1.1.2 ! misho    84304:         if (isset($this->cdata)) {
        !          84305:             $this->cdata .= $data;
1.1       misho    84306:         }
                   84307:     }
1.1.1.2 ! misho    84308: 
        !          84309:     // }}}
        !          84310: }
        !          84311: ?><?php
1.1       misho    84312: /**
1.1.1.2 ! misho    84313:  * package.xml parsing class, package.xml version 2.0
1.1       misho    84314:  *
                   84315:  * PHP versions 4 and 5
                   84316:  *
                   84317:  * @category   pear
                   84318:  * @package    PEAR
                   84319:  * @author     Greg Beaver <cellog@php.net>
1.1.1.2 ! misho    84320:  * @copyright  1997-2009 The Authors
1.1       misho    84321:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    84322:  * @version    CVS: $Id: v2.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    84323:  * @link       http://pear.php.net/package/PEAR
                   84324:  * @since      File available since Release 1.4.0a1
                   84325:  */
                   84326: /**
1.1.1.2 ! misho    84327:  * base xml parser class
        !          84328:  */
        !          84329: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/XMLParser.php';
        !          84330: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2.php';
        !          84331: /**
        !          84332:  * Parser for package.xml version 2.0
1.1       misho    84333:  * @category   pear
                   84334:  * @package    PEAR
                   84335:  * @author     Greg Beaver <cellog@php.net>
1.1.1.2 ! misho    84336:  * @copyright  1997-2009 The Authors
1.1       misho    84337:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
                   84338:  * @version    Release: 1.10.0beta1
                   84339:  * @link       http://pear.php.net/package/PEAR
                   84340:  * @since      Class available since Release 1.4.0a1
                   84341:  */
1.1.1.2 ! misho    84342: class PEAR_PackageFile_Parser_v2 extends PEAR_XMLParser
1.1       misho    84343: {
1.1.1.2 ! misho    84344:     var $_config;
        !          84345:     var $_logger;
        !          84346:     var $_registry;
1.1       misho    84347: 
1.1.1.2 ! misho    84348:     function setConfig(&$c)
1.1       misho    84349:     {
1.1.1.2 ! misho    84350:         $this->_config = &$c;
        !          84351:         $this->_registry = &$c->getRegistry();
1.1       misho    84352:     }
                   84353: 
1.1.1.2 ! misho    84354:     function setLogger(&$l)
1.1       misho    84355:     {
1.1.1.2 ! misho    84356:         $this->_logger = &$l;
1.1       misho    84357:     }
                   84358:     /**
1.1.1.2 ! misho    84359:      * Unindent given string
1.1       misho    84360:      *
1.1.1.2 ! misho    84361:      * @param string $str The string that has to be unindented.
        !          84362:      * @return string
        !          84363:      * @access private
1.1       misho    84364:      */
1.1.1.2 ! misho    84365:     function _unIndent($str)
1.1       misho    84366:     {
1.1.1.2 ! misho    84367:         // remove leading newlines
        !          84368:         $str = preg_replace('/^[\r\n]+/', '', $str);
        !          84369:         // find whitespace at the beginning of the first line
        !          84370:         $indent_len = strspn($str, " \t");
        !          84371:         $indent = substr($str, 0, $indent_len);
        !          84372:         $data = '';
        !          84373:         // remove the same amount of whitespace from following lines
        !          84374:         foreach (explode("\n", $str) as $line) {
        !          84375:             if (substr($line, 0, $indent_len) == $indent) {
        !          84376:                 $data .= substr($line, $indent_len) . "\n";
        !          84377:             } else {
        !          84378:                 $data .= $line . "\n";
1.1       misho    84379:             }
                   84380:         }
1.1.1.2 ! misho    84381:         return $data;
1.1       misho    84382:     }
                   84383: 
                   84384:     /**
1.1.1.2 ! misho    84385:      * post-process data
        !          84386:      *
        !          84387:      * @param string $data
        !          84388:      * @param string $element element name
1.1       misho    84389:      */
1.1.1.2 ! misho    84390:     function postProcess($data, $element)
1.1       misho    84391:     {
1.1.1.2 ! misho    84392:         if ($element == 'notes') {
        !          84393:             return trim($this->_unIndent($data));
1.1       misho    84394:         }
1.1.1.2 ! misho    84395:         return trim($data);
1.1       misho    84396:     }
                   84397: 
                   84398:     /**
1.1.1.2 ! misho    84399:      * @param string
        !          84400:      * @param string file name of the package.xml
        !          84401:      * @param string|false name of the archive this package.xml came from, if any
        !          84402:      * @param string class name to instantiate and return.  This must be PEAR_PackageFile_v2 or
        !          84403:      *               a subclass
        !          84404:      * @return PEAR_PackageFile_v2
1.1       misho    84405:      */
1.1.1.2 ! misho    84406:     function &parse($data, $file, $archive = false, $class = 'PEAR_PackageFile_v2')
1.1       misho    84407:     {
1.1.1.2 ! misho    84408:         if (PEAR::isError($err = parent::parse($data, $file))) {
        !          84409:             return $err;
1.1       misho    84410:         }
                   84411: 
1.1.1.2 ! misho    84412:         $ret = new $class;
        !          84413:         $ret->encoding = $this->encoding;
        !          84414:         $ret->setConfig($this->_config);
        !          84415:         if (isset($this->_logger)) {
        !          84416:             $ret->setLogger($this->_logger);
1.1       misho    84417:         }
                   84418: 
1.1.1.2 ! misho    84419:         $ret->fromArray($this->_unserializedData);
        !          84420:         $ret->setPackagefile($file, $archive);
        !          84421:         return $ret;
1.1       misho    84422:     }
                   84423: }<?php
                   84424: /**
1.1.1.2 ! misho    84425:  * PEAR_PackageFile_v1, package.xml version 1.0
1.1       misho    84426:  *
                   84427:  * PHP versions 4 and 5
                   84428:  *
                   84429:  * @category   pear
                   84430:  * @package    PEAR
                   84431:  * @author     Greg Beaver <cellog@php.net>
                   84432:  * @copyright  1997-2009 The Authors
                   84433:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    84434:  * @version    CVS: $Id: v1.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    84435:  * @link       http://pear.php.net/package/PEAR
                   84436:  * @since      File available since Release 1.4.0a1
                   84437:  */
1.1.1.2 ! misho    84438: /**
        !          84439:  * For error handling
        !          84440:  */
        !          84441: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ErrorStack.php';
        !          84442: 
        !          84443: /**
        !          84444:  * Error code if parsing is attempted with no xml extension
        !          84445:  */
        !          84446: define('PEAR_PACKAGEFILE_ERROR_NO_XML_EXT', 3);
        !          84447: 
        !          84448: /**
        !          84449:  * Error code if creating the xml parser resource fails
        !          84450:  */
        !          84451: define('PEAR_PACKAGEFILE_ERROR_CANT_MAKE_PARSER', 4);
        !          84452: 
        !          84453: /**
        !          84454:  * Error code used for all sax xml parsing errors
        !          84455:  */
        !          84456: define('PEAR_PACKAGEFILE_ERROR_PARSER_ERROR', 5);
        !          84457: 
        !          84458: /**
        !          84459:  * Error code used when there is no name
        !          84460:  */
        !          84461: define('PEAR_PACKAGEFILE_ERROR_NO_NAME', 6);
        !          84462: 
        !          84463: /**
        !          84464:  * Error code when a package name is not valid
        !          84465:  */
        !          84466: define('PEAR_PACKAGEFILE_ERROR_INVALID_NAME', 7);
        !          84467: 
        !          84468: /**
        !          84469:  * Error code used when no summary is parsed
        !          84470:  */
        !          84471: define('PEAR_PACKAGEFILE_ERROR_NO_SUMMARY', 8);
        !          84472: 
        !          84473: /**
        !          84474:  * Error code for summaries that are more than 1 line
        !          84475:  */
        !          84476: define('PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY', 9);
        !          84477: 
        !          84478: /**
        !          84479:  * Error code used when no description is present
        !          84480:  */
        !          84481: define('PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION', 10);
        !          84482: 
        !          84483: /**
        !          84484:  * Error code used when no license is present
        !          84485:  */
        !          84486: define('PEAR_PACKAGEFILE_ERROR_NO_LICENSE', 11);
        !          84487: 
        !          84488: /**
        !          84489:  * Error code used when a <version> version number is not present
        !          84490:  */
        !          84491: define('PEAR_PACKAGEFILE_ERROR_NO_VERSION', 12);
        !          84492: 
        !          84493: /**
        !          84494:  * Error code used when a <version> version number is invalid
        !          84495:  */
        !          84496: define('PEAR_PACKAGEFILE_ERROR_INVALID_VERSION', 13);
        !          84497: 
        !          84498: /**
        !          84499:  * Error code when release state is missing
        !          84500:  */
        !          84501: define('PEAR_PACKAGEFILE_ERROR_NO_STATE', 14);
        !          84502: 
        !          84503: /**
        !          84504:  * Error code when release state is invalid
        !          84505:  */
        !          84506: define('PEAR_PACKAGEFILE_ERROR_INVALID_STATE', 15);
        !          84507: 
        !          84508: /**
        !          84509:  * Error code when release state is missing
        !          84510:  */
        !          84511: define('PEAR_PACKAGEFILE_ERROR_NO_DATE', 16);
        !          84512: 
        !          84513: /**
        !          84514:  * Error code when release state is invalid
        !          84515:  */
        !          84516: define('PEAR_PACKAGEFILE_ERROR_INVALID_DATE', 17);
        !          84517: 
        !          84518: /**
        !          84519:  * Error code when no release notes are found
        !          84520:  */
        !          84521: define('PEAR_PACKAGEFILE_ERROR_NO_NOTES', 18);
        !          84522: 
        !          84523: /**
        !          84524:  * Error code when no maintainers are found
        !          84525:  */
        !          84526: define('PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS', 19);
        !          84527: 
        !          84528: /**
        !          84529:  * Error code when a maintainer has no handle
        !          84530:  */
        !          84531: define('PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE', 20);
        !          84532: 
        !          84533: /**
        !          84534:  * Error code when a maintainer has no handle
        !          84535:  */
        !          84536: define('PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE', 21);
        !          84537: 
        !          84538: /**
        !          84539:  * Error code when a maintainer has no name
        !          84540:  */
        !          84541: define('PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME', 22);
        !          84542: 
        !          84543: /**
        !          84544:  * Error code when a maintainer has no email
        !          84545:  */
        !          84546: define('PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL', 23);
        !          84547: 
        !          84548: /**
        !          84549:  * Error code when a maintainer has no handle
        !          84550:  */
        !          84551: define('PEAR_PACKAGEFILE_ERROR_INVALID_MAINTROLE', 24);
        !          84552: 
        !          84553: /**
        !          84554:  * Error code when a dependency is not a PHP dependency, but has no name
        !          84555:  */
        !          84556: define('PEAR_PACKAGEFILE_ERROR_NO_DEPNAME', 25);
        !          84557: 
        !          84558: /**
        !          84559:  * Error code when a dependency has no type (pkg, php, etc.)
        !          84560:  */
        !          84561: define('PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE', 26);
        !          84562: 
        !          84563: /**
        !          84564:  * Error code when a dependency has no relation (lt, ge, has, etc.)
        !          84565:  */
        !          84566: define('PEAR_PACKAGEFILE_ERROR_NO_DEPREL', 27);
        !          84567: 
        !          84568: /**
        !          84569:  * Error code when a dependency is not a 'has' relation, but has no version
        !          84570:  */
        !          84571: define('PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION', 28);
        !          84572: 
        !          84573: /**
        !          84574:  * Error code when a dependency has an invalid relation
        !          84575:  */
        !          84576: define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPREL', 29);
        !          84577: 
        !          84578: /**
        !          84579:  * Error code when a dependency has an invalid type
        !          84580:  */
        !          84581: define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPTYPE', 30);
        !          84582: 
        !          84583: /**
        !          84584:  * Error code when a dependency has an invalid optional option
        !          84585:  */
        !          84586: define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL', 31);
        !          84587: 
        !          84588: /**
        !          84589:  * Error code when a dependency is a pkg dependency, and has an invalid package name
        !          84590:  */
        !          84591: define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPNAME', 32);
        !          84592: 
        !          84593: /**
        !          84594:  * Error code when a dependency has a channel="foo" attribute, and foo is not a registered channel
        !          84595:  */
        !          84596: define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_DEPCHANNEL', 33);
        !          84597: 
        !          84598: /**
        !          84599:  * Error code when rel="has" and version attribute is present.
        !          84600:  */
        !          84601: define('PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED', 34);
        !          84602: 
        !          84603: /**
        !          84604:  * Error code when type="php" and dependency name is present
        !          84605:  */
        !          84606: define('PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED', 35);
        !          84607: 
        !          84608: /**
        !          84609:  * Error code when a configure option has no name
        !          84610:  */
        !          84611: define('PEAR_PACKAGEFILE_ERROR_NO_CONFNAME', 36);
        !          84612: 
        !          84613: /**
        !          84614:  * Error code when a configure option has no name
        !          84615:  */
        !          84616: define('PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT', 37);
        !          84617: 
        !          84618: /**
        !          84619:  * Error code when a file in the filelist has an invalid role
        !          84620:  */
        !          84621: define('PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE', 38);
1.1       misho    84622: 
                   84623: /**
1.1.1.2 ! misho    84624:  * Error code when a file in the filelist has no role
1.1       misho    84625:  */
1.1.1.2 ! misho    84626: define('PEAR_PACKAGEFILE_ERROR_NO_FILEROLE', 39);
        !          84627: 
1.1       misho    84628: /**
1.1.1.2 ! misho    84629:  * Error code when analyzing a php source file that has parse errors
1.1       misho    84630:  */
1.1.1.2 ! misho    84631: define('PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE', 40);
1.1       misho    84632: 
                   84633: /**
1.1.1.2 ! misho    84634:  * Error code when analyzing a php source file reveals a source element
        !          84635:  * without a package name prefix
1.1       misho    84636:  */
1.1.1.2 ! misho    84637: define('PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX', 41);
        !          84638: 
1.1       misho    84639: /**
1.1.1.2 ! misho    84640:  * Error code when an unknown channel is specified
1.1       misho    84641:  */
1.1.1.2 ! misho    84642: define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_CHANNEL', 42);
1.1       misho    84643: 
                   84644: /**
1.1.1.2 ! misho    84645:  * Error code when no files are found in the filelist
1.1       misho    84646:  */
1.1.1.2 ! misho    84647: define('PEAR_PACKAGEFILE_ERROR_NO_FILES', 43);
        !          84648: 
1.1       misho    84649: /**
1.1.1.2 ! misho    84650:  * Error code when a file is not valid php according to _analyzeSourceCode()
1.1       misho    84651:  */
1.1.1.2 ! misho    84652: define('PEAR_PACKAGEFILE_ERROR_INVALID_FILE', 44);
1.1       misho    84653: 
                   84654: /**
1.1.1.2 ! misho    84655:  * Error code when the channel validator returns an error or warning
1.1       misho    84656:  */
1.1.1.2 ! misho    84657: define('PEAR_PACKAGEFILE_ERROR_CHANNELVAL', 45);
        !          84658: 
1.1       misho    84659: /**
1.1.1.2 ! misho    84660:  * Error code when a php5 package is packaged in php4 (analysis doesn't work)
1.1       misho    84661:  */
1.1.1.2 ! misho    84662: define('PEAR_PACKAGEFILE_ERROR_PHP5', 46);
1.1       misho    84663: 
                   84664: /**
1.1.1.2 ! misho    84665:  * Error code when a file is listed in package.xml but does not exist
1.1       misho    84666:  */
1.1.1.2 ! misho    84667: define('PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND', 47);
        !          84668: 
1.1       misho    84669: /**
1.1.1.2 ! misho    84670:  * Error code when a <dep type="php" rel="not"... is encountered (use rel="ne")
1.1       misho    84671:  */
1.1.1.2 ! misho    84672: define('PEAR_PACKAGEFILE_PHP_NO_NOT', 48);
1.1       misho    84673: 
                   84674: /**
1.1.1.2 ! misho    84675:  * Error code when a package.xml contains non-ISO-8859-1 characters
1.1       misho    84676:  */
1.1.1.2 ! misho    84677: define('PEAR_PACKAGEFILE_ERROR_NON_ISO_CHARS', 49);
        !          84678: 
1.1       misho    84679: /**
1.1.1.2 ! misho    84680:  * Error code when a dependency is not a 'has' relation, but has no version
1.1       misho    84681:  */
1.1.1.2 ! misho    84682: define('PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION', 50);
        !          84683: 
1.1       misho    84684: /**
1.1.1.2 ! misho    84685:  * Error code when a package has no lead developer
1.1       misho    84686:  */
1.1.1.2 ! misho    84687: define('PEAR_PACKAGEFILE_ERROR_NO_LEAD', 51);
        !          84688: 
1.1       misho    84689: /**
1.1.1.2 ! misho    84690:  * Error code when a filename begins with "."
        !          84691:  */
        !          84692: define('PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME', 52);
        !          84693: /**
        !          84694:  * package.xml encapsulator
1.1       misho    84695:  * @category   pear
                   84696:  * @package    PEAR
                   84697:  * @author     Greg Beaver <cellog@php.net>
                   84698:  * @copyright  1997-2009 The Authors
                   84699:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    84700:  * @version    Release: 1.9.4
1.1       misho    84701:  * @link       http://pear.php.net/package/PEAR
                   84702:  * @since      Class available since Release 1.4.0a1
                   84703:  */
1.1.1.2 ! misho    84704: class PEAR_PackageFile_v1
1.1       misho    84705: {
                   84706:     /**
1.1.1.2 ! misho    84707:      * @access private
        !          84708:      * @var PEAR_ErrorStack
        !          84709:      * @access private
1.1       misho    84710:      */
1.1.1.2 ! misho    84711:     var $_stack;
1.1       misho    84712: 
                   84713:     /**
1.1.1.2 ! misho    84714:      * A registry object, used to access the package name validation regex for non-standard channels
        !          84715:      * @var PEAR_Registry
        !          84716:      * @access private
1.1       misho    84717:      */
1.1.1.2 ! misho    84718:     var $_registry;
1.1       misho    84719: 
                   84720:     /**
1.1.1.2 ! misho    84721:      * An object that contains a log method that matches PEAR_Common::log's signature
        !          84722:      * @var object
        !          84723:      * @access private
        !          84724:      */
        !          84725:     var $_logger;
        !          84726: 
        !          84727:     /**
        !          84728:      * Parsed package information
1.1       misho    84729:      * @var array
                   84730:      * @access private
                   84731:      */
1.1.1.2 ! misho    84732:     var $_packageInfo;
1.1       misho    84733: 
                   84734:     /**
1.1.1.2 ! misho    84735:      * path to package.xml
        !          84736:      * @var string
        !          84737:      * @access private
1.1       misho    84738:      */
1.1.1.2 ! misho    84739:     var $_packageFile;
1.1       misho    84740: 
                   84741:     /**
1.1.1.2 ! misho    84742:      * path to package .tgz or false if this is a local/extracted package.xml
        !          84743:      * @var string
        !          84744:      * @access private
        !          84745:      */
        !          84746:     var $_archiveFile;
        !          84747: 
        !          84748:     /**
        !          84749:      * @var int
        !          84750:      * @access private
        !          84751:      */
        !          84752:     var $_isValid = 0;
        !          84753: 
        !          84754:     /**
        !          84755:      * Determines whether this packagefile was initialized only with partial package info
1.1       misho    84756:      *
1.1.1.2 ! misho    84757:      * If this package file was constructed via parsing REST, it will only contain
        !          84758:      *
        !          84759:      * - package name
        !          84760:      * - channel name
        !          84761:      * - dependencies 
        !          84762:      * @var boolean
        !          84763:      * @access private
1.1       misho    84764:      */
1.1.1.2 ! misho    84765:     var $_incomplete = true;
        !          84766: 
        !          84767:     /**
        !          84768:      * @param bool determines whether to return a PEAR_Error object, or use the PEAR_ErrorStack
        !          84769:      * @param string Name of Error Stack class to use.
        !          84770:      */
        !          84771:     function PEAR_PackageFile_v1()
1.1       misho    84772:     {
1.1.1.2 ! misho    84773:         $this->_stack = &new PEAR_ErrorStack('PEAR_PackageFile_v1');
        !          84774:         $this->_stack->setErrorMessageTemplate($this->_getErrorMessage());
        !          84775:         $this->_isValid = 0;
1.1       misho    84776:     }
                   84777: 
1.1.1.2 ! misho    84778:     function installBinary($installer)
1.1       misho    84779:     {
1.1.1.2 ! misho    84780:         return false;
1.1       misho    84781:     }
                   84782: 
1.1.1.2 ! misho    84783:     function isExtension($name)
1.1       misho    84784:     {
1.1.1.2 ! misho    84785:         return false;
        !          84786:     }
1.1       misho    84787: 
1.1.1.2 ! misho    84788:     function setConfig(&$config)
        !          84789:     {
        !          84790:         $this->_config = &$config;
        !          84791:         $this->_registry = &$config->getRegistry();
        !          84792:     }
        !          84793: 
        !          84794:     function setRequestedGroup()
        !          84795:     {
        !          84796:         // placeholder
1.1       misho    84797:     }
                   84798: 
                   84799:     /**
1.1.1.2 ! misho    84800:      * For saving in the registry.
        !          84801:      *
        !          84802:      * Set the last version that was installed
        !          84803:      * @param string
1.1       misho    84804:      */
1.1.1.2 ! misho    84805:     function setLastInstalledVersion($version)
1.1       misho    84806:     {
1.1.1.2 ! misho    84807:         $this->_packageInfo['_lastversion'] = $version;
1.1       misho    84808:     }
                   84809: 
                   84810:     /**
1.1.1.2 ! misho    84811:      * @return string|false
1.1       misho    84812:      */
1.1.1.2 ! misho    84813:     function getLastInstalledVersion()
1.1       misho    84814:     {
1.1.1.2 ! misho    84815:         if (isset($this->_packageInfo['_lastversion'])) {
        !          84816:             return $this->_packageInfo['_lastversion'];
1.1       misho    84817:         }
1.1.1.2 ! misho    84818:         return false;
        !          84819:     }
1.1       misho    84820: 
1.1.1.2 ! misho    84821:     function getInstalledBinary()
        !          84822:     {
        !          84823:         return false;
1.1       misho    84824:     }
                   84825: 
1.1.1.2 ! misho    84826:     function listPostinstallScripts()
1.1       misho    84827:     {
1.1.1.2 ! misho    84828:         return false;
        !          84829:     }
1.1       misho    84830: 
1.1.1.2 ! misho    84831:     function initPostinstallScripts()
        !          84832:     {
        !          84833:         return false;
        !          84834:     }
        !          84835: 
        !          84836:     function setLogger(&$logger)
        !          84837:     {
        !          84838:         if ($logger && (!is_object($logger) || !method_exists($logger, 'log'))) {
        !          84839:             return PEAR::raiseError('Logger must be compatible with PEAR_Common::log');
1.1       misho    84840:         }
1.1.1.2 ! misho    84841:         $this->_logger = &$logger;
        !          84842:     }
1.1       misho    84843: 
1.1.1.2 ! misho    84844:     function setPackagefile($file, $archive = false)
        !          84845:     {
        !          84846:         $this->_packageFile = $file;
        !          84847:         $this->_archiveFile = $archive ? $archive : $file;
        !          84848:     }
        !          84849: 
        !          84850:     function getPackageFile()
        !          84851:     {
        !          84852:         return isset($this->_packageFile) ? $this->_packageFile : false;
        !          84853:     }
        !          84854: 
        !          84855:     function getPackageType()
        !          84856:     {
        !          84857:         return 'php';
        !          84858:     }
        !          84859: 
        !          84860:     function getArchiveFile()
        !          84861:     {
        !          84862:         return $this->_archiveFile;
        !          84863:     }
        !          84864: 
        !          84865:     function packageInfo($field)
        !          84866:     {
        !          84867:         if (!is_string($field) || empty($field) ||
        !          84868:             !isset($this->_packageInfo[$field])) {
        !          84869:             return false;
1.1       misho    84870:         }
1.1.1.2 ! misho    84871:         return $this->_packageInfo[$field];
        !          84872:     }
1.1       misho    84873: 
1.1.1.2 ! misho    84874:     function setDirtree($path)
        !          84875:     {
        !          84876:         if (!isset($this->_packageInfo['dirtree'])) {
        !          84877:             $this->_packageInfo['dirtree'] = array();
1.1       misho    84878:         }
1.1.1.2 ! misho    84879:         $this->_packageInfo['dirtree'][$path] = true;
        !          84880:     }
1.1       misho    84881: 
1.1.1.2 ! misho    84882:     function getDirtree()
        !          84883:     {
        !          84884:         if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) {
        !          84885:             return $this->_packageInfo['dirtree'];
        !          84886:         }
        !          84887:         return false;
1.1       misho    84888:     }
                   84889: 
1.1.1.2 ! misho    84890:     function resetDirtree()
1.1       misho    84891:     {
1.1.1.2 ! misho    84892:         unset($this->_packageInfo['dirtree']);
        !          84893:     }
1.1       misho    84894: 
1.1.1.2 ! misho    84895:     function fromArray($pinfo)
        !          84896:     {
        !          84897:         $this->_incomplete = false;
        !          84898:         $this->_packageInfo = $pinfo;
        !          84899:     }
1.1       misho    84900: 
1.1.1.2 ! misho    84901:     function isIncomplete()
        !          84902:     {
        !          84903:         return $this->_incomplete;
        !          84904:     }
1.1       misho    84905: 
1.1.1.2 ! misho    84906:     function getChannel()
        !          84907:     {
        !          84908:         return 'pear.php.net';
        !          84909:     }
1.1       misho    84910: 
1.1.1.2 ! misho    84911:     function getUri()
        !          84912:     {
        !          84913:         return false;
        !          84914:     }
        !          84915: 
        !          84916:     function getTime()
        !          84917:     {
        !          84918:         return false;
        !          84919:     }
        !          84920: 
        !          84921:     function getExtends()
        !          84922:     {
        !          84923:         if (isset($this->_packageInfo['extends'])) {
        !          84924:             return $this->_packageInfo['extends'];
        !          84925:         }
        !          84926:         return false;
        !          84927:     }
1.1       misho    84928: 
1.1.1.2 ! misho    84929:     /**
        !          84930:      * @return array
        !          84931:      */
        !          84932:     function toArray()
        !          84933:     {
        !          84934:         if (!$this->validate(PEAR_VALIDATE_NORMAL)) {
        !          84935:             return false;
        !          84936:         }
        !          84937:         return $this->getArray();
        !          84938:     }
1.1       misho    84939: 
1.1.1.2 ! misho    84940:     function getArray()
        !          84941:     {
        !          84942:         return $this->_packageInfo;
        !          84943:     }
1.1       misho    84944: 
1.1.1.2 ! misho    84945:     function getName()
        !          84946:     {
        !          84947:         return $this->getPackage();
        !          84948:     }
1.1       misho    84949: 
1.1.1.2 ! misho    84950:     function getPackage()
        !          84951:     {
        !          84952:         if (isset($this->_packageInfo['package'])) {
        !          84953:             return $this->_packageInfo['package'];
        !          84954:         }
        !          84955:         return false;
        !          84956:     }
1.1       misho    84957: 
1.1.1.2 ! misho    84958:     /**
        !          84959:      * WARNING - don't use this unless you know what you are doing
        !          84960:      */
        !          84961:     function setRawPackage($package)
        !          84962:     {
        !          84963:         $this->_packageInfo['package'] = $package;
        !          84964:     }
1.1       misho    84965: 
1.1.1.2 ! misho    84966:     function setPackage($package)
        !          84967:     {
        !          84968:         $this->_packageInfo['package'] = $package;
        !          84969:         $this->_isValid = false;
        !          84970:     }
1.1       misho    84971: 
1.1.1.2 ! misho    84972:     function getVersion()
        !          84973:     {
        !          84974:         if (isset($this->_packageInfo['version'])) {
        !          84975:             return $this->_packageInfo['version'];
        !          84976:         }
        !          84977:         return false;
        !          84978:     }
1.1       misho    84979: 
1.1.1.2 ! misho    84980:     function setVersion($version)
        !          84981:     {
        !          84982:         $this->_packageInfo['version'] = $version;
        !          84983:         $this->_isValid = false;
        !          84984:     }
1.1       misho    84985: 
1.1.1.2 ! misho    84986:     function clearMaintainers()
        !          84987:     {
        !          84988:         unset($this->_packageInfo['maintainers']);
        !          84989:     }
1.1       misho    84990: 
1.1.1.2 ! misho    84991:     function getMaintainers()
        !          84992:     {
        !          84993:         if (isset($this->_packageInfo['maintainers'])) {
        !          84994:             return $this->_packageInfo['maintainers'];
1.1       misho    84995:         }
1.1.1.2 ! misho    84996:         return false;
1.1       misho    84997:     }
                   84998: 
                   84999:     /**
1.1.1.2 ! misho    85000:      * Adds a new maintainer - no checking of duplicates is performed, use
        !          85001:      * updatemaintainer for that purpose.
1.1       misho    85002:      */
1.1.1.2 ! misho    85003:     function addMaintainer($role, $handle, $name, $email)
1.1       misho    85004:     {
1.1.1.2 ! misho    85005:         $this->_packageInfo['maintainers'][] =
        !          85006:             array('handle' => $handle, 'role' => $role, 'email' => $email, 'name' => $name);
        !          85007:         $this->_isValid = false;
1.1       misho    85008:     }
                   85009: 
1.1.1.2 ! misho    85010:     function updateMaintainer($role, $handle, $name, $email)
1.1       misho    85011:     {
1.1.1.2 ! misho    85012:         $found = false;
        !          85013:         if (!isset($this->_packageInfo['maintainers']) ||
        !          85014:               !is_array($this->_packageInfo['maintainers'])) {
        !          85015:             return $this->addMaintainer($role, $handle, $name, $email);
1.1       misho    85016:         }
1.1.1.2 ! misho    85017:         foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) {
        !          85018:             if ($maintainer['handle'] == $handle) {
        !          85019:                 $found = $i;
        !          85020:                 break;
        !          85021:             }
1.1       misho    85022:         }
1.1.1.2 ! misho    85023:         if ($found !== false) {
        !          85024:             unset($this->_packageInfo['maintainers'][$found]);
        !          85025:             $this->_packageInfo['maintainers'] =
        !          85026:                 array_values($this->_packageInfo['maintainers']);
1.1       misho    85027:         }
1.1.1.2 ! misho    85028:         $this->addMaintainer($role, $handle, $name, $email);
        !          85029:     }
1.1       misho    85030: 
1.1.1.2 ! misho    85031:     function deleteMaintainer($handle)
        !          85032:     {
        !          85033:         $found = false;
        !          85034:         foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) {
        !          85035:             if ($maintainer['handle'] == $handle) {
        !          85036:                 $found = $i;
        !          85037:                 break;
1.1       misho    85038:             }
1.1.1.2 ! misho    85039:         }
        !          85040:         if ($found !== false) {
        !          85041:             unset($this->_packageInfo['maintainers'][$found]);
        !          85042:             $this->_packageInfo['maintainers'] =
        !          85043:                 array_values($this->_packageInfo['maintainers']);
        !          85044:             return true;
        !          85045:         }
        !          85046:         return false;
        !          85047:     }
1.1       misho    85048: 
1.1.1.2 ! misho    85049:     function getState()
        !          85050:     {
        !          85051:         if (isset($this->_packageInfo['release_state'])) {
        !          85052:             return $this->_packageInfo['release_state'];
1.1       misho    85053:         }
1.1.1.2 ! misho    85054:         return false;
        !          85055:     }
1.1       misho    85056: 
1.1.1.2 ! misho    85057:     function setRawState($state)
        !          85058:     {
        !          85059:         $this->_packageInfo['release_state'] = $state;
        !          85060:     }
        !          85061: 
        !          85062:     function setState($state)
        !          85063:     {
        !          85064:         $this->_packageInfo['release_state'] = $state;
        !          85065:         $this->_isValid = false;
        !          85066:     }
        !          85067: 
        !          85068:     function getDate()
        !          85069:     {
        !          85070:         if (isset($this->_packageInfo['release_date'])) {
        !          85071:             return $this->_packageInfo['release_date'];
1.1       misho    85072:         }
1.1.1.2 ! misho    85073:         return false;
        !          85074:     }
1.1       misho    85075: 
1.1.1.2 ! misho    85076:     function setDate($date)
        !          85077:     {
        !          85078:         $this->_packageInfo['release_date'] = $date;
        !          85079:         $this->_isValid = false;
        !          85080:     }
1.1       misho    85081: 
1.1.1.2 ! misho    85082:     function getLicense()
        !          85083:     {
        !          85084:         if (isset($this->_packageInfo['release_license'])) {
        !          85085:             return $this->_packageInfo['release_license'];
1.1       misho    85086:         }
1.1.1.2 ! misho    85087:         return false;
        !          85088:     }
1.1       misho    85089: 
1.1.1.2 ! misho    85090:     function setLicense($date)
        !          85091:     {
        !          85092:         $this->_packageInfo['release_license'] = $date;
        !          85093:         $this->_isValid = false;
        !          85094:     }
        !          85095: 
        !          85096:     function getSummary()
        !          85097:     {
        !          85098:         if (isset($this->_packageInfo['summary'])) {
        !          85099:             return $this->_packageInfo['summary'];
1.1       misho    85100:         }
1.1.1.2 ! misho    85101:         return false;
        !          85102:     }
1.1       misho    85103: 
1.1.1.2 ! misho    85104:     function setSummary($summary)
        !          85105:     {
        !          85106:         $this->_packageInfo['summary'] = $summary;
        !          85107:         $this->_isValid = false;
        !          85108:     }
1.1       misho    85109: 
1.1.1.2 ! misho    85110:     function getDescription()
        !          85111:     {
        !          85112:         if (isset($this->_packageInfo['description'])) {
        !          85113:             return $this->_packageInfo['description'];
        !          85114:         }
        !          85115:         return false;
        !          85116:     }
1.1       misho    85117: 
1.1.1.2 ! misho    85118:     function setDescription($desc)
        !          85119:     {
        !          85120:         $this->_packageInfo['description'] = $desc;
        !          85121:         $this->_isValid = false;
        !          85122:     }
1.1       misho    85123: 
1.1.1.2 ! misho    85124:     function getNotes()
        !          85125:     {
        !          85126:         if (isset($this->_packageInfo['release_notes'])) {
        !          85127:             return $this->_packageInfo['release_notes'];
1.1       misho    85128:         }
1.1.1.2 ! misho    85129:         return false;
        !          85130:     }
1.1       misho    85131: 
1.1.1.2 ! misho    85132:     function setNotes($notes)
        !          85133:     {
        !          85134:         $this->_packageInfo['release_notes'] = $notes;
        !          85135:         $this->_isValid = false;
1.1       misho    85136:     }
                   85137: 
1.1.1.2 ! misho    85138:     function getDeps()
1.1       misho    85139:     {
1.1.1.2 ! misho    85140:         if (isset($this->_packageInfo['release_deps'])) {
        !          85141:             return $this->_packageInfo['release_deps'];
1.1       misho    85142:         }
1.1.1.2 ! misho    85143:         return false;
1.1       misho    85144:     }
                   85145: 
                   85146:     /**
1.1.1.2 ! misho    85147:      * Reset dependencies prior to adding new ones
1.1       misho    85148:      */
1.1.1.2 ! misho    85149:     function clearDeps()
1.1       misho    85150:     {
1.1.1.2 ! misho    85151:         unset($this->_packageInfo['release_deps']);
        !          85152:     }
        !          85153: 
        !          85154:     function addPhpDep($version, $rel)
        !          85155:     {
        !          85156:         $this->_isValid = false;
        !          85157:         $this->_packageInfo['release_deps'][] =
        !          85158:             array('type' => 'php',
        !          85159:                   'rel' => $rel,
        !          85160:                   'version' => $version);
        !          85161:     }
        !          85162: 
        !          85163:     function addPackageDep($name, $version, $rel, $optional = 'no')
        !          85164:     {
        !          85165:         $this->_isValid = false;
        !          85166:         $dep =
        !          85167:             array('type' => 'pkg',
        !          85168:                   'name' => $name,
        !          85169:                   'rel' => $rel,
        !          85170:                   'optional' => $optional);
        !          85171:         if ($rel != 'has' && $rel != 'not') {
        !          85172:             $dep['version'] = $version;
1.1       misho    85173:         }
1.1.1.2 ! misho    85174:         $this->_packageInfo['release_deps'][] = $dep;
        !          85175:     }
1.1       misho    85176: 
1.1.1.2 ! misho    85177:     function addExtensionDep($name, $version, $rel, $optional = 'no')
        !          85178:     {
        !          85179:         $this->_isValid = false;
        !          85180:         $this->_packageInfo['release_deps'][] =
        !          85181:             array('type' => 'ext',
        !          85182:                   'name' => $name,
        !          85183:                   'rel' => $rel,
        !          85184:                   'version' => $version,
        !          85185:                   'optional' => $optional);
1.1       misho    85186:     }
                   85187: 
                   85188:     /**
1.1.1.2 ! misho    85189:      * WARNING - do not use this function directly unless you know what you're doing
1.1       misho    85190:      */
1.1.1.2 ! misho    85191:     function setDeps($deps)
1.1       misho    85192:     {
1.1.1.2 ! misho    85193:         $this->_packageInfo['release_deps'] = $deps;
        !          85194:     }
1.1       misho    85195: 
1.1.1.2 ! misho    85196:     function hasDeps()
        !          85197:     {
        !          85198:         return isset($this->_packageInfo['release_deps']) &&
        !          85199:             count($this->_packageInfo['release_deps']);
        !          85200:     }
1.1       misho    85201: 
1.1.1.2 ! misho    85202:     function getDependencyGroup($group)
        !          85203:     {
        !          85204:         return false;
        !          85205:     }
1.1       misho    85206: 
1.1.1.2 ! misho    85207:     function isCompatible($pf)
        !          85208:     {
        !          85209:         return false;
        !          85210:     }
1.1       misho    85211: 
1.1.1.2 ! misho    85212:     function isSubpackageOf($p)
        !          85213:     {
        !          85214:         return $p->isSubpackage($this);
        !          85215:     }
1.1       misho    85216: 
1.1.1.2 ! misho    85217:     function isSubpackage($p)
        !          85218:     {
        !          85219:         return false;
        !          85220:     }
1.1       misho    85221: 
1.1.1.2 ! misho    85222:     function dependsOn($package, $channel)
        !          85223:     {
        !          85224:         if (strtolower($channel) != 'pear.php.net') {
        !          85225:             return false;
        !          85226:         }
        !          85227:         if (!($deps = $this->getDeps())) {
        !          85228:             return false;
        !          85229:         }
        !          85230:         foreach ($deps as $dep) {
        !          85231:             if ($dep['type'] != 'pkg') {
        !          85232:                 continue;
        !          85233:             }
        !          85234:             if (strtolower($dep['name']) == strtolower($package)) {
        !          85235:                 return true;
        !          85236:             }
        !          85237:         }
        !          85238:         return false;
1.1       misho    85239:     }
1.1.1.2 ! misho    85240: 
        !          85241:     function getConfigureOptions()
1.1       misho    85242:     {
1.1.1.2 ! misho    85243:         if (isset($this->_packageInfo['configure_options'])) {
        !          85244:             return $this->_packageInfo['configure_options'];
        !          85245:         }
        !          85246:         return false;
1.1       misho    85247:     }
                   85248: 
1.1.1.2 ! misho    85249:     function hasConfigureOptions()
1.1       misho    85250:     {
1.1.1.2 ! misho    85251:         return isset($this->_packageInfo['configure_options']) &&
        !          85252:             count($this->_packageInfo['configure_options']);
1.1       misho    85253:     }
                   85254: 
1.1.1.2 ! misho    85255:     function addConfigureOption($name, $prompt, $default = false)
1.1       misho    85256:     {
1.1.1.2 ! misho    85257:         $o = array('name' => $name, 'prompt' => $prompt);
        !          85258:         if ($default !== false) {
        !          85259:             $o['default'] = $default;
1.1       misho    85260:         }
1.1.1.2 ! misho    85261:         if (!isset($this->_packageInfo['configure_options'])) {
        !          85262:             $this->_packageInfo['configure_options'] = array();
1.1       misho    85263:         }
1.1.1.2 ! misho    85264:         $this->_packageInfo['configure_options'][] = $o;
        !          85265:     }
        !          85266: 
        !          85267:     function clearConfigureOptions()
        !          85268:     {
        !          85269:         unset($this->_packageInfo['configure_options']);
        !          85270:     }
        !          85271: 
        !          85272:     function getProvides()
        !          85273:     {
        !          85274:         if (isset($this->_packageInfo['provides'])) {
        !          85275:             return $this->_packageInfo['provides'];
1.1       misho    85276:         }
1.1.1.2 ! misho    85277:         return false;
        !          85278:     }
        !          85279: 
        !          85280:     function getProvidesExtension()
        !          85281:     {
        !          85282:         return false;
        !          85283:     }
        !          85284: 
        !          85285:     function addFile($dir, $file, $attrs)
        !          85286:     {
        !          85287:         $dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir);
        !          85288:         if ($dir == '/' || $dir == '') {
        !          85289:             $dir = '';
1.1       misho    85290:         } else {
1.1.1.2 ! misho    85291:             $dir .= '/';
1.1       misho    85292:         }
1.1.1.2 ! misho    85293:         $file = $dir . $file;
        !          85294:         $file = preg_replace('![\\/]+!', '/', $file);
        !          85295:         $this->_packageInfo['filelist'][$file] = $attrs;
        !          85296:     }
1.1       misho    85297: 
1.1.1.2 ! misho    85298:     function getInstallationFilelist()
        !          85299:     {
        !          85300:         return $this->getFilelist();
        !          85301:     }
        !          85302: 
        !          85303:     function getFilelist()
        !          85304:     {
        !          85305:         if (isset($this->_packageInfo['filelist'])) {
        !          85306:             return $this->_packageInfo['filelist'];
1.1       misho    85307:         }
1.1.1.2 ! misho    85308:         return false;
1.1       misho    85309:     }
                   85310: 
1.1.1.2 ! misho    85311:     function setFileAttribute($file, $attr, $value)
1.1       misho    85312:     {
1.1.1.2 ! misho    85313:         $this->_packageInfo['filelist'][$file][$attr] = $value;
        !          85314:     }
        !          85315: 
        !          85316:     function resetFilelist()
        !          85317:     {
        !          85318:         $this->_packageInfo['filelist'] = array();
        !          85319:     }
        !          85320: 
        !          85321:     function setInstalledAs($file, $path)
        !          85322:     {
        !          85323:         if ($path) {
        !          85324:             return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
1.1       misho    85325:         }
1.1.1.2 ! misho    85326:         unset($this->_packageInfo['filelist'][$file]['installed_as']);
        !          85327:     }
        !          85328: 
        !          85329:     function installedFile($file, $atts)
        !          85330:     {
        !          85331:         if (isset($this->_packageInfo['filelist'][$file])) {
        !          85332:             $this->_packageInfo['filelist'][$file] =
        !          85333:                 array_merge($this->_packageInfo['filelist'][$file], $atts);
        !          85334:         } else {
        !          85335:             $this->_packageInfo['filelist'][$file] = $atts;
1.1       misho    85336:         }
1.1.1.2 ! misho    85337:     }
        !          85338: 
        !          85339:     function getChangelog()
        !          85340:     {
        !          85341:         if (isset($this->_packageInfo['changelog'])) {
        !          85342:             return $this->_packageInfo['changelog'];
1.1       misho    85343:         }
1.1.1.2 ! misho    85344:         return false;
        !          85345:     }
        !          85346: 
        !          85347:     function getPackagexmlVersion()
        !          85348:     {
        !          85349:         return '1.0';
1.1       misho    85350:     }
                   85351: 
                   85352:     /**
1.1.1.2 ! misho    85353:      * Wrapper to {@link PEAR_ErrorStack::getErrors()}
        !          85354:      * @param boolean determines whether to purge the error stack after retrieving
        !          85355:      * @return array
        !          85356:      */
        !          85357:     function getValidationWarnings($purge = true)
        !          85358:     {
        !          85359:         return $this->_stack->getErrors($purge);
        !          85360:     }
        !          85361: 
        !          85362:     // }}}
        !          85363:     /**
        !          85364:      * Validation error.  Also marks the object contents as invalid
        !          85365:      * @param error code
        !          85366:      * @param array error information
1.1       misho    85367:      * @access private
                   85368:      */
1.1.1.2 ! misho    85369:     function _validateError($code, $params = array())
1.1       misho    85370:     {
1.1.1.2 ! misho    85371:         $this->_stack->push($code, 'error', $params, false, false, debug_backtrace());
        !          85372:         $this->_isValid = false;
1.1       misho    85373:     }
                   85374: 
                   85375:     /**
1.1.1.2 ! misho    85376:      * Validation warning.  Does not mark the object contents invalid.
        !          85377:      * @param error code
        !          85378:      * @param array error information
        !          85379:      * @access private
        !          85380:      */
        !          85381:     function _validateWarning($code, $params = array())
        !          85382:     {
        !          85383:         $this->_stack->push($code, 'warning', $params, false, false, debug_backtrace());
        !          85384:     }
        !          85385: 
        !          85386:     /**
        !          85387:      * @param integer error code
        !          85388:      * @access protected
        !          85389:      */
        !          85390:     function _getErrorMessage()
        !          85391:     {
        !          85392:         return array(
        !          85393:                 PEAR_PACKAGEFILE_ERROR_NO_NAME =>
        !          85394:                     'Missing Package Name',
        !          85395:                 PEAR_PACKAGEFILE_ERROR_NO_SUMMARY =>
        !          85396:                     'No summary found',
        !          85397:                 PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY =>
        !          85398:                     'Summary should be on one line',
        !          85399:                 PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION =>
        !          85400:                     'Missing description',
        !          85401:                 PEAR_PACKAGEFILE_ERROR_NO_LICENSE =>
        !          85402:                     'Missing license',
        !          85403:                 PEAR_PACKAGEFILE_ERROR_NO_VERSION =>
        !          85404:                     'No release version found',
        !          85405:                 PEAR_PACKAGEFILE_ERROR_NO_STATE =>
        !          85406:                     'No release state found',
        !          85407:                 PEAR_PACKAGEFILE_ERROR_NO_DATE =>
        !          85408:                     'No release date found',
        !          85409:                 PEAR_PACKAGEFILE_ERROR_NO_NOTES =>
        !          85410:                     'No release notes found',
        !          85411:                 PEAR_PACKAGEFILE_ERROR_NO_LEAD =>
        !          85412:                     'Package must have at least one lead maintainer',
        !          85413:                 PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS =>
        !          85414:                     'No maintainers found, at least one must be defined',
        !          85415:                 PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE =>
        !          85416:                     'Maintainer %index% has no handle (user ID at channel server)',
        !          85417:                 PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE =>
        !          85418:                     'Maintainer %index% has no role',
        !          85419:                 PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME =>
        !          85420:                     'Maintainer %index% has no name',
        !          85421:                 PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL =>
        !          85422:                     'Maintainer %index% has no email',
        !          85423:                 PEAR_PACKAGEFILE_ERROR_NO_DEPNAME =>
        !          85424:                     'Dependency %index% is not a php dependency, and has no name',
        !          85425:                 PEAR_PACKAGEFILE_ERROR_NO_DEPREL =>
        !          85426:                     'Dependency %index% has no relation (rel)',
        !          85427:                 PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE =>
        !          85428:                     'Dependency %index% has no type',
        !          85429:                 PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED =>
        !          85430:                     'PHP Dependency %index% has a name attribute of "%name%" which will be' .
        !          85431:                         ' ignored!',
        !          85432:                 PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION =>
        !          85433:                     'Dependency %index% is not a rel="has" or rel="not" dependency, ' .
        !          85434:                         'and has no version',
        !          85435:                 PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION =>
        !          85436:                     'Dependency %index% is a type="php" dependency, ' .
        !          85437:                         'and has no version',
        !          85438:                 PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED =>
        !          85439:                     'Dependency %index% is a rel="%rel%" dependency, versioning is ignored',
        !          85440:                 PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL =>
        !          85441:                     'Dependency %index% has invalid optional value "%opt%", should be yes or no',
        !          85442:                 PEAR_PACKAGEFILE_PHP_NO_NOT =>
        !          85443:                     'Dependency %index%: php dependencies cannot use "not" rel, use "ne"' .
        !          85444:                         ' to exclude specific versions',
        !          85445:                 PEAR_PACKAGEFILE_ERROR_NO_CONFNAME =>
        !          85446:                     'Configure Option %index% has no name',
        !          85447:                 PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT =>
        !          85448:                     'Configure Option %index% has no prompt',
        !          85449:                 PEAR_PACKAGEFILE_ERROR_NO_FILES =>
        !          85450:                     'No files in <filelist> section of package.xml',
        !          85451:                 PEAR_PACKAGEFILE_ERROR_NO_FILEROLE =>
        !          85452:                     'File "%file%" has no role, expecting one of "%roles%"',
        !          85453:                 PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE =>
        !          85454:                     'File "%file%" has invalid role "%role%", expecting one of "%roles%"',
        !          85455:                 PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME =>
        !          85456:                     'File "%file%" cannot start with ".", cannot package or install',
        !          85457:                 PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE =>
        !          85458:                     'Parser error: invalid PHP found in file "%file%"',
        !          85459:                 PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX =>
        !          85460:                     'in %file%: %type% "%name%" not prefixed with package name "%package%"',
        !          85461:                 PEAR_PACKAGEFILE_ERROR_INVALID_FILE =>
        !          85462:                     'Parser error: invalid PHP file "%file%"',
        !          85463:                 PEAR_PACKAGEFILE_ERROR_CHANNELVAL =>
        !          85464:                     'Channel validator error: field "%field%" - %reason%',
        !          85465:                 PEAR_PACKAGEFILE_ERROR_PHP5 =>
        !          85466:                     'Error, PHP5 token encountered in %file%, analysis should be in PHP5',
        !          85467:                 PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND =>
        !          85468:                     'File "%file%" in package.xml does not exist',
        !          85469:                 PEAR_PACKAGEFILE_ERROR_NON_ISO_CHARS =>
        !          85470:                     'Package.xml contains non-ISO-8859-1 characters, and may not validate',
        !          85471:             );
        !          85472:     }
        !          85473: 
        !          85474:     /**
        !          85475:      * Validate XML package definition file.
1.1       misho    85476:      *
1.1.1.2 ! misho    85477:      * @access public
        !          85478:      * @return boolean
1.1       misho    85479:      */
1.1.1.2 ! misho    85480:     function validate($state = PEAR_VALIDATE_NORMAL, $nofilechecking = false)
1.1       misho    85481:     {
1.1.1.2 ! misho    85482:         if (($this->_isValid & $state) == $state) {
        !          85483:             return true;
1.1       misho    85484:         }
1.1.1.2 ! misho    85485:         $this->_isValid = true;
        !          85486:         $info = $this->_packageInfo;
        !          85487:         if (empty($info['package'])) {
        !          85488:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NAME);
        !          85489:             $this->_packageName = $pn = 'unknown';
        !          85490:         } else {
        !          85491:             $this->_packageName = $pn = $info['package'];
1.1       misho    85492:         }
1.1.1.2 ! misho    85493: 
        !          85494:         if (empty($info['summary'])) {
        !          85495:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_SUMMARY);
        !          85496:         } elseif (strpos(trim($info['summary']), "\n") !== false) {
        !          85497:             $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY,
        !          85498:                 array('summary' => $info['summary']));
        !          85499:         }
        !          85500:         if (empty($info['description'])) {
        !          85501:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION);
        !          85502:         }
        !          85503:         if (empty($info['release_license'])) {
        !          85504:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LICENSE);
        !          85505:         }
        !          85506:         if (empty($info['version'])) {
        !          85507:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_VERSION);
        !          85508:         }
        !          85509:         if (empty($info['release_state'])) {
        !          85510:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_STATE);
        !          85511:         }
        !          85512:         if (empty($info['release_date'])) {
        !          85513:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DATE);
        !          85514:         }
        !          85515:         if (empty($info['release_notes'])) {
        !          85516:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NOTES);
        !          85517:         }
        !          85518:         if (empty($info['maintainers'])) {
        !          85519:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS);
        !          85520:         } else {
        !          85521:             $haslead = false;
        !          85522:             $i = 1;
        !          85523:             foreach ($info['maintainers'] as $m) {
        !          85524:                 if (empty($m['handle'])) {
        !          85525:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE,
        !          85526:                         array('index' => $i));
        !          85527:                 }
        !          85528:                 if (empty($m['role'])) {
        !          85529:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE,
        !          85530:                         array('index' => $i, 'roles' => PEAR_Common::getUserRoles()));
        !          85531:                 } elseif ($m['role'] == 'lead') {
        !          85532:                     $haslead = true;
        !          85533:                 }
        !          85534:                 if (empty($m['name'])) {
        !          85535:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME,
        !          85536:                         array('index' => $i));
        !          85537:                 }
        !          85538:                 if (empty($m['email'])) {
        !          85539:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL,
        !          85540:                         array('index' => $i));
        !          85541:                 }
        !          85542:                 $i++;
        !          85543:             }
        !          85544:             if (!$haslead) {
        !          85545:                 $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LEAD);
        !          85546:             }
        !          85547:         }
        !          85548:         if (!empty($info['release_deps'])) {
        !          85549:             $i = 1;
        !          85550:             foreach ($info['release_deps'] as $d) {
        !          85551:                 if (!isset($d['type']) || empty($d['type'])) {
        !          85552:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE,
        !          85553:                         array('index' => $i, 'types' => PEAR_Common::getDependencyTypes()));
        !          85554:                     continue;
        !          85555:                 }
        !          85556:                 if (!isset($d['rel']) || empty($d['rel'])) {
        !          85557:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPREL,
        !          85558:                         array('index' => $i, 'rels' => PEAR_Common::getDependencyRelations()));
        !          85559:                     continue;
        !          85560:                 }
        !          85561:                 if (!empty($d['optional'])) {
        !          85562:                     if (!in_array($d['optional'], array('yes', 'no'))) {
        !          85563:                         $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL,
        !          85564:                             array('index' => $i, 'opt' => $d['optional']));
        !          85565:                     }
        !          85566:                 }
        !          85567:                 if ($d['rel'] != 'has' && $d['rel'] != 'not' && empty($d['version'])) {
        !          85568:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION,
        !          85569:                         array('index' => $i));
        !          85570:                 } elseif (($d['rel'] == 'has' || $d['rel'] == 'not') && !empty($d['version'])) {
        !          85571:                     $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED,
        !          85572:                         array('index' => $i, 'rel' => $d['rel']));
        !          85573:                 }
        !          85574:                 if ($d['type'] == 'php' && !empty($d['name'])) {
        !          85575:                     $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED,
        !          85576:                         array('index' => $i, 'name' => $d['name']));
        !          85577:                 } elseif ($d['type'] != 'php' && empty($d['name'])) {
        !          85578:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPNAME,
        !          85579:                         array('index' => $i));
        !          85580:                 }
        !          85581:                 if ($d['type'] == 'php' && empty($d['version'])) {
        !          85582:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION,
        !          85583:                         array('index' => $i));
        !          85584:                 }
        !          85585:                 if (($d['rel'] == 'not') && ($d['type'] == 'php')) {
        !          85586:                     $this->_validateError(PEAR_PACKAGEFILE_PHP_NO_NOT,
        !          85587:                         array('index' => $i));
        !          85588:                 }
        !          85589:                 $i++;
        !          85590:             }
        !          85591:         }
        !          85592:         if (!empty($info['configure_options'])) {
        !          85593:             $i = 1;
        !          85594:             foreach ($info['configure_options'] as $c) {
        !          85595:                 if (empty($c['name'])) {
        !          85596:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFNAME,
        !          85597:                         array('index' => $i));
        !          85598:                 }
        !          85599:                 if (empty($c['prompt'])) {
        !          85600:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT,
        !          85601:                         array('index' => $i));
        !          85602:                 }
        !          85603:                 $i++;
        !          85604:             }
        !          85605:         }
        !          85606:         if (empty($info['filelist'])) {
        !          85607:             $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILES);
        !          85608:             $errors[] = 'no files';
        !          85609:         } else {
        !          85610:             foreach ($info['filelist'] as $file => $fa) {
        !          85611:                 if (empty($fa['role'])) {
        !          85612:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILEROLE,
        !          85613:                         array('file' => $file, 'roles' => PEAR_Common::getFileRoles()));
        !          85614:                     continue;
        !          85615:                 } elseif (!in_array($fa['role'], PEAR_Common::getFileRoles())) {
        !          85616:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE,
        !          85617:                         array('file' => $file, 'role' => $fa['role'], 'roles' => PEAR_Common::getFileRoles()));
        !          85618:                 }
        !          85619:                 if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', str_replace('\\', '/', $file))) {
        !          85620:                     // file contains .. parent directory or . cur directory references
        !          85621:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
        !          85622:                         array('file' => $file));
        !          85623:                 }
        !          85624:                 if (isset($fa['install-as']) &&
        !          85625:                       preg_match('~/\.\.?(/|\\z)|^\.\.?/~', 
        !          85626:                                  str_replace('\\', '/', $fa['install-as']))) {
        !          85627:                     // install-as contains .. parent directory or . cur directory references
        !          85628:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
        !          85629:                         array('file' => $file . ' [installed as ' . $fa['install-as'] . ']'));
        !          85630:                 }
        !          85631:                 if (isset($fa['baseinstalldir']) &&
        !          85632:                       preg_match('~/\.\.?(/|\\z)|^\.\.?/~', 
        !          85633:                                  str_replace('\\', '/', $fa['baseinstalldir']))) {
        !          85634:                     // install-as contains .. parent directory or . cur directory references
        !          85635:                     $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
        !          85636:                         array('file' => $file . ' [baseinstalldir ' . $fa['baseinstalldir'] . ']'));
        !          85637:                 }
        !          85638:             }
        !          85639:         }
        !          85640:         if (isset($this->_registry) && $this->_isValid) {
        !          85641:             $chan = $this->_registry->getChannel('pear.php.net');
        !          85642:             if (PEAR::isError($chan)) {
        !          85643:                 $this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $chan->getMessage());
        !          85644:                 return $this->_isValid = 0;
        !          85645:             }
        !          85646:             $validator = $chan->getValidationObject();
        !          85647:             $validator->setPackageFile($this);
        !          85648:             $validator->validate($state);
        !          85649:             $failures = $validator->getFailures();
        !          85650:             foreach ($failures['errors'] as $error) {
        !          85651:                 $this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $error);
        !          85652:             }
        !          85653:             foreach ($failures['warnings'] as $warning) {
        !          85654:                 $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $warning);
1.1       misho    85655:             }
                   85656:         }
1.1.1.2 ! misho    85657:         if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$nofilechecking) {
        !          85658:             if ($this->_analyzePhpFiles()) {
        !          85659:                 $this->_isValid = true;
1.1       misho    85660:             }
                   85661:         }
1.1.1.2 ! misho    85662:         if ($this->_isValid) {
        !          85663:             return $this->_isValid = $state;
        !          85664:         }
        !          85665:         return $this->_isValid = 0;
1.1       misho    85666:     }
                   85667: 
1.1.1.2 ! misho    85668:     function _analyzePhpFiles()
1.1       misho    85669:     {
1.1.1.2 ! misho    85670:         if (!$this->_isValid) {
        !          85671:             return false;
1.1       misho    85672:         }
1.1.1.2 ! misho    85673:         if (!isset($this->_packageFile)) {
        !          85674:             return false;
1.1       misho    85675:         }
1.1.1.2 ! misho    85676:         $dir_prefix = dirname($this->_packageFile);
        !          85677:         $common = new PEAR_Common;
        !          85678:         $log = isset($this->_logger) ? array(&$this->_logger, 'log') :
        !          85679:             array($common, 'log');
        !          85680:         $info = $this->getFilelist();
        !          85681:         foreach ($info as $file => $fa) {
        !          85682:             if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) {
        !          85683:                 $this->_validateError(PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND,
        !          85684:                     array('file' => realpath($dir_prefix) . DIRECTORY_SEPARATOR . $file));
        !          85685:                 continue;
1.1       misho    85686:             }
1.1.1.2 ! misho    85687:             if ($fa['role'] == 'php' && $dir_prefix) {
        !          85688:                 call_user_func_array($log, array(1, "Analyzing $file"));
        !          85689:                 $srcinfo = $this->_analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file);
        !          85690:                 if ($srcinfo) {
        !          85691:                     $this->_buildProvidesArray($srcinfo);
1.1       misho    85692:                 }
                   85693:             }
                   85694:         }
1.1.1.2 ! misho    85695:         $this->_packageName = $pn = $this->getPackage();
        !          85696:         $pnl = strlen($pn);
        !          85697:         if (isset($this->_packageInfo['provides'])) {
        !          85698:             foreach ((array) $this->_packageInfo['provides'] as $key => $what) {
        !          85699:                 if (isset($what['explicit'])) {
        !          85700:                     // skip conformance checks if the provides entry is
        !          85701:                     // specified in the package.xml file
        !          85702:                     continue;
1.1       misho    85703:                 }
1.1.1.2 ! misho    85704:                 extract($what);
        !          85705:                 if ($type == 'class') {
        !          85706:                     if (!strncasecmp($name, $pn, $pnl)) {
        !          85707:                         continue;
1.1       misho    85708:                     }
1.1.1.2 ! misho    85709:                     $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX,
        !          85710:                         array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn));
        !          85711:                 } elseif ($type == 'function') {
        !          85712:                     if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) {
        !          85713:                         continue;
1.1       misho    85714:                     }
1.1.1.2 ! misho    85715:                     $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX,
        !          85716:                         array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn));
1.1       misho    85717:                 }
                   85718:             }
                   85719:         }
1.1.1.2 ! misho    85720:         return $this->_isValid;
1.1       misho    85721:     }
                   85722: 
                   85723:     /**
1.1.1.2 ! misho    85724:      * Get the default xml generator object
        !          85725:      *
        !          85726:      * @return PEAR_PackageFile_Generator_v1
1.1       misho    85727:      */
1.1.1.2 ! misho    85728:     function &getDefaultGenerator()
1.1       misho    85729:     {
1.1.1.2 ! misho    85730:         if (!class_exists('PEAR_PackageFile_Generator_v1')) {
        !          85731:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/Generator/v1.php';
1.1       misho    85732:         }
1.1.1.2 ! misho    85733:         $a = &new PEAR_PackageFile_Generator_v1($this);
        !          85734:         return $a;
1.1       misho    85735:     }
                   85736: 
                   85737:     /**
1.1.1.2 ! misho    85738:      * Get the contents of a file listed within the package.xml
1.1       misho    85739:      * @param string
1.1.1.2 ! misho    85740:      * @return string
1.1       misho    85741:      */
1.1.1.2 ! misho    85742:     function getFileContents($file)
1.1       misho    85743:     {
1.1.1.2 ! misho    85744:         if ($this->_archiveFile == $this->_packageFile) { // unpacked
        !          85745:             $dir = dirname($this->_packageFile);
        !          85746:             $file = $dir . DIRECTORY_SEPARATOR . $file;
        !          85747:             $file = str_replace(array('/', '\\'),
        !          85748:                 array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file);
        !          85749:             if (file_exists($file) && is_readable($file)) {
        !          85750:                 return implode('', file($file));
1.1       misho    85751:             }
1.1.1.2 ! misho    85752:         } else { // tgz
        !          85753:             if (!class_exists('Archive_Tar')) {
        !          85754:                 require_once 'phar://install-pear-nozlib.phar/' . 'Archive/Tar.php';
1.1       misho    85755:             }
1.1.1.2 ! misho    85756:             $tar = &new Archive_Tar($this->_archiveFile);
        !          85757:             $tar->pushErrorHandling(PEAR_ERROR_RETURN);
        !          85758:             if ($file != 'package.xml' && $file != 'package2.xml') {
        !          85759:                 $file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file;
        !          85760:             }
        !          85761:             $file = $tar->extractInString($file);
        !          85762:             $tar->popErrorHandling();
        !          85763:             if (PEAR::isError($file)) {
        !          85764:                 return PEAR::raiseError("Cannot locate file '$file' in archive");
        !          85765:             }
        !          85766:             return $file;
1.1       misho    85767:         }
                   85768:     }
                   85769: 
1.1.1.2 ! misho    85770:     // {{{ analyzeSourceCode()
1.1       misho    85771:     /**
1.1.1.2 ! misho    85772:      * Analyze the source code of the given PHP file
        !          85773:      *
        !          85774:      * @param  string Filename of the PHP file
        !          85775:      * @return mixed
1.1       misho    85776:      * @access private
                   85777:      */
1.1.1.2 ! misho    85778:     function _analyzeSourceCode($file)
1.1       misho    85779:     {
1.1.1.2 ! misho    85780:         if (!function_exists("token_get_all")) {
        !          85781:             return false;
1.1       misho    85782:         }
1.1.1.2 ! misho    85783:         if (!defined('T_DOC_COMMENT')) {
        !          85784:             define('T_DOC_COMMENT', T_COMMENT);
1.1       misho    85785:         }
1.1.1.2 ! misho    85786:         if (!defined('T_INTERFACE')) {
        !          85787:             define('T_INTERFACE', -1);
1.1       misho    85788:         }
1.1.1.2 ! misho    85789:         if (!defined('T_IMPLEMENTS')) {
        !          85790:             define('T_IMPLEMENTS', -1);
1.1       misho    85791:         }
1.1.1.2 ! misho    85792:         if (!$fp = @fopen($file, "r")) {
        !          85793:             return false;
        !          85794:         }
        !          85795:         fclose($fp);
        !          85796:         $contents = file_get_contents($file);
        !          85797:         $tokens = token_get_all($contents);
        !          85798: /*
        !          85799:         for ($i = 0; $i < sizeof($tokens); $i++) {
        !          85800:             @list($token, $data) = $tokens[$i];
        !          85801:             if (is_string($token)) {
        !          85802:                 var_dump($token);
        !          85803:             } else {
        !          85804:                 print token_name($token) . ' ';
        !          85805:                 var_dump(rtrim($data));
        !          85806:             }
        !          85807:         }
        !          85808: */
        !          85809:         $look_for = 0;
        !          85810:         $paren_level = 0;
        !          85811:         $bracket_level = 0;
        !          85812:         $brace_level = 0;
        !          85813:         $lastphpdoc = '';
        !          85814:         $current_class = '';
        !          85815:         $current_interface = '';
        !          85816:         $current_class_level = -1;
        !          85817:         $current_function = '';
        !          85818:         $current_function_level = -1;
        !          85819:         $declared_classes = array();
        !          85820:         $declared_interfaces = array();
        !          85821:         $declared_functions = array();
        !          85822:         $declared_methods = array();
        !          85823:         $used_classes = array();
        !          85824:         $used_functions = array();
        !          85825:         $extends = array();
        !          85826:         $implements = array();
        !          85827:         $nodeps = array();
        !          85828:         $inquote = false;
        !          85829:         $interface = false;
        !          85830:         for ($i = 0; $i < sizeof($tokens); $i++) {
        !          85831:             if (is_array($tokens[$i])) {
        !          85832:                 list($token, $data) = $tokens[$i];
        !          85833:             } else {
        !          85834:                 $token = $tokens[$i];
        !          85835:                 $data = '';
        !          85836:             }
        !          85837:             if ($inquote) {
        !          85838:                 if ($token != '"' && $token != T_END_HEREDOC) {
        !          85839:                     continue;
        !          85840:                 } else {
        !          85841:                     $inquote = false;
        !          85842:                     continue;
1.1       misho    85843:                 }
                   85844:             }
1.1.1.2 ! misho    85845:             switch ($token) {
        !          85846:                 case T_WHITESPACE :
        !          85847:                     continue;
        !          85848:                 case ';':
        !          85849:                     if ($interface) {
        !          85850:                         $current_function = '';
        !          85851:                         $current_function_level = -1;
        !          85852:                     }
        !          85853:                     break;
        !          85854:                 case '"':
        !          85855:                 case T_START_HEREDOC:
        !          85856:                     $inquote = true;
        !          85857:                     break;
        !          85858:                 case T_CURLY_OPEN:
        !          85859:                 case T_DOLLAR_OPEN_CURLY_BRACES:
        !          85860:                 case '{': $brace_level++; continue 2;
        !          85861:                 case '}':
        !          85862:                     $brace_level--;
        !          85863:                     if ($current_class_level == $brace_level) {
        !          85864:                         $current_class = '';
        !          85865:                         $current_class_level = -1;
        !          85866:                     }
        !          85867:                     if ($current_function_level == $brace_level) {
        !          85868:                         $current_function = '';
        !          85869:                         $current_function_level = -1;
        !          85870:                     }
        !          85871:                     continue 2;
        !          85872:                 case '[': $bracket_level++; continue 2;
        !          85873:                 case ']': $bracket_level--; continue 2;
        !          85874:                 case '(': $paren_level++;   continue 2;
        !          85875:                 case ')': $paren_level--;   continue 2;
        !          85876:                 case T_INTERFACE:
        !          85877:                     $interface = true;
        !          85878:                 case T_CLASS:
        !          85879:                     if (($current_class_level != -1) || ($current_function_level != -1)) {
        !          85880:                         $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE,
        !          85881:                             array('file' => $file));
        !          85882:                         return false;
        !          85883:                     }
        !          85884:                 case T_FUNCTION:
        !          85885:                 case T_NEW:
        !          85886:                 case T_EXTENDS:
        !          85887:                 case T_IMPLEMENTS:
        !          85888:                     $look_for = $token;
        !          85889:                     continue 2;
        !          85890:                 case T_STRING:
        !          85891:                     if (version_compare(zend_version(), '2.0', '<')) {
        !          85892:                         if (in_array(strtolower($data),
        !          85893:                             array('public', 'private', 'protected', 'abstract',
        !          85894:                                   'interface', 'implements', 'throw') 
        !          85895:                                  )) {
        !          85896:                             $this->_validateWarning(PEAR_PACKAGEFILE_ERROR_PHP5,
        !          85897:                                 array($file));
        !          85898:                         }
        !          85899:                     }
        !          85900:                     if ($look_for == T_CLASS) {
        !          85901:                         $current_class = $data;
        !          85902:                         $current_class_level = $brace_level;
        !          85903:                         $declared_classes[] = $current_class;
        !          85904:                     } elseif ($look_for == T_INTERFACE) {
        !          85905:                         $current_interface = $data;
        !          85906:                         $current_class_level = $brace_level;
        !          85907:                         $declared_interfaces[] = $current_interface;
        !          85908:                     } elseif ($look_for == T_IMPLEMENTS) {
        !          85909:                         $implements[$current_class] = $data;
        !          85910:                     } elseif ($look_for == T_EXTENDS) {
        !          85911:                         $extends[$current_class] = $data;
        !          85912:                     } elseif ($look_for == T_FUNCTION) {
        !          85913:                         if ($current_class) {
        !          85914:                             $current_function = "$current_class::$data";
        !          85915:                             $declared_methods[$current_class][] = $data;
        !          85916:                         } elseif ($current_interface) {
        !          85917:                             $current_function = "$current_interface::$data";
        !          85918:                             $declared_methods[$current_interface][] = $data;
        !          85919:                         } else {
        !          85920:                             $current_function = $data;
        !          85921:                             $declared_functions[] = $current_function;
        !          85922:                         }
        !          85923:                         $current_function_level = $brace_level;
        !          85924:                         $m = array();
        !          85925:                     } elseif ($look_for == T_NEW) {
        !          85926:                         $used_classes[$data] = true;
        !          85927:                     }
        !          85928:                     $look_for = 0;
        !          85929:                     continue 2;
        !          85930:                 case T_VARIABLE:
        !          85931:                     $look_for = 0;
        !          85932:                     continue 2;
        !          85933:                 case T_DOC_COMMENT:
        !          85934:                 case T_COMMENT:
        !          85935:                     if (preg_match('!^/\*\*\s!', $data)) {
        !          85936:                         $lastphpdoc = $data;
        !          85937:                         if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) {
        !          85938:                             $nodeps = array_merge($nodeps, $m[1]);
        !          85939:                         }
        !          85940:                     }
        !          85941:                     continue 2;
        !          85942:                 case T_DOUBLE_COLON:
        !          85943:                     if (!($tokens[$i - 1][0] == T_WHITESPACE || $tokens[$i - 1][0] == T_STRING)) {
        !          85944:                         $this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE,
        !          85945:                             array('file' => $file));
        !          85946:                         return false;
        !          85947:                     }
        !          85948:                     $class = $tokens[$i - 1][1];
        !          85949:                     if (strtolower($class) != 'parent') {
        !          85950:                         $used_classes[$class] = true;
        !          85951:                     }
        !          85952:                     continue 2;
        !          85953:             }
1.1       misho    85954:         }
1.1.1.2 ! misho    85955:         return array(
        !          85956:             "source_file" => $file,
        !          85957:             "declared_classes" => $declared_classes,
        !          85958:             "declared_interfaces" => $declared_interfaces,
        !          85959:             "declared_methods" => $declared_methods,
        !          85960:             "declared_functions" => $declared_functions,
        !          85961:             "used_classes" => array_diff(array_keys($used_classes), $nodeps),
        !          85962:             "inheritance" => $extends,
        !          85963:             "implements" => $implements,
        !          85964:             );
1.1       misho    85965:     }
                   85966: 
                   85967:     /**
1.1.1.2 ! misho    85968:      * Build a "provides" array from data returned by
        !          85969:      * analyzeSourceCode().  The format of the built array is like
        !          85970:      * this:
        !          85971:      *
        !          85972:      *  array(
        !          85973:      *    'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
        !          85974:      *    ...
        !          85975:      *  )
        !          85976:      *
        !          85977:      *
        !          85978:      * @param array $srcinfo array with information about a source file
        !          85979:      * as returned by the analyzeSourceCode() method.
        !          85980:      *
        !          85981:      * @return void
1.1       misho    85982:      *
                   85983:      * @access private
                   85984:      *
                   85985:      */
1.1.1.2 ! misho    85986:     function _buildProvidesArray($srcinfo)
1.1       misho    85987:     {
1.1.1.2 ! misho    85988:         if (!$this->_isValid) {
        !          85989:             return false;
1.1       misho    85990:         }
1.1.1.2 ! misho    85991:         $file = basename($srcinfo['source_file']);
        !          85992:         $pn = $this->getPackage();
        !          85993:         $pnl = strlen($pn);
        !          85994:         foreach ($srcinfo['declared_classes'] as $class) {
        !          85995:             $key = "class;$class";
        !          85996:             if (isset($this->_packageInfo['provides'][$key])) {
1.1       misho    85997:                 continue;
                   85998:             }
1.1.1.2 ! misho    85999:             $this->_packageInfo['provides'][$key] =
        !          86000:                 array('file'=> $file, 'type' => 'class', 'name' => $class);
        !          86001:             if (isset($srcinfo['inheritance'][$class])) {
        !          86002:                 $this->_packageInfo['provides'][$key]['extends'] =
        !          86003:                     $srcinfo['inheritance'][$class];
        !          86004:             }
1.1       misho    86005:         }
1.1.1.2 ! misho    86006:         foreach ($srcinfo['declared_methods'] as $class => $methods) {
        !          86007:             foreach ($methods as $method) {
        !          86008:                 $function = "$class::$method";
        !          86009:                 $key = "function;$function";
        !          86010:                 if ($method{0} == '_' || !strcasecmp($method, $class) ||
        !          86011:                     isset($this->_packageInfo['provides'][$key])) {
        !          86012:                     continue;
        !          86013:                 }
        !          86014:                 $this->_packageInfo['provides'][$key] =
        !          86015:                     array('file'=> $file, 'type' => 'function', 'name' => $function);
        !          86016:             }
1.1       misho    86017:         }
                   86018: 
1.1.1.2 ! misho    86019:         foreach ($srcinfo['declared_functions'] as $function) {
        !          86020:             $key = "function;$function";
        !          86021:             if ($function{0} == '_' || isset($this->_packageInfo['provides'][$key])) {
1.1       misho    86022:                 continue;
                   86023:             }
1.1.1.2 ! misho    86024:             if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
        !          86025:                 $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
        !          86026:             }
        !          86027:             $this->_packageInfo['provides'][$key] =
        !          86028:                 array('file'=> $file, 'type' => 'function', 'name' => $function);
1.1       misho    86029:         }
1.1.1.2 ! misho    86030:     }
1.1       misho    86031: 
1.1.1.2 ! misho    86032:     // }}}
        !          86033: }
        !          86034: ?>
        !          86035: <?php
        !          86036: /**
        !          86037:  * PEAR_PackageFile_v2, package.xml version 2.0
        !          86038:  *
        !          86039:  * PHP versions 4 and 5
        !          86040:  *
        !          86041:  * @category   pear
        !          86042:  * @package    PEAR
        !          86043:  * @author     Greg Beaver <cellog@php.net>
        !          86044:  * @copyright  1997-2009 The Authors
        !          86045:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          86046:  * @version    CVS: $Id: v2.php 313023 2011-07-06 19:17:11Z dufuz $
        !          86047:  * @link       http://pear.php.net/package/PEAR
        !          86048:  * @since      File available since Release 1.4.0a1
        !          86049:  */
        !          86050: /**
        !          86051:  * For error handling
        !          86052:  */
        !          86053: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ErrorStack.php';
        !          86054: /**
        !          86055:  * @category   pear
        !          86056:  * @package    PEAR
        !          86057:  * @author     Greg Beaver <cellog@php.net>
        !          86058:  * @copyright  1997-2009 The Authors
        !          86059:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          86060:  * @version    Release: 1.9.4
        !          86061:  * @link       http://pear.php.net/package/PEAR
        !          86062:  * @since      Class available since Release 1.4.0a1
        !          86063:  */
        !          86064: class PEAR_PackageFile_v2
        !          86065: {
1.1       misho    86066: 
1.1.1.2 ! misho    86067:     /**
        !          86068:      * Parsed package information
        !          86069:      * @var array
        !          86070:      * @access private
        !          86071:      */
        !          86072:     var $_packageInfo = array();
1.1       misho    86073: 
1.1.1.2 ! misho    86074:     /**
        !          86075:      * path to package .tgz or false if this is a local/extracted package.xml
        !          86076:      * @var string|false
        !          86077:      * @access private
        !          86078:      */
        !          86079:     var $_archiveFile;
1.1       misho    86080: 
1.1.1.2 ! misho    86081:     /**
        !          86082:      * path to package .xml or false if this is an abstract parsed-from-string xml
        !          86083:      * @var string|false
        !          86084:      * @access private
        !          86085:      */
        !          86086:     var $_packageFile;
1.1       misho    86087: 
1.1.1.2 ! misho    86088:     /**
        !          86089:      * This is used by file analysis routines to log progress information
        !          86090:      * @var PEAR_Common
        !          86091:      * @access protected
        !          86092:      */
        !          86093:     var $_logger;
1.1       misho    86094: 
1.1.1.2 ! misho    86095:     /**
        !          86096:      * This is set to the highest validation level that has been validated
        !          86097:      *
        !          86098:      * If the package.xml is invalid or unknown, this is set to 0.  If
        !          86099:      * normal validation has occurred, this is set to PEAR_VALIDATE_NORMAL.  If
        !          86100:      * downloading/installation validation has occurred it is set to PEAR_VALIDATE_DOWNLOADING
        !          86101:      * or INSTALLING, and so on up to PEAR_VALIDATE_PACKAGING.  This allows validation
        !          86102:      * "caching" to occur, which is particularly important for package validation, so
        !          86103:      * that PHP files are not validated twice
        !          86104:      * @var int
        !          86105:      * @access private
        !          86106:      */
        !          86107:     var $_isValid = 0;
1.1       misho    86108: 
1.1.1.2 ! misho    86109:     /**
        !          86110:      * True if the filelist has been validated
        !          86111:      * @param bool
        !          86112:      */
        !          86113:     var $_filesValid = false;
1.1       misho    86114: 
1.1.1.2 ! misho    86115:     /**
        !          86116:      * @var PEAR_Registry
        !          86117:      * @access protected
        !          86118:      */
        !          86119:     var $_registry;
1.1       misho    86120: 
1.1.1.2 ! misho    86121:     /**
        !          86122:      * @var PEAR_Config
        !          86123:      * @access protected
        !          86124:      */
        !          86125:     var $_config;
1.1       misho    86126: 
1.1.1.2 ! misho    86127:     /**
        !          86128:      * Optional Dependency group requested for installation
        !          86129:      * @var string
        !          86130:      * @access private
        !          86131:      */
        !          86132:     var $_requestedGroup = false;
1.1       misho    86133: 
1.1.1.2 ! misho    86134:     /**
        !          86135:      * @var PEAR_ErrorStack
        !          86136:      * @access protected
        !          86137:      */
        !          86138:     var $_stack;
1.1       misho    86139: 
1.1.1.2 ! misho    86140:     /**
        !          86141:      * Namespace prefix used for tasks in this package.xml - use tasks: whenever possible
        !          86142:      */
        !          86143:     var $_tasksNs;
1.1       misho    86144: 
1.1.1.2 ! misho    86145:     /**
        !          86146:      * Determines whether this packagefile was initialized only with partial package info
        !          86147:      *
        !          86148:      * If this package file was constructed via parsing REST, it will only contain
        !          86149:      *
        !          86150:      * - package name
        !          86151:      * - channel name
        !          86152:      * - dependencies
        !          86153:      * @var boolean
        !          86154:      * @access private
        !          86155:      */
        !          86156:     var $_incomplete = true;
1.1       misho    86157: 
1.1.1.2 ! misho    86158:     /**
        !          86159:      * @var PEAR_PackageFile_v2_Validator
        !          86160:      */
        !          86161:     var $_v2Validator;
1.1       misho    86162: 
                   86163:     /**
1.1.1.2 ! misho    86164:      * The constructor merely sets up the private error stack
1.1       misho    86165:      */
1.1.1.2 ! misho    86166:     function PEAR_PackageFile_v2()
1.1       misho    86167:     {
1.1.1.2 ! misho    86168:         $this->_stack = new PEAR_ErrorStack('PEAR_PackageFile_v2', false, null);
        !          86169:         $this->_isValid = false;
1.1       misho    86170:     }
                   86171: 
                   86172:     /**
1.1.1.2 ! misho    86173:      * To make unit-testing easier
        !          86174:      * @param PEAR_Frontend_*
        !          86175:      * @param array options
        !          86176:      * @param PEAR_Config
        !          86177:      * @return PEAR_Downloader
        !          86178:      * @access protected
1.1       misho    86179:      */
1.1.1.2 ! misho    86180:     function &getPEARDownloader(&$i, $o, &$c)
1.1       misho    86181:     {
1.1.1.2 ! misho    86182:         $z = &new PEAR_Downloader($i, $o, $c);
        !          86183:         return $z;
1.1       misho    86184:     }
                   86185: 
                   86186:     /**
1.1.1.2 ! misho    86187:      * To make unit-testing easier
        !          86188:      * @param PEAR_Config
        !          86189:      * @param array options
        !          86190:      * @param array package name as returned from {@link PEAR_Registry::parsePackageName()}
        !          86191:      * @param int PEAR_VALIDATE_* constant
        !          86192:      * @return PEAR_Dependency2
        !          86193:      * @access protected
1.1       misho    86194:      */
1.1.1.2 ! misho    86195:     function &getPEARDependency2(&$c, $o, $p, $s = PEAR_VALIDATE_INSTALLING)
1.1       misho    86196:     {
1.1.1.2 ! misho    86197:         if (!class_exists('PEAR_Dependency2')) {
        !          86198:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Dependency2.php';
        !          86199:         }
        !          86200:         $z = &new PEAR_Dependency2($c, $o, $p, $s);
        !          86201:         return $z;
        !          86202:     }
        !          86203: 
        !          86204:     function getInstalledBinary()
        !          86205:     {
        !          86206:         return isset($this->_packageInfo['#binarypackage']) ? $this->_packageInfo['#binarypackage'] :
        !          86207:             false;
        !          86208:     }
        !          86209: 
        !          86210:     /**
        !          86211:      * Installation of source package has failed, attempt to download and install the
        !          86212:      * binary version of this package.
        !          86213:      * @param PEAR_Installer
        !          86214:      * @return array|false
        !          86215:      */
        !          86216:     function installBinary(&$installer)
        !          86217:     {
        !          86218:         if (!OS_WINDOWS) {
        !          86219:             $a = false;
        !          86220:             return $a;
        !          86221:         }
        !          86222:         if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
        !          86223:             $releasetype = $this->getPackageType() . 'release';
        !          86224:             if (!is_array($installer->getInstallPackages())) {
        !          86225:                 $a = false;
        !          86226:                 return $a;
1.1       misho    86227:             }
1.1.1.2 ! misho    86228:             foreach ($installer->getInstallPackages() as $p) {
        !          86229:                 if ($p->isExtension($this->_packageInfo['providesextension'])) {
        !          86230:                     if ($p->getPackageType() != 'extsrc' && $p->getPackageType() != 'zendextsrc') {
        !          86231:                         $a = false;
        !          86232:                         return $a; // the user probably downloaded it separately
        !          86233:                     }
1.1       misho    86234:                 }
                   86235:             }
1.1.1.2 ! misho    86236:             if (isset($this->_packageInfo[$releasetype]['binarypackage'])) {
        !          86237:                 $installer->log(0, 'Attempting to download binary version of extension "' .
        !          86238:                     $this->_packageInfo['providesextension'] . '"');
        !          86239:                 $params = $this->_packageInfo[$releasetype]['binarypackage'];
        !          86240:                 if (!is_array($params) || !isset($params[0])) {
        !          86241:                     $params = array($params);
1.1       misho    86242:                 }
1.1.1.2 ! misho    86243:                 if (isset($this->_packageInfo['channel'])) {
        !          86244:                     foreach ($params as $i => $param) {
        !          86245:                         $params[$i] = array('channel' => $this->_packageInfo['channel'],
        !          86246:                             'package' => $param, 'version' => $this->getVersion());
1.1       misho    86247:                     }
                   86248:                 }
1.1.1.2 ! misho    86249:                 $dl = &$this->getPEARDownloader($installer->ui, $installer->getOptions(),
        !          86250:                     $installer->config);
        !          86251:                 $verbose = $dl->config->get('verbose');
        !          86252:                 $dl->config->set('verbose', -1);
        !          86253:                 foreach ($params as $param) {
        !          86254:                     PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          86255:                     $ret = $dl->download(array($param));
        !          86256:                     PEAR::popErrorHandling();
        !          86257:                     if (is_array($ret) && count($ret)) {
        !          86258:                         break;
1.1       misho    86259:                     }
                   86260:                 }
1.1.1.2 ! misho    86261:                 $dl->config->set('verbose', $verbose);
        !          86262:                 if (is_array($ret)) {
        !          86263:                     if (count($ret) == 1) {
        !          86264:                         $pf = $ret[0]->getPackageFile();
        !          86265:                         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          86266:                         $err = $installer->install($ret[0]);
        !          86267:                         PEAR::popErrorHandling();
        !          86268:                         if (is_array($err)) {
        !          86269:                             $this->_packageInfo['#binarypackage'] = $ret[0]->getPackage();
        !          86270:                             // "install" self, so all dependencies will work transparently
        !          86271:                             $this->_registry->addPackage2($this);
        !          86272:                             $installer->log(0, 'Download and install of binary extension "' .
        !          86273:                                 $this->_registry->parsedPackageNameToString(
        !          86274:                                     array('channel' => $pf->getChannel(),
        !          86275:                                           'package' => $pf->getPackage()), true) . '" successful');
        !          86276:                             $a = array($ret[0], $err);
        !          86277:                             return $a;
        !          86278:                         }
        !          86279:                         $installer->log(0, 'Download and install of binary extension "' .
        !          86280:                             $this->_registry->parsedPackageNameToString(
        !          86281:                                     array('channel' => $pf->getChannel(),
        !          86282:                                           'package' => $pf->getPackage()), true) . '" failed');
1.1       misho    86283:                     }
                   86284:                 }
                   86285:             }
                   86286:         }
1.1.1.2 ! misho    86287:         $a = false;
        !          86288:         return $a;
1.1       misho    86289:     }
                   86290: 
                   86291:     /**
1.1.1.2 ! misho    86292:      * @return string|false Extension name
1.1       misho    86293:      */
1.1.1.2 ! misho    86294:     function getProvidesExtension()
1.1       misho    86295:     {
1.1.1.2 ! misho    86296:         if (in_array($this->getPackageType(),
        !          86297:               array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
        !          86298:             if (isset($this->_packageInfo['providesextension'])) {
        !          86299:                 return $this->_packageInfo['providesextension'];
1.1       misho    86300:             }
                   86301:         }
1.1.1.2 ! misho    86302:         return false;
        !          86303:     }
        !          86304: 
        !          86305:     /**
        !          86306:      * @param string Extension name
        !          86307:      * @return bool
        !          86308:      */
        !          86309:     function isExtension($extension)
        !          86310:     {
        !          86311:         if (in_array($this->getPackageType(),
        !          86312:               array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
        !          86313:             return $this->_packageInfo['providesextension'] == $extension;
1.1       misho    86314:         }
1.1.1.2 ! misho    86315:         return false;
        !          86316:     }
        !          86317: 
        !          86318:     /**
        !          86319:      * Tests whether every part of the package.xml 1.0 is represented in
        !          86320:      * this package.xml 2.0
        !          86321:      * @param PEAR_PackageFile_v1
        !          86322:      * @return bool
        !          86323:      */
        !          86324:     function isEquivalent($pf1)
        !          86325:     {
        !          86326:         if (!$pf1) {
        !          86327:             return true;
        !          86328:         }
        !          86329:         if ($this->getPackageType() == 'bundle') {
        !          86330:             return false;
        !          86331:         }
        !          86332:         $this->_stack->getErrors(true);
        !          86333:         if (!$pf1->validate(PEAR_VALIDATE_NORMAL)) {
        !          86334:             return false;
        !          86335:         }
        !          86336:         $pass = true;
        !          86337:         if ($pf1->getPackage() != $this->getPackage()) {
        !          86338:             $this->_differentPackage($pf1->getPackage());
        !          86339:             $pass = false;
        !          86340:         }
        !          86341:         if ($pf1->getVersion() != $this->getVersion()) {
        !          86342:             $this->_differentVersion($pf1->getVersion());
        !          86343:             $pass = false;
        !          86344:         }
        !          86345:         if (trim($pf1->getSummary()) != $this->getSummary()) {
        !          86346:             $this->_differentSummary($pf1->getSummary());
        !          86347:             $pass = false;
        !          86348:         }
        !          86349:         if (preg_replace('/\s+/', '', $pf1->getDescription()) !=
        !          86350:               preg_replace('/\s+/', '', $this->getDescription())) {
        !          86351:             $this->_differentDescription($pf1->getDescription());
        !          86352:             $pass = false;
        !          86353:         }
        !          86354:         if ($pf1->getState() != $this->getState()) {
        !          86355:             $this->_differentState($pf1->getState());
        !          86356:             $pass = false;
        !          86357:         }
        !          86358:         if (!strstr(preg_replace('/\s+/', '', $this->getNotes()),
        !          86359:               preg_replace('/\s+/', '', $pf1->getNotes()))) {
        !          86360:             $this->_differentNotes($pf1->getNotes());
        !          86361:             $pass = false;
        !          86362:         }
        !          86363:         $mymaintainers = $this->getMaintainers();
        !          86364:         $yourmaintainers = $pf1->getMaintainers();
        !          86365:         for ($i1 = 0; $i1 < count($yourmaintainers); $i1++) {
        !          86366:             $reset = false;
        !          86367:             for ($i2 = 0; $i2 < count($mymaintainers); $i2++) {
        !          86368:                 if ($mymaintainers[$i2]['handle'] == $yourmaintainers[$i1]['handle']) {
        !          86369:                     if ($mymaintainers[$i2]['role'] != $yourmaintainers[$i1]['role']) {
        !          86370:                         $this->_differentRole($mymaintainers[$i2]['handle'],
        !          86371:                             $yourmaintainers[$i1]['role'], $mymaintainers[$i2]['role']);
        !          86372:                         $pass = false;
        !          86373:                     }
        !          86374:                     if ($mymaintainers[$i2]['email'] != $yourmaintainers[$i1]['email']) {
        !          86375:                         $this->_differentEmail($mymaintainers[$i2]['handle'],
        !          86376:                             $yourmaintainers[$i1]['email'], $mymaintainers[$i2]['email']);
        !          86377:                         $pass = false;
        !          86378:                     }
        !          86379:                     if ($mymaintainers[$i2]['name'] != $yourmaintainers[$i1]['name']) {
        !          86380:                         $this->_differentName($mymaintainers[$i2]['handle'],
        !          86381:                             $yourmaintainers[$i1]['name'], $mymaintainers[$i2]['name']);
        !          86382:                         $pass = false;
1.1       misho    86383:                     }
1.1.1.2 ! misho    86384:                     unset($mymaintainers[$i2]);
        !          86385:                     $mymaintainers = array_values($mymaintainers);
        !          86386:                     unset($yourmaintainers[$i1]);
        !          86387:                     $yourmaintainers = array_values($yourmaintainers);
        !          86388:                     $reset = true;
        !          86389:                     break;
1.1       misho    86390:                 }
1.1.1.2 ! misho    86391:             }
        !          86392:             if ($reset) {
        !          86393:                 $i1 = -1;
        !          86394:             }
1.1       misho    86395:         }
1.1.1.2 ! misho    86396:         $this->_unmatchedMaintainers($mymaintainers, $yourmaintainers);
        !          86397:         $filelist = $this->getFilelist();
        !          86398:         foreach ($pf1->getFilelist() as $file => $atts) {
        !          86399:             if (!isset($filelist[$file])) {
        !          86400:                 $this->_missingFile($file);
        !          86401:                 $pass = false;
        !          86402:             }
        !          86403:         }
        !          86404:         return $pass;
        !          86405:     }
        !          86406: 
        !          86407:     function _differentPackage($package)
        !          86408:     {
        !          86409:         $this->_stack->push(__FUNCTION__, 'error', array('package' => $package,
        !          86410:             'self' => $this->getPackage()),
        !          86411:             'package.xml 1.0 package "%package%" does not match "%self%"');
        !          86412:     }
        !          86413: 
        !          86414:     function _differentVersion($version)
        !          86415:     {
        !          86416:         $this->_stack->push(__FUNCTION__, 'error', array('version' => $version,
        !          86417:             'self' => $this->getVersion()),
        !          86418:             'package.xml 1.0 version "%version%" does not match "%self%"');
        !          86419:     }
        !          86420: 
        !          86421:     function _differentState($state)
        !          86422:     {
        !          86423:         $this->_stack->push(__FUNCTION__, 'error', array('state' => $state,
        !          86424:             'self' => $this->getState()),
        !          86425:             'package.xml 1.0 state "%state%" does not match "%self%"');
        !          86426:     }
        !          86427: 
        !          86428:     function _differentRole($handle, $role, $selfrole)
        !          86429:     {
        !          86430:         $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
        !          86431:             'role' => $role, 'self' => $selfrole),
        !          86432:             'package.xml 1.0 maintainer "%handle%" role "%role%" does not match "%self%"');
        !          86433:     }
        !          86434: 
        !          86435:     function _differentEmail($handle, $email, $selfemail)
        !          86436:     {
        !          86437:         $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
        !          86438:             'email' => $email, 'self' => $selfemail),
        !          86439:             'package.xml 1.0 maintainer "%handle%" email "%email%" does not match "%self%"');
        !          86440:     }
        !          86441: 
        !          86442:     function _differentName($handle, $name, $selfname)
        !          86443:     {
        !          86444:         $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
        !          86445:             'name' => $name, 'self' => $selfname),
        !          86446:             'package.xml 1.0 maintainer "%handle%" name "%name%" does not match "%self%"');
        !          86447:     }
        !          86448: 
        !          86449:     function _unmatchedMaintainers($my, $yours)
        !          86450:     {
        !          86451:         if ($my) {
        !          86452:             array_walk($my, create_function('&$i, $k', '$i = $i["handle"];'));
        !          86453:             $this->_stack->push(__FUNCTION__, 'error', array('handles' => $my),
        !          86454:                 'package.xml 2.0 has unmatched extra maintainers "%handles%"');
        !          86455:         }
        !          86456:         if ($yours) {
        !          86457:             array_walk($yours, create_function('&$i, $k', '$i = $i["handle"];'));
        !          86458:             $this->_stack->push(__FUNCTION__, 'error', array('handles' => $yours),
        !          86459:                 'package.xml 1.0 has unmatched extra maintainers "%handles%"');
        !          86460:         }
        !          86461:     }
        !          86462: 
        !          86463:     function _differentNotes($notes)
        !          86464:     {
        !          86465:         $truncnotes = strlen($notes) < 25 ? $notes : substr($notes, 0, 24) . '...';
        !          86466:         $truncmynotes = strlen($this->getNotes()) < 25 ? $this->getNotes() :
        !          86467:             substr($this->getNotes(), 0, 24) . '...';
        !          86468:         $this->_stack->push(__FUNCTION__, 'error', array('notes' => $truncnotes,
        !          86469:             'self' => $truncmynotes),
        !          86470:             'package.xml 1.0 release notes "%notes%" do not match "%self%"');
        !          86471:     }
        !          86472: 
        !          86473:     function _differentSummary($summary)
        !          86474:     {
        !          86475:         $truncsummary = strlen($summary) < 25 ? $summary : substr($summary, 0, 24) . '...';
        !          86476:         $truncmysummary = strlen($this->getsummary()) < 25 ? $this->getSummary() :
        !          86477:             substr($this->getsummary(), 0, 24) . '...';
        !          86478:         $this->_stack->push(__FUNCTION__, 'error', array('summary' => $truncsummary,
        !          86479:             'self' => $truncmysummary),
        !          86480:             'package.xml 1.0 summary "%summary%" does not match "%self%"');
        !          86481:     }
        !          86482: 
        !          86483:     function _differentDescription($description)
        !          86484:     {
        !          86485:         $truncdescription = trim(strlen($description) < 25 ? $description : substr($description, 0, 24) . '...');
        !          86486:         $truncmydescription = trim(strlen($this->getDescription()) < 25 ? $this->getDescription() :
        !          86487:             substr($this->getdescription(), 0, 24) . '...');
        !          86488:         $this->_stack->push(__FUNCTION__, 'error', array('description' => $truncdescription,
        !          86489:             'self' => $truncmydescription),
        !          86490:             'package.xml 1.0 description "%description%" does not match "%self%"');
        !          86491:     }
        !          86492: 
        !          86493:     function _missingFile($file)
        !          86494:     {
        !          86495:         $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
        !          86496:             'package.xml 1.0 file "%file%" is not present in <contents>');
1.1       misho    86497:     }
                   86498: 
                   86499:     /**
1.1.1.2 ! misho    86500:      * WARNING - do not use this function unless you know what you're doing
1.1       misho    86501:      */
1.1.1.2 ! misho    86502:     function setRawState($state)
1.1       misho    86503:     {
1.1.1.2 ! misho    86504:         if (!isset($this->_packageInfo['stability'])) {
        !          86505:             $this->_packageInfo['stability'] = array();
1.1       misho    86506:         }
1.1.1.2 ! misho    86507:         $this->_packageInfo['stability']['release'] = $state;
1.1       misho    86508:     }
                   86509: 
                   86510:     /**
1.1.1.2 ! misho    86511:      * WARNING - do not use this function unless you know what you're doing
1.1       misho    86512:      */
1.1.1.2 ! misho    86513:     function setRawCompatible($compatible)
1.1       misho    86514:     {
1.1.1.2 ! misho    86515:         $this->_packageInfo['compatible'] = $compatible;
1.1       misho    86516:     }
                   86517: 
                   86518:     /**
1.1.1.2 ! misho    86519:      * WARNING - do not use this function unless you know what you're doing
1.1       misho    86520:      */
1.1.1.2 ! misho    86521:     function setRawPackage($package)
        !          86522:     {
        !          86523:         $this->_packageInfo['name'] = $package;
        !          86524:     }
        !          86525: 
1.1       misho    86526:     /**
1.1.1.2 ! misho    86527:      * WARNING - do not use this function unless you know what you're doing
1.1       misho    86528:      */
1.1.1.2 ! misho    86529:     function setRawChannel($channel)
1.1       misho    86530:     {
1.1.1.2 ! misho    86531:         $this->_packageInfo['channel'] = $channel;
        !          86532:     }
        !          86533: 
        !          86534:     function setRequestedGroup($group)
        !          86535:     {
        !          86536:         $this->_requestedGroup = $group;
        !          86537:     }
        !          86538: 
        !          86539:     function getRequestedGroup()
        !          86540:     {
        !          86541:         if (isset($this->_requestedGroup)) {
        !          86542:             return $this->_requestedGroup;
1.1       misho    86543:         }
1.1.1.2 ! misho    86544:         return false;
1.1       misho    86545:     }
                   86546: 
                   86547:     /**
1.1.1.2 ! misho    86548:      * For saving in the registry.
        !          86549:      *
        !          86550:      * Set the last version that was installed
        !          86551:      * @param string
1.1       misho    86552:      */
1.1.1.2 ! misho    86553:     function setLastInstalledVersion($version)
1.1       misho    86554:     {
1.1.1.2 ! misho    86555:         $this->_packageInfo['_lastversion'] = $version;
1.1       misho    86556:     }
                   86557: 
                   86558:     /**
1.1.1.2 ! misho    86559:      * @return string|false
1.1       misho    86560:      */
1.1.1.2 ! misho    86561:     function getLastInstalledVersion()
1.1       misho    86562:     {
1.1.1.2 ! misho    86563:         if (isset($this->_packageInfo['_lastversion'])) {
        !          86564:             return $this->_packageInfo['_lastversion'];
        !          86565:         }
        !          86566:         return false;
1.1       misho    86567:     }
                   86568: 
                   86569:     /**
1.1.1.2 ! misho    86570:      * Determines whether this package.xml has post-install scripts or not
        !          86571:      * @return array|false
1.1       misho    86572:      */
1.1.1.2 ! misho    86573:     function listPostinstallScripts()
1.1       misho    86574:     {
1.1.1.2 ! misho    86575:         $filelist = $this->getFilelist();
        !          86576:         $contents = $this->getContents();
        !          86577:         $contents = $contents['dir']['file'];
        !          86578:         if (!is_array($contents) || !isset($contents[0])) {
        !          86579:             $contents = array($contents);
1.1       misho    86580:         }
1.1.1.2 ! misho    86581:         $taskfiles = array();
        !          86582:         foreach ($contents as $file) {
        !          86583:             $atts = $file['attribs'];
        !          86584:             unset($file['attribs']);
        !          86585:             if (count($file)) {
        !          86586:                 $taskfiles[$atts['name']] = $file;
1.1       misho    86587:             }
                   86588:         }
1.1.1.2 ! misho    86589:         $common = new PEAR_Common;
        !          86590:         $common->debug = $this->_config->get('verbose');
        !          86591:         $this->_scripts = array();
        !          86592:         $ret = array();
        !          86593:         foreach ($taskfiles as $name => $tasks) {
        !          86594:             if (!isset($filelist[$name])) {
        !          86595:                 // ignored files will not be in the filelist
        !          86596:                 continue;
        !          86597:             }
        !          86598:             $atts = $filelist[$name];
        !          86599:             foreach ($tasks as $tag => $raw) {
        !          86600:                 $task = $this->getTask($tag);
        !          86601:                 $task = &new $task($this->_config, $common, PEAR_TASK_INSTALL);
        !          86602:                 if ($task->isScript()) {
        !          86603:                     $ret[] = $filelist[$name]['installed_as'];
        !          86604:                 }
        !          86605:             }
1.1       misho    86606:         }
1.1.1.2 ! misho    86607:         if (count($ret)) {
        !          86608:             return $ret;
1.1       misho    86609:         }
1.1.1.2 ! misho    86610:         return false;
        !          86611:     }
1.1       misho    86612: 
1.1.1.2 ! misho    86613:     /**
        !          86614:      * Initialize post-install scripts for running
        !          86615:      *
        !          86616:      * This method can be used to detect post-install scripts, as the return value
        !          86617:      * indicates whether any exist
        !          86618:      * @return bool
        !          86619:      */
        !          86620:     function initPostinstallScripts()
        !          86621:     {
        !          86622:         $filelist = $this->getFilelist();
        !          86623:         $contents = $this->getContents();
        !          86624:         $contents = $contents['dir']['file'];
        !          86625:         if (!is_array($contents) || !isset($contents[0])) {
        !          86626:             $contents = array($contents);
1.1       misho    86627:         }
1.1.1.2 ! misho    86628:         $taskfiles = array();
        !          86629:         foreach ($contents as $file) {
        !          86630:             $atts = $file['attribs'];
        !          86631:             unset($file['attribs']);
        !          86632:             if (count($file)) {
        !          86633:                 $taskfiles[$atts['name']] = $file;
        !          86634:             }
1.1       misho    86635:         }
1.1.1.2 ! misho    86636:         $common = new PEAR_Common;
        !          86637:         $common->debug = $this->_config->get('verbose');
        !          86638:         $this->_scripts = array();
        !          86639:         foreach ($taskfiles as $name => $tasks) {
        !          86640:             if (!isset($filelist[$name])) {
        !          86641:                 // file was not installed due to installconditions
        !          86642:                 continue;
1.1       misho    86643:             }
1.1.1.2 ! misho    86644:             $atts = $filelist[$name];
        !          86645:             foreach ($tasks as $tag => $raw) {
        !          86646:                 $taskname = $this->getTask($tag);
        !          86647:                 $task = &new $taskname($this->_config, $common, PEAR_TASK_INSTALL);
        !          86648:                 if (!$task->isScript()) {
        !          86649:                     continue; // scripts are only handled after installation
1.1       misho    86650:                 }
1.1.1.2 ! misho    86651:                 $lastversion = isset($this->_packageInfo['_lastversion']) ?
        !          86652:                     $this->_packageInfo['_lastversion'] : null;
        !          86653:                 $task->init($raw, $atts, $lastversion);
        !          86654:                 $res = $task->startSession($this, $atts['installed_as']);
        !          86655:                 if (!$res) {
        !          86656:                     continue; // skip this file
        !          86657:                 }
        !          86658:                 if (PEAR::isError($res)) {
        !          86659:                     return $res;
        !          86660:                 }
        !          86661:                 $assign = &$task;
        !          86662:                 $this->_scripts[] = &$assign;
1.1       misho    86663:             }
1.1.1.2 ! misho    86664:         }
        !          86665:         if (count($this->_scripts)) {
        !          86666:             return true;
        !          86667:         }
        !          86668:         return false;
        !          86669:     }
1.1       misho    86670: 
1.1.1.2 ! misho    86671:     function runPostinstallScripts()
        !          86672:     {
        !          86673:         if ($this->initPostinstallScripts()) {
        !          86674:             $ui = &PEAR_Frontend::singleton();
        !          86675:             if ($ui) {
        !          86676:                 $ui->runPostinstallScripts($this->_scripts, $this);
        !          86677:             }
        !          86678:         }
        !          86679:     }
1.1       misho    86680: 
                   86681: 
1.1.1.2 ! misho    86682:     /**
        !          86683:      * Convert a recursive set of <dir> and <file> tags into a single <dir> tag with
        !          86684:      * <file> tags.
        !          86685:      */
        !          86686:     function flattenFilelist()
        !          86687:     {
        !          86688:         if (isset($this->_packageInfo['bundle'])) {
        !          86689:             return;
        !          86690:         }
        !          86691:         $filelist = array();
        !          86692:         if (isset($this->_packageInfo['contents']['dir']['dir'])) {
        !          86693:             $this->_getFlattenedFilelist($filelist, $this->_packageInfo['contents']['dir']);
        !          86694:             if (!isset($filelist[1])) {
        !          86695:                 $filelist = $filelist[0];
        !          86696:             }
        !          86697:             $this->_packageInfo['contents']['dir']['file'] = $filelist;
        !          86698:             unset($this->_packageInfo['contents']['dir']['dir']);
        !          86699:         } else {
        !          86700:             // else already flattened but check for baseinstalldir propagation
        !          86701:             if (isset($this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'])) {
        !          86702:                 if (isset($this->_packageInfo['contents']['dir']['file'][0])) {
        !          86703:                     foreach ($this->_packageInfo['contents']['dir']['file'] as $i => $file) {
        !          86704:                         if (isset($file['attribs']['baseinstalldir'])) {
        !          86705:                             continue;
1.1       misho    86706:                         }
1.1.1.2 ! misho    86707:                         $this->_packageInfo['contents']['dir']['file'][$i]['attribs']['baseinstalldir']
        !          86708:                             = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'];
        !          86709:                     }
        !          86710:                 } else {
        !          86711:                     if (!isset($this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir'])) {
        !          86712:                        $this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir']
        !          86713:                             = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'];
1.1       misho    86714:                     }
                   86715:                 }
                   86716:             }
                   86717:         }
1.1.1.2 ! misho    86718:     }
1.1       misho    86719: 
1.1.1.2 ! misho    86720:     /**
        !          86721:      * @param array the final flattened file list
        !          86722:      * @param array the current directory being processed
        !          86723:      * @param string|false any recursively inherited baeinstalldir attribute
        !          86724:      * @param string private recursion variable
        !          86725:      * @return array
        !          86726:      * @access protected
        !          86727:      */
        !          86728:     function _getFlattenedFilelist(&$files, $dir, $baseinstall = false, $path = '')
        !          86729:     {
        !          86730:         if (isset($dir['attribs']) && isset($dir['attribs']['baseinstalldir'])) {
        !          86731:             $baseinstall = $dir['attribs']['baseinstalldir'];
        !          86732:         }
        !          86733:         if (isset($dir['dir'])) {
        !          86734:             if (!isset($dir['dir'][0])) {
        !          86735:                 $dir['dir'] = array($dir['dir']);
1.1       misho    86736:             }
1.1.1.2 ! misho    86737:             foreach ($dir['dir'] as $subdir) {
        !          86738:                 if (!isset($subdir['attribs']) || !isset($subdir['attribs']['name'])) {
        !          86739:                     $name = '*unknown*';
        !          86740:                 } else {
        !          86741:                     $name = $subdir['attribs']['name'];
        !          86742:                 }
        !          86743:                 $newpath = empty($path) ? $name :
        !          86744:                     $path . '/' . $name;
        !          86745:                 $this->_getFlattenedFilelist($files, $subdir,
        !          86746:                     $baseinstall, $newpath);
1.1       misho    86747:             }
1.1.1.2 ! misho    86748:         }
        !          86749:         if (isset($dir['file'])) {
        !          86750:             if (!isset($dir['file'][0])) {
        !          86751:                 $dir['file'] = array($dir['file']);
        !          86752:             }
        !          86753:             foreach ($dir['file'] as $file) {
        !          86754:                 $attrs = $file['attribs'];
        !          86755:                 $name = $attrs['name'];
        !          86756:                 if ($baseinstall && !isset($attrs['baseinstalldir'])) {
        !          86757:                     $attrs['baseinstalldir'] = $baseinstall;
1.1       misho    86758:                 }
1.1.1.2 ! misho    86759:                 $attrs['name'] = empty($path) ? $name : $path . '/' . $name;
        !          86760:                 $attrs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
        !          86761:                     $attrs['name']);
        !          86762:                 $file['attribs'] = $attrs;
        !          86763:                 $files[] = $file;
1.1       misho    86764:             }
                   86765:         }
                   86766:     }
                   86767: 
1.1.1.2 ! misho    86768:     function setConfig(&$config)
1.1       misho    86769:     {
1.1.1.2 ! misho    86770:         $this->_config = &$config;
        !          86771:         $this->_registry = &$config->getRegistry();
        !          86772:     }
1.1       misho    86773: 
1.1.1.2 ! misho    86774:     function setLogger(&$logger)
        !          86775:     {
        !          86776:         if (!is_object($logger) || !method_exists($logger, 'log')) {
        !          86777:             return PEAR::raiseError('Logger must be compatible with PEAR_Common::log');
1.1       misho    86778:         }
1.1.1.2 ! misho    86779:         $this->_logger = &$logger;
1.1       misho    86780:     }
                   86781: 
1.1.1.2 ! misho    86782:     /**
        !          86783:      * WARNING - do not use this function directly unless you know what you're doing
        !          86784:      */
        !          86785:     function setDeps($deps)
1.1       misho    86786:     {
1.1.1.2 ! misho    86787:         $this->_packageInfo['dependencies'] = $deps;
1.1       misho    86788:     }
                   86789: 
                   86790:     /**
1.1.1.2 ! misho    86791:      * WARNING - do not use this function directly unless you know what you're doing
1.1       misho    86792:      */
1.1.1.2 ! misho    86793:     function setCompatible($compat)
1.1       misho    86794:     {
1.1.1.2 ! misho    86795:         $this->_packageInfo['compatible'] = $compat;
        !          86796:     }
1.1       misho    86797: 
1.1.1.2 ! misho    86798:     function setPackagefile($file, $archive = false)
        !          86799:     {
        !          86800:         $this->_packageFile = $file;
        !          86801:         $this->_archiveFile = $archive ? $archive : $file;
        !          86802:     }
1.1       misho    86803: 
1.1.1.2 ! misho    86804:     /**
        !          86805:      * Wrapper to {@link PEAR_ErrorStack::getErrors()}
        !          86806:      * @param boolean determines whether to purge the error stack after retrieving
        !          86807:      * @return array
        !          86808:      */
        !          86809:     function getValidationWarnings($purge = true)
        !          86810:     {
        !          86811:         return $this->_stack->getErrors($purge);
        !          86812:     }
1.1       misho    86813: 
1.1.1.2 ! misho    86814:     function getPackageFile()
        !          86815:     {
        !          86816:         return $this->_packageFile;
        !          86817:     }
1.1       misho    86818: 
1.1.1.2 ! misho    86819:     function getArchiveFile()
        !          86820:     {
        !          86821:         return $this->_archiveFile;
        !          86822:     }
1.1       misho    86823: 
                   86824: 
1.1.1.2 ! misho    86825:     /**
        !          86826:      * Directly set the array that defines this packagefile
        !          86827:      *
        !          86828:      * WARNING: no validation.  This should only be performed by internal methods
        !          86829:      * inside PEAR or by inputting an array saved from an existing PEAR_PackageFile_v2
        !          86830:      * @param array
        !          86831:      */
        !          86832:     function fromArray($pinfo)
        !          86833:     {
        !          86834:         unset($pinfo['old']);
        !          86835:         unset($pinfo['xsdversion']);
        !          86836:         // If the changelog isn't an array then it was passed in as an empty tag
        !          86837:         if (isset($pinfo['changelog']) && !is_array($pinfo['changelog'])) {
        !          86838:           unset($pinfo['changelog']);
1.1       misho    86839:         }
1.1.1.2 ! misho    86840:         $this->_incomplete = false;
        !          86841:         $this->_packageInfo = $pinfo;
        !          86842:     }
1.1       misho    86843: 
1.1.1.2 ! misho    86844:     function isIncomplete()
        !          86845:     {
        !          86846:         return $this->_incomplete;
        !          86847:     }
1.1       misho    86848: 
1.1.1.2 ! misho    86849:     /**
        !          86850:      * @return array
        !          86851:      */
        !          86852:     function toArray($forreg = false)
        !          86853:     {
        !          86854:         if (!$this->validate(PEAR_VALIDATE_NORMAL)) {
        !          86855:             return false;
1.1       misho    86856:         }
1.1.1.2 ! misho    86857:         return $this->getArray($forreg);
1.1       misho    86858:     }
                   86859: 
1.1.1.2 ! misho    86860:     function getArray($forReg = false)
1.1       misho    86861:     {
1.1.1.2 ! misho    86862:         if ($forReg) {
        !          86863:             $arr = $this->_packageInfo;
        !          86864:             $arr['old'] = array();
        !          86865:             $arr['old']['version'] = $this->getVersion();
        !          86866:             $arr['old']['release_date'] = $this->getDate();
        !          86867:             $arr['old']['release_state'] = $this->getState();
        !          86868:             $arr['old']['release_license'] = $this->getLicense();
        !          86869:             $arr['old']['release_notes'] = $this->getNotes();
        !          86870:             $arr['old']['release_deps'] = $this->getDeps();
        !          86871:             $arr['old']['maintainers'] = $this->getMaintainers();
        !          86872:             $arr['xsdversion'] = '2.0';
        !          86873:             return $arr;
1.1       misho    86874:         } else {
1.1.1.2 ! misho    86875:             $info = $this->_packageInfo;
        !          86876:             unset($info['dirtree']);
        !          86877:             if (isset($info['_lastversion'])) {
        !          86878:                 unset($info['_lastversion']);
        !          86879:             }
        !          86880:             if (isset($info['#binarypackage'])) {
        !          86881:                 unset($info['#binarypackage']);
1.1       misho    86882:             }
1.1.1.2 ! misho    86883:             return $info;
1.1       misho    86884:         }
                   86885:     }
                   86886: 
1.1.1.2 ! misho    86887:     function packageInfo($field)
1.1       misho    86888:     {
1.1.1.2 ! misho    86889:         $arr = $this->getArray(true);
        !          86890:         if ($field == 'state') {
        !          86891:             return $arr['stability']['release'];
1.1       misho    86892:         }
1.1.1.2 ! misho    86893:         if ($field == 'api-version') {
        !          86894:             return $arr['version']['api'];
1.1       misho    86895:         }
1.1.1.2 ! misho    86896:         if ($field == 'api-state') {
        !          86897:             return $arr['stability']['api'];
1.1       misho    86898:         }
1.1.1.2 ! misho    86899:         if (isset($arr['old'][$field])) {
        !          86900:             if (!is_string($arr['old'][$field])) {
        !          86901:                 return null;
        !          86902:             }
        !          86903:             return $arr['old'][$field];
1.1       misho    86904:         }
1.1.1.2 ! misho    86905:         if (isset($arr[$field])) {
        !          86906:             if (!is_string($arr[$field])) {
        !          86907:                 return null;
1.1       misho    86908:             }
1.1.1.2 ! misho    86909:             return $arr[$field];
1.1       misho    86910:         }
1.1.1.2 ! misho    86911:         return null;
1.1       misho    86912:     }
                   86913: 
1.1.1.2 ! misho    86914:     function getName()
1.1       misho    86915:     {
1.1.1.2 ! misho    86916:         return $this->getPackage();
1.1       misho    86917:     }
                   86918: 
1.1.1.2 ! misho    86919:     function getPackage()
1.1       misho    86920:     {
1.1.1.2 ! misho    86921:         if (isset($this->_packageInfo['name'])) {
        !          86922:             return $this->_packageInfo['name'];
        !          86923:         }
        !          86924:         return false;
1.1       misho    86925:     }
                   86926: 
1.1.1.2 ! misho    86927:     function getChannel()
1.1       misho    86928:     {
1.1.1.2 ! misho    86929:         if (isset($this->_packageInfo['uri'])) {
        !          86930:             return '__uri';
        !          86931:         }
        !          86932:         if (isset($this->_packageInfo['channel'])) {
        !          86933:             return strtolower($this->_packageInfo['channel']);
        !          86934:         }
        !          86935:         return false;
1.1       misho    86936:     }
                   86937: 
1.1.1.2 ! misho    86938:     function getUri()
1.1       misho    86939:     {
1.1.1.2 ! misho    86940:         if (isset($this->_packageInfo['uri'])) {
        !          86941:             return $this->_packageInfo['uri'];
        !          86942:         }
        !          86943:         return false;
1.1       misho    86944:     }
                   86945: 
1.1.1.2 ! misho    86946:     function getExtends()
1.1       misho    86947:     {
1.1.1.2 ! misho    86948:         if (isset($this->_packageInfo['extends'])) {
        !          86949:             return $this->_packageInfo['extends'];
1.1       misho    86950:         }
1.1.1.2 ! misho    86951:         return false;
        !          86952:     }
1.1       misho    86953: 
1.1.1.2 ! misho    86954:     function getSummary()
        !          86955:     {
        !          86956:         if (isset($this->_packageInfo['summary'])) {
        !          86957:             return $this->_packageInfo['summary'];
1.1       misho    86958:         }
1.1.1.2 ! misho    86959:         return false;
        !          86960:     }
1.1       misho    86961: 
1.1.1.2 ! misho    86962:     function getDescription()
        !          86963:     {
        !          86964:         if (isset($this->_packageInfo['description'])) {
        !          86965:             return $this->_packageInfo['description'];
1.1       misho    86966:         }
1.1.1.2 ! misho    86967:         return false;
        !          86968:     }
1.1       misho    86969: 
1.1.1.2 ! misho    86970:     function getMaintainers($raw = false)
        !          86971:     {
        !          86972:         if (!isset($this->_packageInfo['lead'])) {
        !          86973:             return false;
        !          86974:         }
        !          86975:         if ($raw) {
        !          86976:             $ret = array('lead' => $this->_packageInfo['lead']);
        !          86977:             (isset($this->_packageInfo['developer'])) ?
        !          86978:                 $ret['developer'] = $this->_packageInfo['developer'] :null;
        !          86979:             (isset($this->_packageInfo['contributor'])) ?
        !          86980:                 $ret['contributor'] = $this->_packageInfo['contributor'] :null;
        !          86981:             (isset($this->_packageInfo['helper'])) ?
        !          86982:                 $ret['helper'] = $this->_packageInfo['helper'] :null;
        !          86983:             return $ret;
        !          86984:         } else {
        !          86985:             $ret = array();
        !          86986:             $leads = isset($this->_packageInfo['lead'][0]) ? $this->_packageInfo['lead'] :
        !          86987:                 array($this->_packageInfo['lead']);
        !          86988:             foreach ($leads as $lead) {
        !          86989:                 $s = $lead;
        !          86990:                 $s['handle'] = $s['user'];
        !          86991:                 unset($s['user']);
        !          86992:                 $s['role'] = 'lead';
        !          86993:                 $ret[] = $s;
        !          86994:             }
        !          86995:             if (isset($this->_packageInfo['developer'])) {
        !          86996:                 $leads = isset($this->_packageInfo['developer'][0]) ?
        !          86997:                     $this->_packageInfo['developer'] :
        !          86998:                     array($this->_packageInfo['developer']);
        !          86999:                 foreach ($leads as $maintainer) {
        !          87000:                     $s = $maintainer;
        !          87001:                     $s['handle'] = $s['user'];
        !          87002:                     unset($s['user']);
        !          87003:                     $s['role'] = 'developer';
        !          87004:                     $ret[] = $s;
        !          87005:                 }
        !          87006:             }
        !          87007:             if (isset($this->_packageInfo['contributor'])) {
        !          87008:                 $leads = isset($this->_packageInfo['contributor'][0]) ?
        !          87009:                     $this->_packageInfo['contributor'] :
        !          87010:                     array($this->_packageInfo['contributor']);
        !          87011:                 foreach ($leads as $maintainer) {
        !          87012:                     $s = $maintainer;
        !          87013:                     $s['handle'] = $s['user'];
        !          87014:                     unset($s['user']);
        !          87015:                     $s['role'] = 'contributor';
        !          87016:                     $ret[] = $s;
        !          87017:                 }
        !          87018:             }
        !          87019:             if (isset($this->_packageInfo['helper'])) {
        !          87020:                 $leads = isset($this->_packageInfo['helper'][0]) ?
        !          87021:                     $this->_packageInfo['helper'] :
        !          87022:                     array($this->_packageInfo['helper']);
        !          87023:                 foreach ($leads as $maintainer) {
        !          87024:                     $s = $maintainer;
        !          87025:                     $s['handle'] = $s['user'];
        !          87026:                     unset($s['user']);
        !          87027:                     $s['role'] = 'helper';
        !          87028:                     $ret[] = $s;
        !          87029:                 }
        !          87030:             }
        !          87031:             return $ret;
1.1       misho    87032:         }
1.1.1.2 ! misho    87033:         return false;
        !          87034:     }
1.1       misho    87035: 
1.1.1.2 ! misho    87036:     function getLeads()
        !          87037:     {
        !          87038:         if (isset($this->_packageInfo['lead'])) {
        !          87039:             return $this->_packageInfo['lead'];
1.1       misho    87040:         }
1.1.1.2 ! misho    87041:         return false;
1.1       misho    87042:     }
                   87043: 
1.1.1.2 ! misho    87044:     function getDevelopers()
1.1       misho    87045:     {
1.1.1.2 ! misho    87046:         if (isset($this->_packageInfo['developer'])) {
        !          87047:             return $this->_packageInfo['developer'];
1.1       misho    87048:         }
1.1.1.2 ! misho    87049:         return false;
1.1       misho    87050:     }
                   87051: 
1.1.1.2 ! misho    87052:     function getContributors()
1.1       misho    87053:     {
1.1.1.2 ! misho    87054:         if (isset($this->_packageInfo['contributor'])) {
        !          87055:             return $this->_packageInfo['contributor'];
1.1       misho    87056:         }
1.1.1.2 ! misho    87057:         return false;
1.1       misho    87058:     }
                   87059: 
1.1.1.2 ! misho    87060:     function getHelpers()
1.1       misho    87061:     {
1.1.1.2 ! misho    87062:         if (isset($this->_packageInfo['helper'])) {
        !          87063:             return $this->_packageInfo['helper'];
1.1       misho    87064:         }
1.1.1.2 ! misho    87065:         return false;
        !          87066:     }
1.1       misho    87067: 
1.1.1.2 ! misho    87068:     function setDate($date)
        !          87069:     {
        !          87070:         if (!isset($this->_packageInfo['date'])) {
        !          87071:             // ensure that the extends tag is set up in the right location
        !          87072:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
        !          87073:                 array('time', 'version',
        !          87074:                     'stability', 'license', 'notes', 'contents', 'compatible',
        !          87075:                     'dependencies', 'providesextension', 'srcpackage', 'srcuri',
        !          87076:                     'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease',
        !          87077:                     'zendextbinrelease', 'bundle', 'changelog'), array(), 'date');
1.1       misho    87078:         }
1.1.1.2 ! misho    87079:         $this->_packageInfo['date'] = $date;
        !          87080:         $this->_isValid = 0;
        !          87081:     }
1.1       misho    87082: 
1.1.1.2 ! misho    87083:     function setTime($time)
        !          87084:     {
        !          87085:         $this->_isValid = 0;
        !          87086:         if (!isset($this->_packageInfo['time'])) {
        !          87087:             // ensure that the time tag is set up in the right location
        !          87088:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
        !          87089:                     array('version',
        !          87090:                     'stability', 'license', 'notes', 'contents', 'compatible',
        !          87091:                     'dependencies', 'providesextension', 'srcpackage', 'srcuri',
        !          87092:                     'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease',
        !          87093:                     'zendextbinrelease', 'bundle', 'changelog'), $time, 'time');
1.1       misho    87094:         }
1.1.1.2 ! misho    87095:         $this->_packageInfo['time'] = $time;
        !          87096:     }
1.1       misho    87097: 
1.1.1.2 ! misho    87098:     function getDate()
        !          87099:     {
        !          87100:         if (isset($this->_packageInfo['date'])) {
        !          87101:             return $this->_packageInfo['date'];
1.1       misho    87102:         }
1.1.1.2 ! misho    87103:         return false;
        !          87104:     }
        !          87105: 
        !          87106:     function getTime()
        !          87107:     {
        !          87108:         if (isset($this->_packageInfo['time'])) {
        !          87109:             return $this->_packageInfo['time'];
1.1       misho    87110:         }
1.1.1.2 ! misho    87111:         return false;
        !          87112:     }
1.1       misho    87113: 
1.1.1.2 ! misho    87114:     /**
        !          87115:      * @param package|api version category to return
        !          87116:      */
        !          87117:     function getVersion($key = 'release')
        !          87118:     {
        !          87119:         if (isset($this->_packageInfo['version'][$key])) {
        !          87120:             return $this->_packageInfo['version'][$key];
        !          87121:         }
        !          87122:         return false;
1.1       misho    87123:     }
                   87124: 
1.1.1.2 ! misho    87125:     function getStability()
1.1       misho    87126:     {
1.1.1.2 ! misho    87127:         if (isset($this->_packageInfo['stability'])) {
        !          87128:             return $this->_packageInfo['stability'];
        !          87129:         }
        !          87130:         return false;
        !          87131:     }
1.1       misho    87132: 
1.1.1.2 ! misho    87133:     function getState($key = 'release')
        !          87134:     {
        !          87135:         if (isset($this->_packageInfo['stability'][$key])) {
        !          87136:             return $this->_packageInfo['stability'][$key];
        !          87137:         }
        !          87138:         return false;
        !          87139:     }
1.1       misho    87140: 
1.1.1.2 ! misho    87141:     function getLicense($raw = false)
        !          87142:     {
        !          87143:         if (isset($this->_packageInfo['license'])) {
        !          87144:             if ($raw) {
        !          87145:                 return $this->_packageInfo['license'];
        !          87146:             }
        !          87147:             if (is_array($this->_packageInfo['license'])) {
        !          87148:                 return $this->_packageInfo['license']['_content'];
1.1       misho    87149:             } else {
1.1.1.2 ! misho    87150:                 return $this->_packageInfo['license'];
1.1       misho    87151:             }
                   87152:         }
1.1.1.2 ! misho    87153:         return false;
        !          87154:     }
1.1       misho    87155: 
1.1.1.2 ! misho    87156:     function getLicenseLocation()
        !          87157:     {
        !          87158:         if (!isset($this->_packageInfo['license']) || !is_array($this->_packageInfo['license'])) {
        !          87159:             return false;
1.1       misho    87160:         }
1.1.1.2 ! misho    87161:         return $this->_packageInfo['license']['attribs'];
        !          87162:     }
1.1       misho    87163: 
1.1.1.2 ! misho    87164:     function getNotes()
        !          87165:     {
        !          87166:         if (isset($this->_packageInfo['notes'])) {
        !          87167:             return $this->_packageInfo['notes'];
1.1       misho    87168:         }
1.1.1.2 ! misho    87169:         return false;
1.1       misho    87170:     }
1.1.1.2 ! misho    87171: 
1.1       misho    87172:     /**
1.1.1.2 ! misho    87173:      * Return the <usesrole> tag contents, if any
        !          87174:      * @return array|false
1.1       misho    87175:      */
1.1.1.2 ! misho    87176:     function getUsesrole()
1.1       misho    87177:     {
1.1.1.2 ! misho    87178:         if (isset($this->_packageInfo['usesrole'])) {
        !          87179:             return $this->_packageInfo['usesrole'];
        !          87180:         }
        !          87181:         return false;
1.1       misho    87182:     }
                   87183: 
1.1.1.2 ! misho    87184:     /**
        !          87185:      * Return the <usestask> tag contents, if any
        !          87186:      * @return array|false
        !          87187:      */
        !          87188:     function getUsestask()
1.1       misho    87189:     {
1.1.1.2 ! misho    87190:         if (isset($this->_packageInfo['usestask'])) {
        !          87191:             return $this->_packageInfo['usestask'];
        !          87192:         }
        !          87193:         return false;
1.1       misho    87194:     }
                   87195: 
1.1.1.2 ! misho    87196:     /**
        !          87197:      * This should only be used to retrieve filenames and install attributes
        !          87198:      */
        !          87199:     function getFilelist($preserve = false)
1.1       misho    87200:     {
1.1.1.2 ! misho    87201:         if (isset($this->_packageInfo['filelist']) && !$preserve) {
        !          87202:             return $this->_packageInfo['filelist'];
        !          87203:         }
        !          87204:         $this->flattenFilelist();
        !          87205:         if ($contents = $this->getContents()) {
        !          87206:             $ret = array();
        !          87207:             if (!isset($contents['dir'])) {
        !          87208:                 return false;
        !          87209:             }
        !          87210:             if (!isset($contents['dir']['file'][0])) {
        !          87211:                 $contents['dir']['file'] = array($contents['dir']['file']);
        !          87212:             }
        !          87213:             foreach ($contents['dir']['file'] as $file) {
        !          87214:                 $name = $file['attribs']['name'];
        !          87215:                 if (!$preserve) {
        !          87216:                     $file = $file['attribs'];
        !          87217:                 }
        !          87218:                 $ret[$name] = $file;
        !          87219:             }
        !          87220:             if (!$preserve) {
        !          87221:                 $this->_packageInfo['filelist'] = $ret;
        !          87222:             }
        !          87223:             return $ret;
        !          87224:         }
        !          87225:         return false;
1.1       misho    87226:     }
                   87227: 
                   87228:     /**
1.1.1.2 ! misho    87229:      * Return configure options array, if any
        !          87230:      *
        !          87231:      * @return array|false
1.1       misho    87232:      */
1.1.1.2 ! misho    87233:     function getConfigureOptions()
1.1       misho    87234:     {
1.1.1.2 ! misho    87235:         if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
        !          87236:             return false;
1.1       misho    87237:         }
                   87238: 
1.1.1.2 ! misho    87239:         $releases = $this->getReleases();
        !          87240:         if (isset($releases[0])) {
        !          87241:             $releases = $releases[0];
1.1       misho    87242:         }
                   87243: 
1.1.1.2 ! misho    87244:         if (isset($releases['configureoption'])) {
        !          87245:             if (!isset($releases['configureoption'][0])) {
        !          87246:                 $releases['configureoption'] = array($releases['configureoption']);
        !          87247:             }
1.1       misho    87248: 
1.1.1.2 ! misho    87249:             for ($i = 0; $i < count($releases['configureoption']); $i++) {
        !          87250:                 $releases['configureoption'][$i] = $releases['configureoption'][$i]['attribs'];
        !          87251:             }
        !          87252: 
        !          87253:             return $releases['configureoption'];
1.1       misho    87254:         }
1.1.1.2 ! misho    87255: 
        !          87256:         return false;
1.1       misho    87257:     }
                   87258: 
                   87259:     /**
1.1.1.2 ! misho    87260:      * This is only used at install-time, after all serialization
        !          87261:      * is over.
1.1       misho    87262:      */
1.1.1.2 ! misho    87263:     function resetFilelist()
1.1       misho    87264:     {
1.1.1.2 ! misho    87265:         $this->_packageInfo['filelist'] = array();
1.1       misho    87266:     }
                   87267: 
                   87268:     /**
1.1.1.2 ! misho    87269:      * Retrieve a list of files that should be installed on this computer
        !          87270:      * @return array
1.1       misho    87271:      */
1.1.1.2 ! misho    87272:     function getInstallationFilelist($forfilecheck = false)
1.1       misho    87273:     {
1.1.1.2 ! misho    87274:         $contents = $this->getFilelist(true);
        !          87275:         if (isset($contents['dir']['attribs']['baseinstalldir'])) {
        !          87276:             $base = $contents['dir']['attribs']['baseinstalldir'];
        !          87277:         }
        !          87278:         if (isset($this->_packageInfo['bundle'])) {
        !          87279:             return PEAR::raiseError(
        !          87280:                 'Exception: bundles should be handled in download code only');
        !          87281:         }
        !          87282:         $release = $this->getReleases();
        !          87283:         if ($release) {
        !          87284:             if (!isset($release[0])) {
        !          87285:                 if (!isset($release['installconditions']) && !isset($release['filelist'])) {
        !          87286:                     if ($forfilecheck) {
        !          87287:                         return $this->getFilelist();
1.1       misho    87288:                     }
1.1.1.2 ! misho    87289:                     return $contents;
1.1       misho    87290:                 }
1.1.1.2 ! misho    87291:                 $release = array($release);
        !          87292:             }
        !          87293:             $depchecker = &$this->getPEARDependency2($this->_config, array(),
        !          87294:                 array('channel' => $this->getChannel(), 'package' => $this->getPackage()),
        !          87295:                 PEAR_VALIDATE_INSTALLING);
        !          87296:             foreach ($release as $instance) {
        !          87297:                 if (isset($instance['installconditions'])) {
        !          87298:                     $installconditions = $instance['installconditions'];
        !          87299:                     if (is_array($installconditions)) {
        !          87300:                         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          87301:                         foreach ($installconditions as $type => $conditions) {
        !          87302:                             if (!isset($conditions[0])) {
        !          87303:                                 $conditions = array($conditions);
        !          87304:                             }
        !          87305:                             foreach ($conditions as $condition) {
        !          87306:                                 $ret = $depchecker->{"validate{$type}Dependency"}($condition);
        !          87307:                                 if (PEAR::isError($ret)) {
        !          87308:                                     PEAR::popErrorHandling();
        !          87309:                                     continue 3; // skip this release
        !          87310:                                 }
        !          87311:                             }
1.1       misho    87312:                         }
1.1.1.2 ! misho    87313:                         PEAR::popErrorHandling();
1.1       misho    87314:                     }
1.1.1.2 ! misho    87315:                 }
        !          87316:                 // this is the release to use
        !          87317:                 if (isset($instance['filelist'])) {
        !          87318:                     // ignore files
        !          87319:                     if (isset($instance['filelist']['ignore'])) {
        !          87320:                         $ignore = isset($instance['filelist']['ignore'][0]) ?
        !          87321:                             $instance['filelist']['ignore'] :
        !          87322:                             array($instance['filelist']['ignore']);
        !          87323:                         foreach ($ignore as $ig) {
        !          87324:                             unset ($contents[$ig['attribs']['name']]);
        !          87325:                         }
1.1       misho    87326:                     }
1.1.1.2 ! misho    87327:                     // install files as this name
        !          87328:                     if (isset($instance['filelist']['install'])) {
        !          87329:                         $installas = isset($instance['filelist']['install'][0]) ?
        !          87330:                             $instance['filelist']['install'] :
        !          87331:                             array($instance['filelist']['install']);
        !          87332:                         foreach ($installas as $as) {
        !          87333:                             $contents[$as['attribs']['name']]['attribs']['install-as'] =
        !          87334:                                 $as['attribs']['as'];
        !          87335:                         }
1.1       misho    87336:                     }
                   87337:                 }
1.1.1.2 ! misho    87338:                 if ($forfilecheck) {
        !          87339:                     foreach ($contents as $file => $attrs) {
        !          87340:                         $contents[$file] = $attrs['attribs'];
        !          87341:                     }
1.1       misho    87342:                 }
1.1.1.2 ! misho    87343:                 return $contents;
        !          87344:             }
        !          87345:         } else { // simple release - no installconditions or install-as
        !          87346:             if ($forfilecheck) {
        !          87347:                 return $this->getFilelist();
        !          87348:             }
        !          87349:             return $contents;
1.1       misho    87350:         }
1.1.1.2 ! misho    87351:         // no releases matched
        !          87352:         return PEAR::raiseError('No releases in package.xml matched the existing operating ' .
        !          87353:             'system, extensions installed, or architecture, cannot install');
1.1       misho    87354:     }
                   87355: 
                   87356:     /**
1.1.1.2 ! misho    87357:      * This is only used at install-time, after all serialization
        !          87358:      * is over.
        !          87359:      * @param string file name
        !          87360:      * @param string installed path
1.1       misho    87361:      */
1.1.1.2 ! misho    87362:     function setInstalledAs($file, $path)
1.1       misho    87363:     {
1.1.1.2 ! misho    87364:         if ($path) {
        !          87365:             return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
1.1       misho    87366:         }
1.1.1.2 ! misho    87367:         unset($this->_packageInfo['filelist'][$file]['installed_as']);
1.1       misho    87368:     }
                   87369: 
1.1.1.2 ! misho    87370:     function getInstalledLocation($file)
        !          87371:     {
        !          87372:         if (isset($this->_packageInfo['filelist'][$file]['installed_as'])) {
        !          87373:             return $this->_packageInfo['filelist'][$file]['installed_as'];
        !          87374:         }
        !          87375:         return false;
        !          87376:     }
1.1       misho    87377: 
                   87378:     /**
1.1.1.2 ! misho    87379:      * This is only used at install-time, after all serialization
        !          87380:      * is over.
1.1       misho    87381:      */
1.1.1.2 ! misho    87382:     function installedFile($file, $atts)
1.1       misho    87383:     {
1.1.1.2 ! misho    87384:         if (isset($this->_packageInfo['filelist'][$file])) {
        !          87385:             $this->_packageInfo['filelist'][$file] =
        !          87386:                 array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']);
        !          87387:         } else {
        !          87388:             $this->_packageInfo['filelist'][$file] = $atts['attribs'];
1.1       misho    87389:         }
                   87390:     }
                   87391: 
1.1.1.2 ! misho    87392:     /**
        !          87393:      * Retrieve the contents tag
        !          87394:      */
        !          87395:     function getContents()
        !          87396:     {
        !          87397:         if (isset($this->_packageInfo['contents'])) {
        !          87398:             return $this->_packageInfo['contents'];
        !          87399:         }
        !          87400:         return false;
        !          87401:     }
        !          87402: 
        !          87403:     /**
        !          87404:      * @param string full path to file
        !          87405:      * @param string attribute name
        !          87406:      * @param string attribute value
        !          87407:      * @param int risky but fast - use this to choose a file based on its position in the list
        !          87408:      *            of files.  Index is zero-based like PHP arrays.
        !          87409:      * @return bool success of operation
        !          87410:      */
        !          87411:     function setFileAttribute($filename, $attr, $value, $index = false)
        !          87412:     {
        !          87413:         $this->_isValid = 0;
        !          87414:         if (in_array($attr, array('role', 'name', 'baseinstalldir'))) {
        !          87415:             $this->_filesValid = false;
        !          87416:         }
        !          87417:         if ($index !== false &&
        !          87418:               isset($this->_packageInfo['contents']['dir']['file'][$index]['attribs'])) {
        !          87419:             $this->_packageInfo['contents']['dir']['file'][$index]['attribs'][$attr] = $value;
        !          87420:             return true;
        !          87421:         }
        !          87422:         if (!isset($this->_packageInfo['contents']['dir']['file'])) {
        !          87423:             return false;
        !          87424:         }
        !          87425:         $files = $this->_packageInfo['contents']['dir']['file'];
        !          87426:         if (!isset($files[0])) {
        !          87427:             $files = array($files);
        !          87428:             $ind = false;
        !          87429:         } else {
        !          87430:             $ind = true;
        !          87431:         }
        !          87432:         foreach ($files as $i => $file) {
        !          87433:             if (isset($file['attribs'])) {
        !          87434:                 if ($file['attribs']['name'] == $filename) {
        !          87435:                     if ($ind) {
        !          87436:                         $this->_packageInfo['contents']['dir']['file'][$i]['attribs'][$attr] = $value;
        !          87437:                     } else {
        !          87438:                         $this->_packageInfo['contents']['dir']['file']['attribs'][$attr] = $value;
        !          87439:                     }
        !          87440:                     return true;
        !          87441:                 }
        !          87442:             }
        !          87443:         }
        !          87444:         return false;
        !          87445:     }
1.1       misho    87446: 
1.1.1.2 ! misho    87447:     function setDirtree($path)
1.1       misho    87448:     {
1.1.1.2 ! misho    87449:         if (!isset($this->_packageInfo['dirtree'])) {
        !          87450:             $this->_packageInfo['dirtree'] = array();
        !          87451:         }
        !          87452:         $this->_packageInfo['dirtree'][$path] = true;
1.1       misho    87453:     }
                   87454: 
1.1.1.2 ! misho    87455:     function getDirtree()
1.1       misho    87456:     {
1.1.1.2 ! misho    87457:         if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) {
        !          87458:             return $this->_packageInfo['dirtree'];
        !          87459:         }
        !          87460:         return false;
1.1       misho    87461:     }
1.1.1.2 ! misho    87462: 
        !          87463:     function resetDirtree()
1.1       misho    87464:     {
1.1.1.2 ! misho    87465:         unset($this->_packageInfo['dirtree']);
1.1       misho    87466:     }
                   87467: 
                   87468:     /**
1.1.1.2 ! misho    87469:      * Determines whether this package claims it is compatible with the version of
        !          87470:      * the package that has a recommended version dependency
        !          87471:      * @param PEAR_PackageFile_v2|PEAR_PackageFile_v1|PEAR_Downloader_Package
        !          87472:      * @return boolean
1.1       misho    87473:      */
1.1.1.2 ! misho    87474:     function isCompatible($pf)
1.1       misho    87475:     {
1.1.1.2 ! misho    87476:         if (!isset($this->_packageInfo['compatible'])) {
        !          87477:             return false;
1.1       misho    87478:         }
1.1.1.2 ! misho    87479:         if (!isset($this->_packageInfo['channel'])) {
        !          87480:             return false;
        !          87481:         }
        !          87482:         $me = $pf->getVersion();
        !          87483:         $compatible = $this->_packageInfo['compatible'];
        !          87484:         if (!isset($compatible[0])) {
        !          87485:             $compatible = array($compatible);
        !          87486:         }
        !          87487:         $found = false;
        !          87488:         foreach ($compatible as $info) {
        !          87489:             if (strtolower($info['name']) == strtolower($pf->getPackage())) {
        !          87490:                 if (strtolower($info['channel']) == strtolower($pf->getChannel())) {
        !          87491:                     $found = true;
        !          87492:                     break;
        !          87493:                 }
        !          87494:             }
        !          87495:         }
        !          87496:         if (!$found) {
        !          87497:             return false;
        !          87498:         }
        !          87499:         if (isset($info['exclude'])) {
        !          87500:             if (!isset($info['exclude'][0])) {
        !          87501:                 $info['exclude'] = array($info['exclude']);
        !          87502:             }
        !          87503:             foreach ($info['exclude'] as $exclude) {
        !          87504:                 if (version_compare($me, $exclude, '==')) {
        !          87505:                     return false;
        !          87506:                 }
        !          87507:             }
        !          87508:         }
        !          87509:         if (version_compare($me, $info['min'], '>=') && version_compare($me, $info['max'], '<=')) {
        !          87510:             return true;
        !          87511:         }
        !          87512:         return false;
1.1       misho    87513:     }
                   87514: 
                   87515:     /**
1.1.1.2 ! misho    87516:      * @return array|false
1.1       misho    87517:      */
1.1.1.2 ! misho    87518:     function getCompatible()
1.1       misho    87519:     {
1.1.1.2 ! misho    87520:         if (isset($this->_packageInfo['compatible'])) {
        !          87521:             return $this->_packageInfo['compatible'];
1.1       misho    87522:         }
1.1.1.2 ! misho    87523:         return false;
        !          87524:     }
1.1       misho    87525: 
1.1.1.2 ! misho    87526:     function getDependencies()
        !          87527:     {
        !          87528:         if (isset($this->_packageInfo['dependencies'])) {
        !          87529:             return $this->_packageInfo['dependencies'];
1.1       misho    87530:         }
1.1.1.2 ! misho    87531:         return false;
1.1       misho    87532:     }
                   87533: 
1.1.1.2 ! misho    87534:     function isSubpackageOf($p)
        !          87535:     {
        !          87536:         return $p->isSubpackage($this);
        !          87537:     }
1.1       misho    87538: 
                   87539:     /**
1.1.1.2 ! misho    87540:      * Determines whether the passed in package is a subpackage of this package.
        !          87541:      *
        !          87542:      * No version checking is done, only name verification.
        !          87543:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
        !          87544:      * @return bool
1.1       misho    87545:      */
1.1.1.2 ! misho    87546:     function isSubpackage($p)
        !          87547:     {
        !          87548:         $sub = array();
        !          87549:         if (isset($this->_packageInfo['dependencies']['required']['subpackage'])) {
        !          87550:             $sub = $this->_packageInfo['dependencies']['required']['subpackage'];
        !          87551:             if (!isset($sub[0])) {
        !          87552:                 $sub = array($sub);
        !          87553:             }
        !          87554:         }
        !          87555:         if (isset($this->_packageInfo['dependencies']['optional']['subpackage'])) {
        !          87556:             $sub1 = $this->_packageInfo['dependencies']['optional']['subpackage'];
        !          87557:             if (!isset($sub1[0])) {
        !          87558:                 $sub1 = array($sub1);
        !          87559:             }
        !          87560:             $sub = array_merge($sub, $sub1);
        !          87561:         }
        !          87562:         if (isset($this->_packageInfo['dependencies']['group'])) {
        !          87563:             $group = $this->_packageInfo['dependencies']['group'];
        !          87564:             if (!isset($group[0])) {
        !          87565:                 $group = array($group);
        !          87566:             }
        !          87567:             foreach ($group as $deps) {
        !          87568:                 if (isset($deps['subpackage'])) {
        !          87569:                     $sub2 = $deps['subpackage'];
        !          87570:                     if (!isset($sub2[0])) {
        !          87571:                         $sub2 = array($sub2);
        !          87572:                     }
        !          87573:                     $sub = array_merge($sub, $sub2);
        !          87574:                 }
        !          87575:             }
        !          87576:         }
        !          87577:         foreach ($sub as $dep) {
        !          87578:             if (strtolower($dep['name']) == strtolower($p->getPackage())) {
        !          87579:                 if (isset($dep['channel'])) {
        !          87580:                     if (strtolower($dep['channel']) == strtolower($p->getChannel())) {
        !          87581:                         return true;
        !          87582:                     }
        !          87583:                 } else {
        !          87584:                     if ($dep['uri'] == $p->getURI()) {
        !          87585:                         return true;
        !          87586:                     }
        !          87587:                 }
        !          87588:             }
        !          87589:         }
        !          87590:         return false;
        !          87591:     }
        !          87592: 
        !          87593:     function dependsOn($package, $channel)
        !          87594:     {
        !          87595:         if (!($deps = $this->getDependencies())) {
        !          87596:             return false;
        !          87597:         }
        !          87598:         foreach (array('package', 'subpackage') as $type) {
        !          87599:             foreach (array('required', 'optional') as $needed) {
        !          87600:                 if (isset($deps[$needed][$type])) {
        !          87601:                     if (!isset($deps[$needed][$type][0])) {
        !          87602:                         $deps[$needed][$type] = array($deps[$needed][$type]);
        !          87603:                     }
        !          87604:                     foreach ($deps[$needed][$type] as $dep) {
        !          87605:                         $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
        !          87606:                         if (strtolower($dep['name']) == strtolower($package) &&
        !          87607:                               $depchannel == $channel) {
        !          87608:                             return true;
        !          87609:                         }
        !          87610:                     }
        !          87611:                 }
        !          87612:             }
        !          87613:             if (isset($deps['group'])) {
        !          87614:                 if (!isset($deps['group'][0])) {
        !          87615:                     $dep['group'] = array($deps['group']);
        !          87616:                 }
        !          87617:                 foreach ($deps['group'] as $group) {
        !          87618:                     if (isset($group[$type])) {
        !          87619:                         if (!is_array($group[$type])) {
        !          87620:                             $group[$type] = array($group[$type]);
        !          87621:                         }
        !          87622:                         foreach ($group[$type] as $dep) {
        !          87623:                             $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
        !          87624:                             if (strtolower($dep['name']) == strtolower($package) &&
        !          87625:                                   $depchannel == $channel) {
        !          87626:                                 return true;
        !          87627:                             }
        !          87628:                         }
        !          87629:                     }
        !          87630:                 }
        !          87631:             }
        !          87632:         }
        !          87633:         return false;
        !          87634:     }
1.1       misho    87635: 
                   87636:     /**
1.1.1.2 ! misho    87637:      * Get the contents of a dependency group
        !          87638:      * @param string
        !          87639:      * @return array|false
1.1       misho    87640:      */
1.1.1.2 ! misho    87641:     function getDependencyGroup($name)
        !          87642:     {
        !          87643:         $name = strtolower($name);
        !          87644:         if (!isset($this->_packageInfo['dependencies']['group'])) {
        !          87645:             return false;
        !          87646:         }
        !          87647:         $groups = $this->_packageInfo['dependencies']['group'];
        !          87648:         if (!isset($groups[0])) {
        !          87649:             $groups = array($groups);
        !          87650:         }
        !          87651:         foreach ($groups as $group) {
        !          87652:             if (strtolower($group['attribs']['name']) == $name) {
        !          87653:                 return $group;
        !          87654:             }
        !          87655:         }
        !          87656:         return false;
        !          87657:     }
1.1       misho    87658: 
                   87659:     /**
1.1.1.2 ! misho    87660:      * Retrieve a partial package.xml 1.0 representation of dependencies
        !          87661:      *
        !          87662:      * a very limited representation of dependencies is returned by this method.
        !          87663:      * The <exclude> tag for excluding certain versions of a dependency is
        !          87664:      * completely ignored.  In addition, dependency groups are ignored, with the
        !          87665:      * assumption that all dependencies in dependency groups are also listed in
        !          87666:      * the optional group that work with all dependency groups
        !          87667:      * @param boolean return package.xml 2.0 <dependencies> tag
        !          87668:      * @return array|false
1.1       misho    87669:      */
1.1.1.2 ! misho    87670:     function getDeps($raw = false, $nopearinstaller = false)
        !          87671:     {
        !          87672:         if (isset($this->_packageInfo['dependencies'])) {
        !          87673:             if ($raw) {
        !          87674:                 return $this->_packageInfo['dependencies'];
        !          87675:             }
        !          87676:             $ret = array();
        !          87677:             $map = array(
        !          87678:                 'php' => 'php',
        !          87679:                 'package' => 'pkg',
        !          87680:                 'subpackage' => 'pkg',
        !          87681:                 'extension' => 'ext',
        !          87682:                 'os' => 'os',
        !          87683:                 'pearinstaller' => 'pkg',
        !          87684:                 );
        !          87685:             foreach (array('required', 'optional') as $type) {
        !          87686:                 $optional = ($type == 'optional') ? 'yes' : 'no';
        !          87687:                 if (!isset($this->_packageInfo['dependencies'][$type])
        !          87688:                     || empty($this->_packageInfo['dependencies'][$type])) {
        !          87689:                     continue;
        !          87690:                 }
        !          87691:                 foreach ($this->_packageInfo['dependencies'][$type] as $dtype => $deps) {
        !          87692:                     if ($dtype == 'pearinstaller' && $nopearinstaller) {
        !          87693:                         continue;
        !          87694:                     }
        !          87695:                     if (!isset($deps[0])) {
        !          87696:                         $deps = array($deps);
        !          87697:                     }
        !          87698:                     foreach ($deps as $dep) {
        !          87699:                         if (!isset($map[$dtype])) {
        !          87700:                             // no support for arch type
        !          87701:                             continue;
        !          87702:                         }
        !          87703:                         if ($dtype == 'pearinstaller') {
        !          87704:                             $dep['name'] = 'PEAR';
        !          87705:                             $dep['channel'] = 'pear.php.net';
        !          87706:                         }
        !          87707:                         $s = array('type' => $map[$dtype]);
        !          87708:                         if (isset($dep['channel'])) {
        !          87709:                             $s['channel'] = $dep['channel'];
        !          87710:                         }
        !          87711:                         if (isset($dep['uri'])) {
        !          87712:                             $s['uri'] = $dep['uri'];
        !          87713:                         }
        !          87714:                         if (isset($dep['name'])) {
        !          87715:                             $s['name'] = $dep['name'];
        !          87716:                         }
        !          87717:                         if (isset($dep['conflicts'])) {
        !          87718:                             $s['rel'] = 'not';
        !          87719:                         } else {
        !          87720:                             if (!isset($dep['min']) &&
        !          87721:                                   !isset($dep['max'])) {
        !          87722:                                 $s['rel'] = 'has';
        !          87723:                                 $s['optional'] = $optional;
        !          87724:                             } elseif (isset($dep['min']) &&
        !          87725:                                   isset($dep['max'])) {
        !          87726:                                 $s['rel'] = 'ge';
        !          87727:                                 $s1 = $s;
        !          87728:                                 $s1['rel'] = 'le';
        !          87729:                                 $s['version'] = $dep['min'];
        !          87730:                                 $s1['version'] = $dep['max'];
        !          87731:                                 if (isset($dep['channel'])) {
        !          87732:                                     $s1['channel'] = $dep['channel'];
        !          87733:                                 }
        !          87734:                                 if ($dtype != 'php') {
        !          87735:                                     $s['name'] = $dep['name'];
        !          87736:                                     $s1['name'] = $dep['name'];
        !          87737:                                 }
        !          87738:                                 $s['optional'] = $optional;
        !          87739:                                 $s1['optional'] = $optional;
        !          87740:                                 $ret[] = $s1;
        !          87741:                             } elseif (isset($dep['min'])) {
        !          87742:                                 if (isset($dep['exclude']) &&
        !          87743:                                       $dep['exclude'] == $dep['min']) {
        !          87744:                                     $s['rel'] = 'gt';
        !          87745:                                 } else {
        !          87746:                                     $s['rel'] = 'ge';
        !          87747:                                 }
        !          87748:                                 $s['version'] = $dep['min'];
        !          87749:                                 $s['optional'] = $optional;
        !          87750:                                 if ($dtype != 'php') {
        !          87751:                                     $s['name'] = $dep['name'];
        !          87752:                                 }
        !          87753:                             } elseif (isset($dep['max'])) {
        !          87754:                                 if (isset($dep['exclude']) &&
        !          87755:                                       $dep['exclude'] == $dep['max']) {
        !          87756:                                     $s['rel'] = 'lt';
        !          87757:                                 } else {
        !          87758:                                     $s['rel'] = 'le';
        !          87759:                                 }
        !          87760:                                 $s['version'] = $dep['max'];
        !          87761:                                 $s['optional'] = $optional;
        !          87762:                                 if ($dtype != 'php') {
        !          87763:                                     $s['name'] = $dep['name'];
        !          87764:                                 }
        !          87765:                             }
        !          87766:                         }
        !          87767:                         $ret[] = $s;
        !          87768:                     }
        !          87769:                 }
        !          87770:             }
        !          87771:             if (count($ret)) {
        !          87772:                 return $ret;
        !          87773:             }
        !          87774:         }
        !          87775:         return false;
        !          87776:     }
1.1       misho    87777: 
                   87778:     /**
1.1.1.2 ! misho    87779:      * @return php|extsrc|extbin|zendextsrc|zendextbin|bundle|false
1.1       misho    87780:      */
1.1.1.2 ! misho    87781:     function getPackageType()
        !          87782:     {
        !          87783:         if (isset($this->_packageInfo['phprelease'])) {
        !          87784:             return 'php';
        !          87785:         }
        !          87786:         if (isset($this->_packageInfo['extsrcrelease'])) {
        !          87787:             return 'extsrc';
        !          87788:         }
        !          87789:         if (isset($this->_packageInfo['extbinrelease'])) {
        !          87790:             return 'extbin';
        !          87791:         }
        !          87792:         if (isset($this->_packageInfo['zendextsrcrelease'])) {
        !          87793:             return 'zendextsrc';
        !          87794:         }
        !          87795:         if (isset($this->_packageInfo['zendextbinrelease'])) {
        !          87796:             return 'zendextbin';
        !          87797:         }
        !          87798:         if (isset($this->_packageInfo['bundle'])) {
        !          87799:             return 'bundle';
        !          87800:         }
        !          87801:         return false;
        !          87802:     }
1.1       misho    87803: 
                   87804:     /**
1.1.1.2 ! misho    87805:      * @return array|false
1.1       misho    87806:      */
1.1.1.2 ! misho    87807:     function getReleases()
        !          87808:     {
        !          87809:         $type = $this->getPackageType();
        !          87810:         if ($type != 'bundle') {
        !          87811:             $type .= 'release';
        !          87812:         }
        !          87813:         if ($this->getPackageType() && isset($this->_packageInfo[$type])) {
        !          87814:             return $this->_packageInfo[$type];
        !          87815:         }
        !          87816:         return false;
        !          87817:     }
1.1       misho    87818: 
                   87819:     /**
1.1.1.2 ! misho    87820:      * @return array
1.1       misho    87821:      */
1.1.1.2 ! misho    87822:     function getChangelog()
        !          87823:     {
        !          87824:         if (isset($this->_packageInfo['changelog'])) {
        !          87825:             return $this->_packageInfo['changelog'];
        !          87826:         }
        !          87827:         return false;
        !          87828:     }
1.1       misho    87829: 
1.1.1.2 ! misho    87830:     function hasDeps()
        !          87831:     {
        !          87832:         return isset($this->_packageInfo['dependencies']);
        !          87833:     }
1.1       misho    87834: 
1.1.1.2 ! misho    87835:     function getPackagexmlVersion()
        !          87836:     {
        !          87837:         if (isset($this->_packageInfo['zendextsrcrelease'])) {
        !          87838:             return '2.1';
        !          87839:         }
        !          87840:         if (isset($this->_packageInfo['zendextbinrelease'])) {
        !          87841:             return '2.1';
        !          87842:         }
        !          87843:         return '2.0';
        !          87844:     }
1.1       misho    87845: 
                   87846:     /**
1.1.1.2 ! misho    87847:      * @return array|false
1.1       misho    87848:      */
1.1.1.2 ! misho    87849:     function getSourcePackage()
1.1       misho    87850:     {
1.1.1.2 ! misho    87851:         if (isset($this->_packageInfo['extbinrelease']) ||
        !          87852:               isset($this->_packageInfo['zendextbinrelease'])) {
        !          87853:             return array('channel' => $this->_packageInfo['srcchannel'],
        !          87854:                          'package' => $this->_packageInfo['srcpackage']);
        !          87855:         }
        !          87856:         return false;
1.1       misho    87857:     }
                   87858: 
1.1.1.2 ! misho    87859:     function getBundledPackages()
1.1       misho    87860:     {
1.1.1.2 ! misho    87861:         if (isset($this->_packageInfo['bundle'])) {
        !          87862:             return $this->_packageInfo['contents']['bundledpackage'];
        !          87863:         }
1.1       misho    87864:         return false;
                   87865:     }
                   87866: 
1.1.1.2 ! misho    87867:     function getLastModified()
1.1       misho    87868:     {
1.1.1.2 ! misho    87869:         if (isset($this->_packageInfo['_lastmodified'])) {
        !          87870:             return $this->_packageInfo['_lastmodified'];
        !          87871:         }
1.1       misho    87872:         return false;
                   87873:     }
                   87874: 
1.1.1.2 ! misho    87875:     /**
        !          87876:      * Get the contents of a file listed within the package.xml
        !          87877:      * @param string
        !          87878:      * @return string
        !          87879:      */
        !          87880:     function getFileContents($file)
1.1       misho    87881:     {
1.1.1.2 ! misho    87882:         if ($this->_archiveFile == $this->_packageFile) { // unpacked
        !          87883:             $dir = dirname($this->_packageFile);
        !          87884:             $file = $dir . DIRECTORY_SEPARATOR . $file;
        !          87885:             $file = str_replace(array('/', '\\'),
        !          87886:                 array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file);
        !          87887:             if (file_exists($file) && is_readable($file)) {
        !          87888:                 return implode('', file($file));
        !          87889:             }
        !          87890:         } else { // tgz
        !          87891:             $tar = &new Archive_Tar($this->_archiveFile);
        !          87892:             $tar->pushErrorHandling(PEAR_ERROR_RETURN);
        !          87893:             if ($file != 'package.xml' && $file != 'package2.xml') {
        !          87894:                 $file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file;
        !          87895:             }
        !          87896:             $file = $tar->extractInString($file);
        !          87897:             $tar->popErrorHandling();
        !          87898:             if (PEAR::isError($file)) {
        !          87899:                 return PEAR::raiseError("Cannot locate file '$file' in archive");
        !          87900:             }
        !          87901:             return $file;
        !          87902:         }
1.1       misho    87903:     }
                   87904: 
1.1.1.2 ! misho    87905:     function &getRW()
1.1       misho    87906:     {
1.1.1.2 ! misho    87907:         if (!class_exists('PEAR_PackageFile_v2_rw')) {
        !          87908:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2/rw.php';
        !          87909:         }
        !          87910:         $a = new PEAR_PackageFile_v2_rw;
        !          87911:         foreach (get_object_vars($this) as $name => $unused) {
        !          87912:             if (!isset($this->$name)) {
        !          87913:                 continue;
        !          87914:             }
        !          87915:             if ($name == '_config' || $name == '_logger'|| $name == '_registry' ||
        !          87916:                   $name == '_stack') {
        !          87917:                 $a->$name = &$this->$name;
        !          87918:             } else {
        !          87919:                 $a->$name = $this->$name;
        !          87920:             }
        !          87921:         }
        !          87922:         return $a;
        !          87923:     }
        !          87924: 
        !          87925:     function &getDefaultGenerator()
        !          87926:     {
        !          87927:         if (!class_exists('PEAR_PackageFile_Generator_v2')) {
        !          87928:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/Generator/v2.php';
        !          87929:         }
        !          87930:         $a = &new PEAR_PackageFile_Generator_v2($this);
        !          87931:         return $a;
        !          87932:     }
        !          87933: 
        !          87934:     function analyzeSourceCode($file, $string = false)
        !          87935:     {
        !          87936:         if (!isset($this->_v2Validator) ||
        !          87937:               !is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) {
        !          87938:             if (!class_exists('PEAR_PackageFile_v2_Validator')) {
        !          87939:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2/Validator.php';
        !          87940:             }
        !          87941:             $this->_v2Validator = new PEAR_PackageFile_v2_Validator;
        !          87942:         }
        !          87943:         return $this->_v2Validator->analyzeSourceCode($file, $string);
        !          87944:     }
        !          87945: 
        !          87946:     function validate($state = PEAR_VALIDATE_NORMAL)
        !          87947:     {
        !          87948:         if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) {
        !          87949:             return false;
        !          87950:         }
        !          87951:         if (!isset($this->_v2Validator) ||
        !          87952:               !is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) {
        !          87953:             if (!class_exists('PEAR_PackageFile_v2_Validator')) {
        !          87954:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2/Validator.php';
        !          87955:             }
        !          87956:             $this->_v2Validator = new PEAR_PackageFile_v2_Validator;
        !          87957:         }
        !          87958:         if (isset($this->_packageInfo['xsdversion'])) {
        !          87959:             unset($this->_packageInfo['xsdversion']);
        !          87960:         }
        !          87961:         return $this->_v2Validator->validate($this, $state);
        !          87962:     }
        !          87963: 
        !          87964:     function getTasksNs()
        !          87965:     {
        !          87966:         if (!isset($this->_tasksNs)) {
        !          87967:             if (isset($this->_packageInfo['attribs'])) {
        !          87968:                 foreach ($this->_packageInfo['attribs'] as $name => $value) {
        !          87969:                     if ($value == 'http://pear.php.net/dtd/tasks-1.0') {
        !          87970:                         $this->_tasksNs = str_replace('xmlns:', '', $name);
        !          87971:                         break;
        !          87972:                     }
        !          87973:                 }
        !          87974:             }
        !          87975:         }
        !          87976:         return $this->_tasksNs;
1.1       misho    87977:     }
                   87978: 
                   87979:     /**
1.1.1.2 ! misho    87980:      * Determine whether a task name is a valid task.  Custom tasks may be defined
        !          87981:      * using subdirectories by putting a "-" in the name, as in <tasks:mycustom-task>
1.1       misho    87982:      *
1.1.1.2 ! misho    87983:      * Note that this method will auto-load the task class file and test for the existence
        !          87984:      * of the name with "-" replaced by "_" as in PEAR/Task/mycustom/task.php makes class
        !          87985:      * PEAR_Task_mycustom_task
1.1       misho    87986:      * @param string
1.1.1.2 ! misho    87987:      * @return boolean
1.1       misho    87988:      */
1.1.1.2 ! misho    87989:     function getTask($task)
1.1       misho    87990:     {
1.1.1.2 ! misho    87991:         $this->getTasksNs();
        !          87992:         // transform all '-' to '/' and 'tasks:' to '' so tasks:replace becomes replace
        !          87993:         $task = str_replace(array($this->_tasksNs . ':', '-'), array('', ' '), $task);
        !          87994:         $taskfile = str_replace(' ', '/', ucwords($task));
        !          87995:         $task = str_replace(array(' ', '/'), '_', ucwords($task));
        !          87996:         if (class_exists("PEAR_Task_$task")) {
        !          87997:             return "PEAR_Task_$task";
        !          87998:         }
        !          87999:         $fp = @fopen("phar://install-pear-nozlib.phar/PEAR/Task/$taskfile.php", 'r', true);
        !          88000:         if ($fp) {
        !          88001:             fclose($fp);
        !          88002:             require_once  'phar://install-pear-nozlib.phar/' . "PEAR/Task/$taskfile.php";
        !          88003:             return "PEAR_Task_$task";
        !          88004:         }
        !          88005:         return false;
1.1       misho    88006:     }
                   88007: 
                   88008:     /**
1.1.1.2 ! misho    88009:      * Key-friendly array_splice
        !          88010:      * @param tagname to splice a value in before
        !          88011:      * @param mixed the value to splice in
        !          88012:      * @param string the new tag name
1.1       misho    88013:      */
1.1.1.2 ! misho    88014:     function _ksplice($array, $key, $value, $newkey)
1.1       misho    88015:     {
1.1.1.2 ! misho    88016:         $offset = array_search($key, array_keys($array));
        !          88017:         $after = array_slice($array, $offset);
        !          88018:         $before = array_slice($array, 0, $offset);
        !          88019:         $before[$newkey] = $value;
        !          88020:         return array_merge($before, $after);
        !          88021:     }
        !          88022: 
        !          88023:     /**
        !          88024:      * @param array a list of possible keys, in the order they may occur
        !          88025:      * @param mixed contents of the new package.xml tag
        !          88026:      * @param string tag name
        !          88027:      * @access private
        !          88028:      */
        !          88029:     function _insertBefore($array, $keys, $contents, $newkey)
        !          88030:     {
        !          88031:         foreach ($keys as $key) {
        !          88032:             if (isset($array[$key])) {
        !          88033:                 return $array = $this->_ksplice($array, $key, $contents, $newkey);
        !          88034:             }
        !          88035:         }
        !          88036:         $array[$newkey] = $contents;
        !          88037:         return $array;
        !          88038:     }
        !          88039: 
        !          88040:     /**
        !          88041:      * @param subsection of {@link $_packageInfo}
        !          88042:      * @param array|string tag contents
        !          88043:      * @param array format:
        !          88044:      * <pre>
        !          88045:      * array(
        !          88046:      *   tagname => array(list of tag names that follow this one),
        !          88047:      *   childtagname => array(list of child tag names that follow this one),
        !          88048:      * )
        !          88049:      * </pre>
        !          88050:      *
        !          88051:      * This allows construction of nested tags
        !          88052:      * @access private
        !          88053:      */
        !          88054:     function _mergeTag($manip, $contents, $order)
        !          88055:     {
        !          88056:         if (count($order)) {
        !          88057:             foreach ($order as $tag => $curorder) {
        !          88058:                 if (!isset($manip[$tag])) {
        !          88059:                     // ensure that the tag is set up
        !          88060:                     $manip = $this->_insertBefore($manip, $curorder, array(), $tag);
        !          88061:                 }
        !          88062:                 if (count($order) > 1) {
        !          88063:                     $manip[$tag] = $this->_mergeTag($manip[$tag], $contents, array_slice($order, 1));
        !          88064:                     return $manip;
        !          88065:                 }
        !          88066:             }
        !          88067:         } else {
        !          88068:             return $manip;
        !          88069:         }
        !          88070:         if (is_array($manip[$tag]) && !empty($manip[$tag]) && isset($manip[$tag][0])) {
        !          88071:             $manip[$tag][] = $contents;
        !          88072:         } else {
        !          88073:             if (!count($manip[$tag])) {
        !          88074:                 $manip[$tag] = $contents;
        !          88075:             } else {
        !          88076:                 $manip[$tag] = array($manip[$tag]);
        !          88077:                 $manip[$tag][] = $contents;
        !          88078:             }
        !          88079:         }
        !          88080:         return $manip;
        !          88081:     }
        !          88082: }
        !          88083: ?>
        !          88084: <?php
        !          88085: /**
        !          88086:  * PEAR_PackageFile_v2, package.xml version 2.0, read/write version
        !          88087:  *
        !          88088:  * PHP versions 4 and 5
        !          88089:  *
        !          88090:  * @category   pear
        !          88091:  * @package    PEAR
        !          88092:  * @author     Greg Beaver <cellog@php.net>
        !          88093:  * @copyright  1997-2009 The Authors
        !          88094:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          88095:  * @version    CVS: $Id: rw.php 313023 2011-07-06 19:17:11Z dufuz $
        !          88096:  * @link       http://pear.php.net/package/PEAR
        !          88097:  * @since      File available since Release 1.4.0a8
        !          88098:  */
        !          88099: /**
        !          88100:  * For base class
        !          88101:  */
        !          88102: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2.php';
        !          88103: /**
        !          88104:  * @category   pear
        !          88105:  * @package    PEAR
        !          88106:  * @author     Greg Beaver <cellog@php.net>
        !          88107:  * @copyright  1997-2009 The Authors
        !          88108:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          88109:  * @version    Release: 1.9.4
        !          88110:  * @link       http://pear.php.net/package/PEAR
        !          88111:  * @since      Class available since Release 1.4.0a8
        !          88112:  */
        !          88113: class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
        !          88114: {
        !          88115:     /**
        !          88116:      * @param string Extension name
        !          88117:      * @return bool success of operation
        !          88118:      */
        !          88119:     function setProvidesExtension($extension)
        !          88120:     {
        !          88121:         if (in_array($this->getPackageType(),
        !          88122:               array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
        !          88123:             if (!isset($this->_packageInfo['providesextension'])) {
        !          88124:                 // ensure that the channel tag is set up in the right location
        !          88125:                 $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
        !          88126:                     array('usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease',
        !          88127:                     'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
        !          88128:                     'bundle', 'changelog'),
        !          88129:                     $extension, 'providesextension');
        !          88130:             }
        !          88131:             $this->_packageInfo['providesextension'] = $extension;
        !          88132:             return true;
1.1       misho    88133:         }
                   88134:         return false;
                   88135:     }
                   88136: 
1.1.1.2 ! misho    88137:     function setPackage($package)
1.1       misho    88138:     {
1.1.1.2 ! misho    88139:         $this->_isValid = 0;
        !          88140:         if (!isset($this->_packageInfo['attribs'])) {
        !          88141:             $this->_packageInfo = array_merge(array('attribs' => array(
        !          88142:                                  'version' => '2.0',
        !          88143:                                  'xmlns' => 'http://pear.php.net/dtd/package-2.0',
        !          88144:                                  'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
        !          88145:                                  'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
        !          88146:                                  'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
        !          88147:     http://pear.php.net/dtd/tasks-1.0.xsd
        !          88148:     http://pear.php.net/dtd/package-2.0
        !          88149:     http://pear.php.net/dtd/package-2.0.xsd',
        !          88150:                              )), $this->_packageInfo);
        !          88151:         }
        !          88152:         if (!isset($this->_packageInfo['name'])) {
        !          88153:             return $this->_packageInfo = array_merge(array('name' => $package),
        !          88154:                 $this->_packageInfo);
        !          88155:         }
        !          88156:         $this->_packageInfo['name'] = $package;
1.1       misho    88157:     }
                   88158: 
1.1.1.2 ! misho    88159:     /**
        !          88160:      * set this as a package.xml version 2.1
        !          88161:      * @access private
        !          88162:      */
        !          88163:     function _setPackageVersion2_1()
1.1       misho    88164:     {
1.1.1.2 ! misho    88165:         $info = array(
        !          88166:                                  'version' => '2.1',
        !          88167:                                  'xmlns' => 'http://pear.php.net/dtd/package-2.1',
        !          88168:                                  'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
        !          88169:                                  'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
        !          88170:                                  'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
        !          88171:     http://pear.php.net/dtd/tasks-1.0.xsd
        !          88172:     http://pear.php.net/dtd/package-2.1
        !          88173:     http://pear.php.net/dtd/package-2.1.xsd',
        !          88174:                              );
        !          88175:         if (!isset($this->_packageInfo['attribs'])) {
        !          88176:             $this->_packageInfo = array_merge(array('attribs' => $info), $this->_packageInfo);
        !          88177:         } else {
        !          88178:             $this->_packageInfo['attribs'] = $info;
        !          88179:         }
1.1       misho    88180:     }
                   88181: 
1.1.1.2 ! misho    88182:     function setUri($uri)
1.1       misho    88183:     {
1.1.1.2 ! misho    88184:         unset($this->_packageInfo['channel']);
        !          88185:         $this->_isValid = 0;
        !          88186:         if (!isset($this->_packageInfo['uri'])) {
        !          88187:             // ensure that the uri tag is set up in the right location
        !          88188:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
        !          88189:                 array('extends', 'summary', 'description', 'lead',
        !          88190:                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
        !          88191:                 'stability', 'license', 'notes', 'contents', 'compatible',
        !          88192:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
        !          88193:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
        !          88194:                 'extbinrelease', 'bundle', 'changelog'), $uri, 'uri');
1.1       misho    88195:         }
1.1.1.2 ! misho    88196:         $this->_packageInfo['uri'] = $uri;
1.1       misho    88197:     }
                   88198: 
1.1.1.2 ! misho    88199:     function setChannel($channel)
1.1       misho    88200:     {
1.1.1.2 ! misho    88201:         unset($this->_packageInfo['uri']);
        !          88202:         $this->_isValid = 0;
        !          88203:         if (!isset($this->_packageInfo['channel'])) {
        !          88204:             // ensure that the channel tag is set up in the right location
        !          88205:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
        !          88206:                 array('extends', 'summary', 'description', 'lead',
        !          88207:                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
        !          88208:                 'stability', 'license', 'notes', 'contents', 'compatible',
        !          88209:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
        !          88210:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
        !          88211:                 'extbinrelease', 'bundle', 'changelog'), $channel, 'channel');
        !          88212:         }
        !          88213:         $this->_packageInfo['channel'] = $channel;
1.1       misho    88214:     }
                   88215: 
1.1.1.2 ! misho    88216:     function setExtends($extends)
1.1       misho    88217:     {
1.1.1.2 ! misho    88218:         $this->_isValid = 0;
        !          88219:         if (!isset($this->_packageInfo['extends'])) {
        !          88220:             // ensure that the extends tag is set up in the right location
        !          88221:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
        !          88222:                 array('summary', 'description', 'lead',
        !          88223:                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
        !          88224:                 'stability', 'license', 'notes', 'contents', 'compatible',
        !          88225:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
        !          88226:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
        !          88227:                 'extbinrelease', 'bundle', 'changelog'), $extends, 'extends');
        !          88228:         }
        !          88229:         $this->_packageInfo['extends'] = $extends;
1.1       misho    88230:     }
                   88231: 
1.1.1.2 ! misho    88232:     function setSummary($summary)
1.1       misho    88233:     {
1.1.1.2 ! misho    88234:         $this->_isValid = 0;
        !          88235:         if (!isset($this->_packageInfo['summary'])) {
        !          88236:             // ensure that the summary tag is set up in the right location
        !          88237:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
        !          88238:                 array('description', 'lead',
        !          88239:                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
        !          88240:                 'stability', 'license', 'notes', 'contents', 'compatible',
        !          88241:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
        !          88242:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
        !          88243:                 'extbinrelease', 'bundle', 'changelog'), $summary, 'summary');
        !          88244:         }
        !          88245:         $this->_packageInfo['summary'] = $summary;
1.1       misho    88246:     }
                   88247: 
1.1.1.2 ! misho    88248:     function setDescription($desc)
1.1       misho    88249:     {
1.1.1.2 ! misho    88250:         $this->_isValid = 0;
        !          88251:         if (!isset($this->_packageInfo['description'])) {
        !          88252:             // ensure that the description tag is set up in the right location
        !          88253:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
        !          88254:                 array('lead',
        !          88255:                 'developer', 'contributor', 'helper', 'date', 'time', 'version',
        !          88256:                 'stability', 'license', 'notes', 'contents', 'compatible',
        !          88257:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
        !          88258:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
        !          88259:                 'extbinrelease', 'bundle', 'changelog'), $desc, 'description');
        !          88260:         }
        !          88261:         $this->_packageInfo['description'] = $desc;
1.1       misho    88262:     }
                   88263: 
1.1.1.2 ! misho    88264:     /**
        !          88265:      * Adds a new maintainer - no checking of duplicates is performed, use
        !          88266:      * updatemaintainer for that purpose.
        !          88267:      */
        !          88268:     function addMaintainer($role, $handle, $name, $email, $active = 'yes')
1.1       misho    88269:     {
1.1.1.2 ! misho    88270:         if (!in_array($role, array('lead', 'developer', 'contributor', 'helper'))) {
1.1       misho    88271:             return false;
                   88272:         }
1.1.1.2 ! misho    88273:         if (isset($this->_packageInfo[$role])) {
        !          88274:             if (!isset($this->_packageInfo[$role][0])) {
        !          88275:                 $this->_packageInfo[$role] = array($this->_packageInfo[$role]);
        !          88276:             }
        !          88277:             $this->_packageInfo[$role][] =
        !          88278:                 array(
        !          88279:                     'name' => $name,
        !          88280:                     'user' => $handle,
        !          88281:                     'email' => $email,
        !          88282:                     'active' => $active,
        !          88283:                 );
        !          88284:         } else {
        !          88285:             $testarr = array('lead',
        !          88286:                     'developer', 'contributor', 'helper', 'date', 'time', 'version',
        !          88287:                     'stability', 'license', 'notes', 'contents', 'compatible',
        !          88288:                     'dependencies', 'providesextension', 'usesrole', 'usestask',
        !          88289:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
        !          88290:                     'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog');
        !          88291:             foreach (array('lead', 'developer', 'contributor', 'helper') as $testrole) {
        !          88292:                 array_shift($testarr);
        !          88293:                 if ($role == $testrole) {
        !          88294:                     break;
        !          88295:                 }
        !          88296:             }
        !          88297:             if (!isset($this->_packageInfo[$role])) {
        !          88298:                 // ensure that the extends tag is set up in the right location
        !          88299:                 $this->_packageInfo = $this->_insertBefore($this->_packageInfo, $testarr,
        !          88300:                     array(), $role);
        !          88301:             }
        !          88302:             $this->_packageInfo[$role] =
        !          88303:                 array(
        !          88304:                     'name' => $name,
        !          88305:                     'user' => $handle,
        !          88306:                     'email' => $email,
        !          88307:                     'active' => $active,
        !          88308:                 );
1.1       misho    88309:         }
1.1.1.2 ! misho    88310:         $this->_isValid = 0;
1.1       misho    88311:     }
                   88312: 
1.1.1.2 ! misho    88313:     function updateMaintainer($newrole, $handle, $name, $email, $active = 'yes')
1.1       misho    88314:     {
1.1.1.2 ! misho    88315:         $found = false;
        !          88316:         foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
        !          88317:             if (!isset($this->_packageInfo[$role])) {
        !          88318:                 continue;
        !          88319:             }
        !          88320:             $info = $this->_packageInfo[$role];
        !          88321:             if (!isset($info[0])) {
        !          88322:                 if ($info['user'] == $handle) {
        !          88323:                     $found = true;
        !          88324:                     break;
        !          88325:                 }
        !          88326:             }
        !          88327:             foreach ($info as $i => $maintainer) {
        !          88328:                 if ($maintainer['user'] == $handle) {
        !          88329:                     $found = $i;
        !          88330:                     break 2;
        !          88331:                 }
        !          88332:             }
1.1       misho    88333:         }
1.1.1.2 ! misho    88334:         if ($found === false) {
        !          88335:             return $this->addMaintainer($newrole, $handle, $name, $email, $active);
        !          88336:         }
        !          88337:         if ($found !== false) {
        !          88338:             if ($found === true) {
        !          88339:                 unset($this->_packageInfo[$role]);
        !          88340:             } else {
        !          88341:                 unset($this->_packageInfo[$role][$found]);
        !          88342:                 $this->_packageInfo[$role] = array_values($this->_packageInfo[$role]);
        !          88343:             }
        !          88344:         }
        !          88345:         $this->addMaintainer($newrole, $handle, $name, $email, $active);
        !          88346:         $this->_isValid = 0;
1.1       misho    88347:     }
                   88348: 
1.1.1.2 ! misho    88349:     function deleteMaintainer($handle)
1.1       misho    88350:     {
1.1.1.2 ! misho    88351:         $found = false;
        !          88352:         foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
        !          88353:             if (!isset($this->_packageInfo[$role])) {
        !          88354:                 continue;
        !          88355:             }
        !          88356:             if (!isset($this->_packageInfo[$role][0])) {
        !          88357:                 $this->_packageInfo[$role] = array($this->_packageInfo[$role]);
        !          88358:             }
        !          88359:             foreach ($this->_packageInfo[$role] as $i => $maintainer) {
        !          88360:                 if ($maintainer['user'] == $handle) {
        !          88361:                     $found = $i;
        !          88362:                     break;
        !          88363:                 }
        !          88364:             }
        !          88365:             if ($found !== false) {
        !          88366:                 unset($this->_packageInfo[$role][$found]);
        !          88367:                 if (!count($this->_packageInfo[$role]) && $role == 'lead') {
        !          88368:                     $this->_isValid = 0;
        !          88369:                 }
        !          88370:                 if (!count($this->_packageInfo[$role])) {
        !          88371:                     unset($this->_packageInfo[$role]);
        !          88372:                     return true;
        !          88373:                 }
        !          88374:                 $this->_packageInfo[$role] =
        !          88375:                     array_values($this->_packageInfo[$role]);
        !          88376:                 if (count($this->_packageInfo[$role]) == 1) {
        !          88377:                     $this->_packageInfo[$role] = $this->_packageInfo[$role][0];
        !          88378:                 }
        !          88379:                 return true;
        !          88380:             }
        !          88381:             if (count($this->_packageInfo[$role]) == 1) {
        !          88382:                 $this->_packageInfo[$role] = $this->_packageInfo[$role][0];
        !          88383:             }
        !          88384:         }
1.1       misho    88385:         return false;
                   88386:     }
                   88387: 
1.1.1.2 ! misho    88388:     function setReleaseVersion($version)
1.1       misho    88389:     {
1.1.1.2 ! misho    88390:         if (isset($this->_packageInfo['version']) &&
        !          88391:               isset($this->_packageInfo['version']['release'])) {
        !          88392:             unset($this->_packageInfo['version']['release']);
        !          88393:         }
        !          88394:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array(
        !          88395:             'version' => array('stability', 'license', 'notes', 'contents', 'compatible',
        !          88396:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
        !          88397:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
        !          88398:                 'extbinrelease', 'bundle', 'changelog'),
        !          88399:             'release' => array('api')));
        !          88400:         $this->_isValid = 0;
1.1       misho    88401:     }
                   88402: 
1.1.1.2 ! misho    88403:     function setAPIVersion($version)
1.1       misho    88404:     {
1.1.1.2 ! misho    88405:         if (isset($this->_packageInfo['version']) &&
        !          88406:               isset($this->_packageInfo['version']['api'])) {
        !          88407:             unset($this->_packageInfo['version']['api']);
1.1       misho    88408:         }
1.1.1.2 ! misho    88409:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array(
        !          88410:             'version' => array('stability', 'license', 'notes', 'contents', 'compatible',
        !          88411:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
        !          88412:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
        !          88413:                 'extbinrelease', 'bundle', 'changelog'),
        !          88414:             'api' => array()));
        !          88415:         $this->_isValid = 0;
1.1       misho    88416:     }
                   88417: 
                   88418:     /**
1.1.1.2 ! misho    88419:      * snapshot|devel|alpha|beta|stable
1.1       misho    88420:      */
1.1.1.2 ! misho    88421:     function setReleaseStability($state)
1.1       misho    88422:     {
1.1.1.2 ! misho    88423:         if (isset($this->_packageInfo['stability']) &&
        !          88424:               isset($this->_packageInfo['stability']['release'])) {
        !          88425:             unset($this->_packageInfo['stability']['release']);
1.1       misho    88426:         }
1.1.1.2 ! misho    88427:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array(
        !          88428:             'stability' => array('license', 'notes', 'contents', 'compatible',
        !          88429:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
        !          88430:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
        !          88431:                 'extbinrelease', 'bundle', 'changelog'),
        !          88432:             'release' => array('api')));
        !          88433:         $this->_isValid = 0;
1.1       misho    88434:     }
                   88435: 
1.1.1.2 ! misho    88436:     /**
        !          88437:      * @param devel|alpha|beta|stable
        !          88438:      */
        !          88439:     function setAPIStability($state)
1.1       misho    88440:     {
1.1.1.2 ! misho    88441:         if (isset($this->_packageInfo['stability']) &&
        !          88442:               isset($this->_packageInfo['stability']['api'])) {
        !          88443:             unset($this->_packageInfo['stability']['api']);
        !          88444:         }
        !          88445:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array(
        !          88446:             'stability' => array('license', 'notes', 'contents', 'compatible',
        !          88447:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
        !          88448:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
        !          88449:                 'extbinrelease', 'bundle', 'changelog'),
        !          88450:             'api' => array()));
        !          88451:         $this->_isValid = 0;
1.1       misho    88452:     }
                   88453: 
1.1.1.2 ! misho    88454:     function setLicense($license, $uri = false, $filesource = false)
1.1       misho    88455:     {
1.1.1.2 ! misho    88456:         if (!isset($this->_packageInfo['license'])) {
        !          88457:             // ensure that the license tag is set up in the right location
        !          88458:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
        !          88459:                 array('notes', 'contents', 'compatible',
        !          88460:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
        !          88461:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
        !          88462:                 'extbinrelease', 'bundle', 'changelog'), 0, 'license');
        !          88463:         }
        !          88464:         if ($uri || $filesource) {
        !          88465:             $attribs = array();
        !          88466:             if ($uri) {
        !          88467:                 $attribs['uri'] = $uri;
        !          88468:             }
        !          88469:             $uri = true; // for test below
        !          88470:             if ($filesource) {
        !          88471:                 $attribs['filesource'] = $filesource;
        !          88472:             }
        !          88473:         }
        !          88474:         $license = $uri ? array('attribs' => $attribs, '_content' => $license) : $license;
        !          88475:         $this->_packageInfo['license'] = $license;
        !          88476:         $this->_isValid = 0;
1.1       misho    88477:     }
                   88478: 
1.1.1.2 ! misho    88479:     function setNotes($notes)
1.1       misho    88480:     {
1.1.1.2 ! misho    88481:         $this->_isValid = 0;
        !          88482:         if (!isset($this->_packageInfo['notes'])) {
        !          88483:             // ensure that the notes tag is set up in the right location
        !          88484:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
        !          88485:                 array('contents', 'compatible',
        !          88486:                 'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
        !          88487:                 'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
        !          88488:                 'extbinrelease', 'bundle', 'changelog'), $notes, 'notes');
1.1       misho    88489:         }
1.1.1.2 ! misho    88490:         $this->_packageInfo['notes'] = $notes;
1.1       misho    88491:     }
                   88492: 
                   88493:     /**
1.1.1.2 ! misho    88494:      * This is only used at install-time, after all serialization
        !          88495:      * is over.
        !          88496:      * @param string file name
        !          88497:      * @param string installed path
1.1       misho    88498:      */
1.1.1.2 ! misho    88499:     function setInstalledAs($file, $path)
1.1       misho    88500:     {
1.1.1.2 ! misho    88501:         if ($path) {
        !          88502:             return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
        !          88503:         }
        !          88504:         unset($this->_packageInfo['filelist'][$file]['installed_as']);
1.1       misho    88505:     }
                   88506: 
1.1.1.2 ! misho    88507:     /**
        !          88508:      * This is only used at install-time, after all serialization
        !          88509:      * is over.
        !          88510:      */
        !          88511:     function installedFile($file, $atts)
1.1       misho    88512:     {
1.1.1.2 ! misho    88513:         if (isset($this->_packageInfo['filelist'][$file])) {
        !          88514:             $this->_packageInfo['filelist'][$file] =
        !          88515:                 array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']);
        !          88516:         } else {
        !          88517:             $this->_packageInfo['filelist'][$file] = $atts['attribs'];
1.1       misho    88518:         }
                   88519:     }
                   88520: 
1.1.1.2 ! misho    88521:     /**
        !          88522:      * Reset the listing of package contents
        !          88523:      * @param string base installation dir for the whole package, if any
        !          88524:      */
        !          88525:     function clearContents($baseinstall = false)
1.1       misho    88526:     {
1.1.1.2 ! misho    88527:         $this->_filesValid = false;
        !          88528:         $this->_isValid = 0;
        !          88529:         if (!isset($this->_packageInfo['contents'])) {
        !          88530:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
        !          88531:                 array('compatible',
        !          88532:                     'dependencies', 'providesextension', 'usesrole', 'usestask',
        !          88533:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
        !          88534:                     'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
        !          88535:                     'bundle', 'changelog'), array(), 'contents');
        !          88536:         }
        !          88537:         if ($this->getPackageType() != 'bundle') {
        !          88538:             $this->_packageInfo['contents'] =
        !          88539:                 array('dir' => array('attribs' => array('name' => '/')));
        !          88540:             if ($baseinstall) {
        !          88541:                 $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'] = $baseinstall;
        !          88542:             }
        !          88543:         } else {
        !          88544:             $this->_packageInfo['contents'] = array('bundledpackage' => array());
        !          88545:         }
1.1       misho    88546:     }
                   88547: 
1.1.1.2 ! misho    88548:     /**
        !          88549:      * @param string relative path of the bundled package.
        !          88550:      */
        !          88551:     function addBundledPackage($path)
1.1       misho    88552:     {
1.1.1.2 ! misho    88553:         if ($this->getPackageType() != 'bundle') {
        !          88554:             return false;
        !          88555:         }
        !          88556:         $this->_filesValid = false;
        !          88557:         $this->_isValid = 0;
        !          88558:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $path, array(
        !          88559:                 'contents' => array('compatible', 'dependencies', 'providesextension',
        !          88560:                 'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease',
        !          88561:                 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
        !          88562:                 'bundle', 'changelog'),
        !          88563:                 'bundledpackage' => array()));
1.1       misho    88564:     }
                   88565: 
1.1.1.2 ! misho    88566:     /**
        !          88567:      * @param string file name
        !          88568:      * @param PEAR_Task_Common a read/write task
        !          88569:      */
        !          88570:     function addTaskToFile($filename, $task)
1.1       misho    88571:     {
1.1.1.2 ! misho    88572:         if (!method_exists($task, 'getXml')) {
        !          88573:             return false;
        !          88574:         }
        !          88575:         if (!method_exists($task, 'getName')) {
        !          88576:             return false;
        !          88577:         }
        !          88578:         if (!method_exists($task, 'validate')) {
        !          88579:             return false;
        !          88580:         }
        !          88581:         if (!$task->validate()) {
        !          88582:             return false;
        !          88583:         }
        !          88584:         if (!isset($this->_packageInfo['contents']['dir']['file'])) {
        !          88585:             return false;
        !          88586:         }
        !          88587:         $this->getTasksNs(); // discover the tasks namespace if not done already
        !          88588:         $files = $this->_packageInfo['contents']['dir']['file'];
        !          88589:         if (!isset($files[0])) {
        !          88590:             $files = array($files);
        !          88591:             $ind = false;
        !          88592:         } else {
        !          88593:             $ind = true;
        !          88594:         }
        !          88595:         foreach ($files as $i => $file) {
        !          88596:             if (isset($file['attribs'])) {
        !          88597:                 if ($file['attribs']['name'] == $filename) {
        !          88598:                     if ($ind) {
        !          88599:                         $t = isset($this->_packageInfo['contents']['dir']['file'][$i]
        !          88600:                               ['attribs'][$this->_tasksNs .
        !          88601:                               ':' . $task->getName()]) ?
        !          88602:                               $this->_packageInfo['contents']['dir']['file'][$i]
        !          88603:                               ['attribs'][$this->_tasksNs .
        !          88604:                               ':' . $task->getName()] : false;
        !          88605:                         if ($t && !isset($t[0])) {
        !          88606:                             $this->_packageInfo['contents']['dir']['file'][$i]
        !          88607:                                 [$this->_tasksNs . ':' . $task->getName()] = array($t);
        !          88608:                         }
        !          88609:                         $this->_packageInfo['contents']['dir']['file'][$i][$this->_tasksNs .
        !          88610:                             ':' . $task->getName()][] = $task->getXml();
        !          88611:                     } else {
        !          88612:                         $t = isset($this->_packageInfo['contents']['dir']['file']
        !          88613:                               ['attribs'][$this->_tasksNs .
        !          88614:                               ':' . $task->getName()]) ? $this->_packageInfo['contents']['dir']['file']
        !          88615:                               ['attribs'][$this->_tasksNs .
        !          88616:                               ':' . $task->getName()] : false;
        !          88617:                         if ($t && !isset($t[0])) {
        !          88618:                             $this->_packageInfo['contents']['dir']['file']
        !          88619:                                 [$this->_tasksNs . ':' . $task->getName()] = array($t);
        !          88620:                         }
        !          88621:                         $this->_packageInfo['contents']['dir']['file'][$this->_tasksNs .
        !          88622:                             ':' . $task->getName()][] = $task->getXml();
        !          88623:                     }
        !          88624:                     return true;
        !          88625:                 }
        !          88626:             }
1.1       misho    88627:         }
                   88628:         return false;
                   88629:     }
                   88630: 
                   88631:     /**
1.1.1.2 ! misho    88632:      * @param string path to the file
        !          88633:      * @param string filename
        !          88634:      * @param array extra attributes
1.1       misho    88635:      */
1.1.1.2 ! misho    88636:     function addFile($dir, $file, $attrs)
1.1       misho    88637:     {
1.1.1.2 ! misho    88638:         if ($this->getPackageType() == 'bundle') {
        !          88639:             return false;
1.1       misho    88640:         }
1.1.1.2 ! misho    88641:         $this->_filesValid = false;
        !          88642:         $this->_isValid = 0;
        !          88643:         $dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir);
        !          88644:         if ($dir == '/' || $dir == '') {
        !          88645:             $dir = '';
        !          88646:         } else {
        !          88647:             $dir .= '/';
1.1       misho    88648:         }
1.1.1.2 ! misho    88649:         $attrs['name'] = $dir . $file;
        !          88650:         if (!isset($this->_packageInfo['contents'])) {
        !          88651:             // ensure that the contents tag is set up
        !          88652:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
        !          88653:                 array('compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask',
        !          88654:                 'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
        !          88655:                 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
        !          88656:                 'bundle', 'changelog'), array(), 'contents');
1.1       misho    88657:         }
1.1.1.2 ! misho    88658:         if (isset($this->_packageInfo['contents']['dir']['file'])) {
        !          88659:             if (!isset($this->_packageInfo['contents']['dir']['file'][0])) {
        !          88660:                 $this->_packageInfo['contents']['dir']['file'] =
        !          88661:                     array($this->_packageInfo['contents']['dir']['file']);
1.1       misho    88662:             }
1.1.1.2 ! misho    88663:             $this->_packageInfo['contents']['dir']['file'][]['attribs'] = $attrs;
        !          88664:         } else {
        !          88665:             $this->_packageInfo['contents']['dir']['file']['attribs'] = $attrs;
1.1       misho    88666:         }
                   88667:     }
                   88668: 
1.1.1.2 ! misho    88669:     /**
        !          88670:      * @param string Dependent package name
        !          88671:      * @param string Dependent package's channel name
        !          88672:      * @param string minimum version of specified package that this release is guaranteed to be
        !          88673:      *               compatible with
        !          88674:      * @param string maximum version of specified package that this release is guaranteed to be
        !          88675:      *               compatible with
        !          88676:      * @param string versions of specified package that this release is not compatible with
        !          88677:      */
        !          88678:     function addCompatiblePackage($name, $channel, $min, $max, $exclude = false)
1.1       misho    88679:     {
1.1.1.2 ! misho    88680:         $this->_isValid = 0;
        !          88681:         $set = array(
        !          88682:             'name' => $name,
        !          88683:             'channel' => $channel,
        !          88684:             'min' => $min,
        !          88685:             'max' => $max,
        !          88686:         );
        !          88687:         if ($exclude) {
        !          88688:             $set['exclude'] = $exclude;
1.1       misho    88689:         }
1.1.1.2 ! misho    88690:         $this->_isValid = 0;
        !          88691:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
        !          88692:                 'compatible' => array('dependencies', 'providesextension', 'usesrole', 'usestask',
        !          88693:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
        !          88694:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
        !          88695:             ));
1.1       misho    88696:     }
                   88697: 
1.1.1.2 ! misho    88698:     /**
        !          88699:      * Removes the <usesrole> tag entirely
        !          88700:      */
        !          88701:     function resetUsesrole()
1.1       misho    88702:     {
1.1.1.2 ! misho    88703:         if (isset($this->_packageInfo['usesrole'])) {
        !          88704:             unset($this->_packageInfo['usesrole']);
1.1       misho    88705:         }
                   88706:     }
                   88707: 
1.1.1.2 ! misho    88708:     /**
        !          88709:      * @param string
        !          88710:      * @param string package name or uri
        !          88711:      * @param string channel name if non-uri
        !          88712:      */
        !          88713:     function addUsesrole($role, $packageOrUri, $channel = false) {
        !          88714:         $set = array('role' => $role);
        !          88715:         if ($channel) {
        !          88716:             $set['package'] = $packageOrUri;
        !          88717:             $set['channel'] = $channel;
        !          88718:         } else {
        !          88719:             $set['uri'] = $packageOrUri;
1.1       misho    88720:         }
1.1.1.2 ! misho    88721:         $this->_isValid = 0;
        !          88722:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
        !          88723:                 'usesrole' => array('usestask', 'srcpackage', 'srcuri',
        !          88724:                     'phprelease', 'extsrcrelease', 'extbinrelease',
        !          88725:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
        !          88726:             ));
1.1       misho    88727:     }
                   88728: 
1.1.1.2 ! misho    88729:     /**
        !          88730:      * Removes the <usestask> tag entirely
        !          88731:      */
        !          88732:     function resetUsestask()
1.1       misho    88733:     {
1.1.1.2 ! misho    88734:         if (isset($this->_packageInfo['usestask'])) {
        !          88735:             unset($this->_packageInfo['usestask']);
1.1       misho    88736:         }
                   88737:     }
                   88738: 
                   88739: 
1.1.1.2 ! misho    88740:     /**
        !          88741:      * @param string
        !          88742:      * @param string package name or uri
        !          88743:      * @param string channel name if non-uri
        !          88744:      */
        !          88745:     function addUsestask($task, $packageOrUri, $channel = false) {
        !          88746:         $set = array('task' => $task);
        !          88747:         if ($channel) {
        !          88748:             $set['package'] = $packageOrUri;
        !          88749:             $set['channel'] = $channel;
        !          88750:         } else {
        !          88751:             $set['uri'] = $packageOrUri;
1.1       misho    88752:         }
1.1.1.2 ! misho    88753:         $this->_isValid = 0;
        !          88754:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
        !          88755:                 'usestask' => array('srcpackage', 'srcuri',
        !          88756:                     'phprelease', 'extsrcrelease', 'extbinrelease',
        !          88757:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
        !          88758:             ));
1.1       misho    88759:     }
                   88760: 
1.1.1.2 ! misho    88761:     /**
        !          88762:      * Remove all compatible tags
        !          88763:      */
        !          88764:     function clearCompatible()
1.1       misho    88765:     {
1.1.1.2 ! misho    88766:         unset($this->_packageInfo['compatible']);
1.1       misho    88767:     }
                   88768: 
                   88769:     /**
                   88770:      * Reset dependencies prior to adding new ones
                   88771:      */
                   88772:     function clearDeps()
                   88773:     {
1.1.1.2 ! misho    88774:         if (!isset($this->_packageInfo['dependencies'])) {
        !          88775:             $this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(),
        !          88776:                 array(
        !          88777:                     'dependencies' => array('providesextension', 'usesrole', 'usestask',
        !          88778:                         'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
        !          88779:                         'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')));
        !          88780:         }
        !          88781:         $this->_packageInfo['dependencies'] = array();
1.1       misho    88782:     }
                   88783: 
1.1.1.2 ! misho    88784:     /**
        !          88785:      * @param string minimum PHP version allowed
        !          88786:      * @param string maximum PHP version allowed
        !          88787:      * @param array $exclude incompatible PHP versions
        !          88788:      */
        !          88789:     function setPhpDep($min, $max = false, $exclude = false)
1.1       misho    88790:     {
1.1.1.2 ! misho    88791:         $this->_isValid = 0;
1.1       misho    88792:         $dep =
1.1.1.2 ! misho    88793:             array(
        !          88794:                 'min' => $min,
        !          88795:             );
        !          88796:         if ($max) {
        !          88797:             $dep['max'] = $max;
1.1       misho    88798:         }
1.1.1.2 ! misho    88799:         if ($exclude) {
        !          88800:             if (count($exclude) == 1) {
        !          88801:                 $exclude = $exclude[0];
        !          88802:             }
        !          88803:             $dep['exclude'] = $exclude;
        !          88804:         }
        !          88805:         if (isset($this->_packageInfo['dependencies']['required']['php'])) {
        !          88806:             $this->_stack->push(__FUNCTION__, 'warning', array('dep' =>
        !          88807:             $this->_packageInfo['dependencies']['required']['php']),
        !          88808:                 'warning: PHP dependency already exists, overwriting');
        !          88809:             unset($this->_packageInfo['dependencies']['required']['php']);
        !          88810:         }
        !          88811:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
        !          88812:             array(
        !          88813:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
        !          88814:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
        !          88815:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
        !          88816:                 'required' => array('optional', 'group'),
        !          88817:                 'php' => array('pearinstaller', 'package', 'subpackage', 'extension', 'os', 'arch')
        !          88818:             ));
        !          88819:         return true;
1.1       misho    88820:     }
                   88821: 
                   88822:     /**
1.1.1.2 ! misho    88823:      * @param string minimum allowed PEAR installer version
        !          88824:      * @param string maximum allowed PEAR installer version
        !          88825:      * @param string recommended PEAR installer version
        !          88826:      * @param array incompatible version of the PEAR installer
1.1       misho    88827:      */
1.1.1.2 ! misho    88828:     function setPearinstallerDep($min, $max = false, $recommended = false, $exclude = false)
1.1       misho    88829:     {
1.1.1.2 ! misho    88830:         $this->_isValid = 0;
        !          88831:         $dep =
        !          88832:             array(
        !          88833:                 'min' => $min,
        !          88834:             );
        !          88835:         if ($max) {
        !          88836:             $dep['max'] = $max;
1.1       misho    88837:         }
1.1.1.2 ! misho    88838:         if ($recommended) {
        !          88839:             $dep['recommended'] = $recommended;
1.1       misho    88840:         }
1.1.1.2 ! misho    88841:         if ($exclude) {
        !          88842:             if (count($exclude) == 1) {
        !          88843:                 $exclude = $exclude[0];
1.1       misho    88844:             }
1.1.1.2 ! misho    88845:             $dep['exclude'] = $exclude;
1.1       misho    88846:         }
1.1.1.2 ! misho    88847:         if (isset($this->_packageInfo['dependencies']['required']['pearinstaller'])) {
        !          88848:             $this->_stack->push(__FUNCTION__, 'warning', array('dep' =>
        !          88849:             $this->_packageInfo['dependencies']['required']['pearinstaller']),
        !          88850:                 'warning: PEAR Installer dependency already exists, overwriting');
        !          88851:             unset($this->_packageInfo['dependencies']['required']['pearinstaller']);
1.1       misho    88852:         }
1.1.1.2 ! misho    88853:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
        !          88854:             array(
        !          88855:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
        !          88856:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
        !          88857:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
        !          88858:                 'required' => array('optional', 'group'),
        !          88859:                 'pearinstaller' => array('package', 'subpackage', 'extension', 'os', 'arch')
        !          88860:             ));
1.1       misho    88861:     }
                   88862: 
1.1.1.2 ! misho    88863:     /**
        !          88864:      * Mark a package as conflicting with this package
        !          88865:      * @param string package name
        !          88866:      * @param string package channel
        !          88867:      * @param string extension this package provides, if any
        !          88868:      * @param string|false minimum version required
        !          88869:      * @param string|false maximum version allowed
        !          88870:      * @param array|false versions to exclude from installation
        !          88871:      */
        !          88872:     function addConflictingPackageDepWithChannel($name, $channel,
        !          88873:                 $providesextension = false, $min = false, $max = false, $exclude = false)
1.1       misho    88874:     {
1.1.1.2 ! misho    88875:         $this->_isValid = 0;
        !          88876:         $dep = $this->_constructDep($name, $channel, false, $min, $max, false,
        !          88877:             $exclude, $providesextension, false, true);
        !          88878:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
        !          88879:             array(
        !          88880:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
        !          88881:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
        !          88882:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
        !          88883:                 'required' => array('optional', 'group'),
        !          88884:                 'package' => array('subpackage', 'extension', 'os', 'arch')
        !          88885:             ));
1.1       misho    88886:     }
                   88887: 
1.1.1.2 ! misho    88888:     /**
        !          88889:      * Mark a package as conflicting with this package
        !          88890:      * @param string package name
        !          88891:      * @param string package channel
        !          88892:      * @param string extension this package provides, if any
        !          88893:      */
        !          88894:     function addConflictingPackageDepWithUri($name, $uri, $providesextension = false)
1.1       misho    88895:     {
1.1.1.2 ! misho    88896:         $this->_isValid = 0;
        !          88897:         $dep =
        !          88898:             array(
        !          88899:                 'name' => $name,
        !          88900:                 'uri' => $uri,
        !          88901:                 'conflicts' => '',
        !          88902:             );
        !          88903:         if ($providesextension) {
        !          88904:             $dep['providesextension'] = $providesextension;
1.1       misho    88905:         }
1.1.1.2 ! misho    88906:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
        !          88907:             array(
        !          88908:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
        !          88909:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
        !          88910:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
        !          88911:                 'required' => array('optional', 'group'),
        !          88912:                 'package' => array('subpackage', 'extension', 'os', 'arch')
        !          88913:             ));
1.1       misho    88914:     }
                   88915: 
1.1.1.2 ! misho    88916:     function addDependencyGroup($name, $hint)
1.1       misho    88917:     {
1.1.1.2 ! misho    88918:         $this->_isValid = 0;
        !          88919:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo,
        !          88920:             array('attribs' => array('name' => $name, 'hint' => $hint)),
        !          88921:             array(
        !          88922:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
        !          88923:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
        !          88924:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
        !          88925:                 'group' => array(),
        !          88926:             ));
1.1       misho    88927:     }
                   88928: 
1.1.1.2 ! misho    88929:     /**
        !          88930:      * @param string package name
        !          88931:      * @param string|false channel name, false if this is a uri
        !          88932:      * @param string|false uri name, false if this is a channel
        !          88933:      * @param string|false minimum version required
        !          88934:      * @param string|false maximum version allowed
        !          88935:      * @param string|false recommended installation version
        !          88936:      * @param array|false versions to exclude from installation
        !          88937:      * @param string extension this package provides, if any
        !          88938:      * @param bool if true, tells the installer to ignore the default optional dependency group
        !          88939:      *             when installing this package
        !          88940:      * @param bool if true, tells the installer to negate this dependency (conflicts)
        !          88941:      * @return array
        !          88942:      * @access private
        !          88943:      */
        !          88944:     function _constructDep($name, $channel, $uri, $min, $max, $recommended, $exclude,
        !          88945:                            $providesextension = false, $nodefault = false,
        !          88946:                            $conflicts = false)
1.1       misho    88947:     {
1.1.1.2 ! misho    88948:         $dep =
        !          88949:             array(
        !          88950:                 'name' => $name,
        !          88951:             );
        !          88952:         if ($channel) {
        !          88953:             $dep['channel'] = $channel;
        !          88954:         } elseif ($uri) {
        !          88955:             $dep['uri'] = $uri;
1.1       misho    88956:         }
1.1.1.2 ! misho    88957:         if ($min) {
        !          88958:             $dep['min'] = $min;
1.1       misho    88959:         }
1.1.1.2 ! misho    88960:         if ($max) {
        !          88961:             $dep['max'] = $max;
        !          88962:         }
        !          88963:         if ($recommended) {
        !          88964:             $dep['recommended'] = $recommended;
        !          88965:         }
        !          88966:         if ($exclude) {
        !          88967:             if (is_array($exclude) && count($exclude) == 1) {
        !          88968:                 $exclude = $exclude[0];
        !          88969:             }
        !          88970:             $dep['exclude'] = $exclude;
1.1       misho    88971:         }
1.1.1.2 ! misho    88972:         if ($conflicts) {
        !          88973:             $dep['conflicts'] = '';
1.1       misho    88974:         }
1.1.1.2 ! misho    88975:         if ($nodefault) {
        !          88976:             $dep['nodefault'] = '';
        !          88977:         }
        !          88978:         if ($providesextension) {
        !          88979:             $dep['providesextension'] = $providesextension;
1.1       misho    88980:         }
1.1.1.2 ! misho    88981:         return $dep;
1.1       misho    88982:     }
                   88983: 
1.1.1.2 ! misho    88984:     /**
        !          88985:      * @param package|subpackage
        !          88986:      * @param string group name
        !          88987:      * @param string package name
        !          88988:      * @param string package channel
        !          88989:      * @param string minimum version
        !          88990:      * @param string maximum version
        !          88991:      * @param string recommended version
        !          88992:      * @param array|false optional excluded versions
        !          88993:      * @param string extension this package provides, if any
        !          88994:      * @param bool if true, tells the installer to ignore the default optional dependency group
        !          88995:      *             when installing this package
        !          88996:      * @return bool false if the dependency group has not been initialized with
        !          88997:      *              {@link addDependencyGroup()}, or a subpackage is added with
        !          88998:      *              a providesextension
        !          88999:      */
        !          89000:     function addGroupPackageDepWithChannel($type, $groupname, $name, $channel, $min = false,
        !          89001:                                       $max = false, $recommended = false, $exclude = false,
        !          89002:                                       $providesextension = false, $nodefault = false)
1.1       misho    89003:     {
1.1.1.2 ! misho    89004:         if ($type == 'subpackage' && $providesextension) {
        !          89005:             return false; // subpackages must be php packages
1.1       misho    89006:         }
1.1.1.2 ! misho    89007:         $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
        !          89008:             $providesextension, $nodefault);
        !          89009:         return $this->_addGroupDependency($type, $dep, $groupname);
1.1       misho    89010:     }
                   89011: 
1.1.1.2 ! misho    89012:     /**
        !          89013:      * @param package|subpackage
        !          89014:      * @param string group name
        !          89015:      * @param string package name
        !          89016:      * @param string package uri
        !          89017:      * @param string extension this package provides, if any
        !          89018:      * @param bool if true, tells the installer to ignore the default optional dependency group
        !          89019:      *             when installing this package
        !          89020:      * @return bool false if the dependency group has not been initialized with
        !          89021:      *              {@link addDependencyGroup()}
        !          89022:      */
        !          89023:     function addGroupPackageDepWithURI($type, $groupname, $name, $uri, $providesextension = false,
        !          89024:                                        $nodefault = false)
1.1       misho    89025:     {
1.1.1.2 ! misho    89026:         if ($type == 'subpackage' && $providesextension) {
        !          89027:             return false; // subpackages must be php packages
        !          89028:         }
        !          89029:         $dep = $this->_constructDep($name, false, $uri, false, false, false, false,
        !          89030:             $providesextension, $nodefault);
        !          89031:         return $this->_addGroupDependency($type, $dep, $groupname);
1.1       misho    89032:     }
                   89033: 
                   89034:     /**
1.1.1.2 ! misho    89035:      * @param string group name (must be pre-existing)
        !          89036:      * @param string extension name
        !          89037:      * @param string minimum version allowed
        !          89038:      * @param string maximum version allowed
        !          89039:      * @param string recommended version
        !          89040:      * @param array incompatible versions
1.1       misho    89041:      */
1.1.1.2 ! misho    89042:     function addGroupExtensionDep($groupname, $name, $min = false, $max = false,
        !          89043:                                          $recommended = false, $exclude = false)
1.1       misho    89044:     {
1.1.1.2 ! misho    89045:         $this->_isValid = 0;
        !          89046:         $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
        !          89047:         return $this->_addGroupDependency('extension', $dep, $groupname);
1.1       misho    89048:     }
                   89049: 
                   89050:     /**
1.1.1.2 ! misho    89051:      * @param package|subpackage|extension
        !          89052:      * @param array dependency contents
        !          89053:      * @param string name of the dependency group to add this to
        !          89054:      * @return boolean
1.1       misho    89055:      * @access private
                   89056:      */
1.1.1.2 ! misho    89057:     function _addGroupDependency($type, $dep, $groupname)
1.1       misho    89058:     {
1.1.1.2 ! misho    89059:         $arr = array('subpackage', 'extension');
        !          89060:         if ($type != 'package') {
        !          89061:             array_shift($arr);
        !          89062:         }
        !          89063:         if ($type == 'extension') {
        !          89064:             array_shift($arr);
        !          89065:         }
        !          89066:         if (!isset($this->_packageInfo['dependencies']['group'])) {
        !          89067:             return false;
        !          89068:         } else {
        !          89069:             if (!isset($this->_packageInfo['dependencies']['group'][0])) {
        !          89070:                 if ($this->_packageInfo['dependencies']['group']['attribs']['name'] == $groupname) {
        !          89071:                     $this->_packageInfo['dependencies']['group'] = $this->_mergeTag(
        !          89072:                         $this->_packageInfo['dependencies']['group'], $dep,
        !          89073:                         array(
        !          89074:                             $type => $arr
        !          89075:                         ));
        !          89076:                     $this->_isValid = 0;
        !          89077:                     return true;
        !          89078:                 } else {
        !          89079:                     return false;
        !          89080:                 }
        !          89081:             } else {
        !          89082:                 foreach ($this->_packageInfo['dependencies']['group'] as $i => $group) {
        !          89083:                     if ($group['attribs']['name'] == $groupname) {
        !          89084:                     $this->_packageInfo['dependencies']['group'][$i] = $this->_mergeTag(
        !          89085:                         $this->_packageInfo['dependencies']['group'][$i], $dep,
        !          89086:                         array(
        !          89087:                             $type => $arr
        !          89088:                         ));
        !          89089:                         $this->_isValid = 0;
        !          89090:                         return true;
        !          89091:                     }
        !          89092:                 }
        !          89093:                 return false;
        !          89094:             }
        !          89095:         }
1.1       misho    89096:     }
                   89097: 
                   89098:     /**
1.1.1.2 ! misho    89099:      * @param optional|required
        !          89100:      * @param string package name
        !          89101:      * @param string package channel
        !          89102:      * @param string minimum version
        !          89103:      * @param string maximum version
        !          89104:      * @param string recommended version
        !          89105:      * @param string extension this package provides, if any
        !          89106:      * @param bool if true, tells the installer to ignore the default optional dependency group
        !          89107:      *             when installing this package
        !          89108:      * @param array|false optional excluded versions
1.1       misho    89109:      */
1.1.1.2 ! misho    89110:     function addPackageDepWithChannel($type, $name, $channel, $min = false, $max = false,
        !          89111:                                       $recommended = false, $exclude = false,
        !          89112:                                       $providesextension = false, $nodefault = false)
1.1       misho    89113:     {
1.1.1.2 ! misho    89114:         if (!in_array($type, array('optional', 'required'), true)) {
        !          89115:             $type = 'required';
        !          89116:         }
        !          89117:         $this->_isValid = 0;
        !          89118:         $arr = array('optional', 'group');
        !          89119:         if ($type != 'required') {
        !          89120:             array_shift($arr);
        !          89121:         }
        !          89122:         $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
        !          89123:             $providesextension, $nodefault);
        !          89124:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
        !          89125:             array(
        !          89126:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
        !          89127:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
        !          89128:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
        !          89129:                 $type => $arr,
        !          89130:                 'package' => array('subpackage', 'extension', 'os', 'arch')
        !          89131:             ));
1.1       misho    89132:     }
                   89133: 
                   89134:     /**
1.1.1.2 ! misho    89135:      * @param optional|required
        !          89136:      * @param string name of the package
        !          89137:      * @param string uri of the package
        !          89138:      * @param string extension this package provides, if any
        !          89139:      * @param bool if true, tells the installer to ignore the default optional dependency group
        !          89140:      *             when installing this package
1.1       misho    89141:      */
1.1.1.2 ! misho    89142:     function addPackageDepWithUri($type, $name, $uri, $providesextension = false,
        !          89143:                                   $nodefault = false)
1.1       misho    89144:     {
1.1.1.2 ! misho    89145:         $this->_isValid = 0;
        !          89146:         $arr = array('optional', 'group');
        !          89147:         if ($type != 'required') {
        !          89148:             array_shift($arr);
        !          89149:         }
        !          89150:         $dep = $this->_constructDep($name, false, $uri, false, false, false, false,
        !          89151:             $providesextension, $nodefault);
        !          89152:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
        !          89153:             array(
        !          89154:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
        !          89155:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
        !          89156:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
        !          89157:                 $type => $arr,
        !          89158:                 'package' => array('subpackage', 'extension', 'os', 'arch')
        !          89159:             ));
1.1       misho    89160:     }
                   89161: 
                   89162:     /**
1.1.1.2 ! misho    89163:      * @param optional|required optional, required
        !          89164:      * @param string package name
        !          89165:      * @param string package channel
        !          89166:      * @param string minimum version
        !          89167:      * @param string maximum version
        !          89168:      * @param string recommended version
        !          89169:      * @param array incompatible versions
        !          89170:      * @param bool if true, tells the installer to ignore the default optional dependency group
        !          89171:      *             when installing this package
1.1       misho    89172:      */
1.1.1.2 ! misho    89173:     function addSubpackageDepWithChannel($type, $name, $channel, $min = false, $max = false,
        !          89174:                                          $recommended = false, $exclude = false,
        !          89175:                                          $nodefault = false)
1.1       misho    89176:     {
1.1.1.2 ! misho    89177:         $this->_isValid = 0;
        !          89178:         $arr = array('optional', 'group');
        !          89179:         if ($type != 'required') {
        !          89180:             array_shift($arr);
1.1       misho    89181:         }
1.1.1.2 ! misho    89182:         $dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
        !          89183:             $nodefault);
        !          89184:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
        !          89185:             array(
        !          89186:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
        !          89187:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
        !          89188:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
        !          89189:                 $type => $arr,
        !          89190:                 'subpackage' => array('extension', 'os', 'arch')
        !          89191:             ));
        !          89192:     }
1.1       misho    89193: 
1.1.1.2 ! misho    89194:     /**
        !          89195:      * @param optional|required optional, required
        !          89196:      * @param string package name
        !          89197:      * @param string package uri for download
        !          89198:      * @param bool if true, tells the installer to ignore the default optional dependency group
        !          89199:      *             when installing this package
        !          89200:      */
        !          89201:     function addSubpackageDepWithUri($type, $name, $uri, $nodefault = false)
        !          89202:     {
        !          89203:         $this->_isValid = 0;
        !          89204:         $arr = array('optional', 'group');
        !          89205:         if ($type != 'required') {
        !          89206:             array_shift($arr);
1.1       misho    89207:         }
1.1.1.2 ! misho    89208:         $dep = $this->_constructDep($name, false, $uri, false, false, false, false, $nodefault);
        !          89209:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
        !          89210:             array(
        !          89211:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
        !          89212:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
        !          89213:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
        !          89214:                 $type => $arr,
        !          89215:                 'subpackage' => array('extension', 'os', 'arch')
        !          89216:             ));
        !          89217:     }
        !          89218: 
        !          89219:     /**
        !          89220:      * @param optional|required optional, required
        !          89221:      * @param string extension name
        !          89222:      * @param string minimum version
        !          89223:      * @param string maximum version
        !          89224:      * @param string recommended version
        !          89225:      * @param array incompatible versions
        !          89226:      */
        !          89227:     function addExtensionDep($type, $name, $min = false, $max = false, $recommended = false,
        !          89228:                              $exclude = false)
        !          89229:     {
        !          89230:         $this->_isValid = 0;
        !          89231:         $arr = array('optional', 'group');
        !          89232:         if ($type != 'required') {
        !          89233:             array_shift($arr);
1.1       misho    89234:         }
1.1.1.2 ! misho    89235:         $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
        !          89236:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
        !          89237:             array(
        !          89238:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
        !          89239:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
        !          89240:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
        !          89241:                 $type => $arr,
        !          89242:                 'extension' => array('os', 'arch')
        !          89243:             ));
        !          89244:     }
        !          89245: 
        !          89246:     /**
        !          89247:      * @param string Operating system name
        !          89248:      * @param boolean true if this package cannot be installed on this OS
        !          89249:      */
        !          89250:     function addOsDep($name, $conflicts = false)
        !          89251:     {
        !          89252:         $this->_isValid = 0;
        !          89253:         $dep = array('name' => $name);
        !          89254:         if ($conflicts) {
        !          89255:             $dep['conflicts'] = '';
1.1       misho    89256:         }
1.1.1.2 ! misho    89257:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
        !          89258:             array(
        !          89259:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
        !          89260:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
        !          89261:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
        !          89262:                 'required' => array('optional', 'group'),
        !          89263:                 'os' => array('arch')
        !          89264:             ));
        !          89265:     }
        !          89266: 
        !          89267:     /**
        !          89268:      * @param string Architecture matching pattern
        !          89269:      * @param boolean true if this package cannot be installed on this architecture
        !          89270:      */
        !          89271:     function addArchDep($pattern, $conflicts = false)
        !          89272:     {
        !          89273:         $this->_isValid = 0;
        !          89274:         $dep = array('pattern' => $pattern);
        !          89275:         if ($conflicts) {
        !          89276:             $dep['conflicts'] = '';
1.1       misho    89277:         }
1.1.1.2 ! misho    89278:         $this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
        !          89279:             array(
        !          89280:                 'dependencies' => array('providesextension', 'usesrole', 'usestask',
        !          89281:                     'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
        !          89282:                     'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
        !          89283:                 'required' => array('optional', 'group'),
        !          89284:                 'arch' => array()
        !          89285:             ));
1.1       misho    89286:     }
                   89287: 
1.1.1.2 ! misho    89288:     /**
        !          89289:      * Set the kind of package, and erase all release tags
        !          89290:      *
        !          89291:      * - a php package is a PEAR-style package
        !          89292:      * - an extbin package is a PECL-style extension binary
        !          89293:      * - an extsrc package is a PECL-style source for a binary
        !          89294:      * - an zendextbin package is a PECL-style zend extension binary
        !          89295:      * - an zendextsrc package is a PECL-style source for a zend extension binary
        !          89296:      * - a bundle package is a collection of other pre-packaged packages
        !          89297:      * @param php|extbin|extsrc|zendextsrc|zendextbin|bundle
        !          89298:      * @return bool success
        !          89299:      */
        !          89300:     function setPackageType($type)
1.1       misho    89301:     {
1.1.1.2 ! misho    89302:         $this->_isValid = 0;
        !          89303:         if (!in_array($type, array('php', 'extbin', 'extsrc', 'zendextsrc',
        !          89304:                                    'zendextbin', 'bundle'))) {
1.1       misho    89305:             return false;
                   89306:         }
1.1.1.2 ! misho    89307: 
        !          89308:         if (in_array($type, array('zendextsrc', 'zendextbin'))) {
        !          89309:             $this->_setPackageVersion2_1();
1.1       misho    89310:         }
1.1.1.2 ! misho    89311: 
        !          89312:         if ($type != 'bundle') {
        !          89313:             $type .= 'release';
1.1       misho    89314:         }
1.1.1.2 ! misho    89315: 
        !          89316:         foreach (array('phprelease', 'extbinrelease', 'extsrcrelease',
        !          89317:                        'zendextsrcrelease', 'zendextbinrelease', 'bundle') as $test) {
        !          89318:             unset($this->_packageInfo[$test]);
1.1       misho    89319:         }
1.1.1.2 ! misho    89320: 
        !          89321:         if (!isset($this->_packageInfo[$type])) {
        !          89322:             // ensure that the release tag is set up
        !          89323:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('changelog'),
        !          89324:                 array(), $type);
        !          89325:         }
        !          89326: 
        !          89327:         $this->_packageInfo[$type] = array();
        !          89328:         return true;
1.1       misho    89329:     }
                   89330: 
                   89331:     /**
1.1.1.2 ! misho    89332:      * @return bool true if package type is set up
1.1       misho    89333:      */
1.1.1.2 ! misho    89334:     function addRelease()
1.1       misho    89335:     {
1.1.1.2 ! misho    89336:         if ($type = $this->getPackageType()) {
        !          89337:             if ($type != 'bundle') {
        !          89338:                 $type .= 'release';
        !          89339:             }
        !          89340:             $this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(),
        !          89341:                 array($type => array('changelog')));
        !          89342:             return true;
1.1       misho    89343:         }
1.1.1.2 ! misho    89344:         return false;
1.1       misho    89345:     }
                   89346: 
                   89347:     /**
1.1.1.2 ! misho    89348:      * Get the current release tag in order to add to it
        !          89349:      * @param bool returns only releases that have installcondition if true
        !          89350:      * @return array|null
1.1       misho    89351:      */
1.1.1.2 ! misho    89352:     function &_getCurrentRelease($strict = true)
1.1       misho    89353:     {
1.1.1.2 ! misho    89354:         if ($p = $this->getPackageType()) {
        !          89355:             if ($strict) {
        !          89356:                 if ($p == 'extsrc' || $p == 'zendextsrc') {
        !          89357:                     $a = null;
        !          89358:                     return $a;
        !          89359:                 }
1.1       misho    89360:             }
1.1.1.2 ! misho    89361:             if ($p != 'bundle') {
        !          89362:                 $p .= 'release';
1.1       misho    89363:             }
1.1.1.2 ! misho    89364:             if (isset($this->_packageInfo[$p][0])) {
        !          89365:                 return $this->_packageInfo[$p][count($this->_packageInfo[$p]) - 1];
        !          89366:             } else {
        !          89367:                 return $this->_packageInfo[$p];
1.1       misho    89368:             }
1.1.1.2 ! misho    89369:         } else {
        !          89370:             $a = null;
        !          89371:             return $a;
1.1       misho    89372:         }
                   89373:     }
                   89374: 
                   89375:     /**
1.1.1.2 ! misho    89376:      * Add a file to the current release that should be installed under a different name
        !          89377:      * @param string <contents> path to file
        !          89378:      * @param string name the file should be installed as
        !          89379:      */
        !          89380:     function addInstallAs($path, $as)
        !          89381:     {
        !          89382:         $r = &$this->_getCurrentRelease();
        !          89383:         if ($r === null) {
        !          89384:             return false;
        !          89385:         }
        !          89386:         $this->_isValid = 0;
        !          89387:         $r = $this->_mergeTag($r, array('attribs' => array('name' => $path, 'as' => $as)),
        !          89388:             array(
        !          89389:                 'filelist' => array(),
        !          89390:                 'install' => array('ignore')
        !          89391:             ));
        !          89392:     }
        !          89393: 
        !          89394:     /**
        !          89395:      * Add a file to the current release that should be ignored
        !          89396:      * @param string <contents> path to file
        !          89397:      * @return bool success of operation
        !          89398:      */
        !          89399:     function addIgnore($path)
        !          89400:     {
        !          89401:         $r = &$this->_getCurrentRelease();
        !          89402:         if ($r === null) {
        !          89403:             return false;
        !          89404:         }
        !          89405:         $this->_isValid = 0;
        !          89406:         $r = $this->_mergeTag($r, array('attribs' => array('name' => $path)),
        !          89407:             array(
        !          89408:                 'filelist' => array(),
        !          89409:                 'ignore' => array()
        !          89410:             ));
        !          89411:     }
        !          89412: 
        !          89413:     /**
        !          89414:      * Add an extension binary package for this extension source code release
1.1       misho    89415:      *
1.1.1.2 ! misho    89416:      * Note that the package must be from the same channel as the extension source package
        !          89417:      * @param string
1.1       misho    89418:      */
1.1.1.2 ! misho    89419:     function addBinarypackage($package)
1.1       misho    89420:     {
1.1.1.2 ! misho    89421:         if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
1.1       misho    89422:             return false;
                   89423:         }
1.1.1.2 ! misho    89424:         $r = &$this->_getCurrentRelease(false);
        !          89425:         if ($r === null) {
        !          89426:             return false;
1.1       misho    89427:         }
1.1.1.2 ! misho    89428:         $this->_isValid = 0;
        !          89429:         $r = $this->_mergeTag($r, $package,
        !          89430:             array(
        !          89431:                 'binarypackage' => array('filelist'),
        !          89432:             ));
        !          89433:     }
        !          89434: 
        !          89435:     /**
        !          89436:      * Add a configureoption to an extension source package
        !          89437:      * @param string
        !          89438:      * @param string
        !          89439:      * @param string
        !          89440:      */
        !          89441:     function addConfigureOption($name, $prompt, $default = null)
        !          89442:     {
        !          89443:         if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
        !          89444:             return false;
1.1       misho    89445:         }
1.1.1.2 ! misho    89446: 
        !          89447:         $r = &$this->_getCurrentRelease(false);
        !          89448:         if ($r === null) {
        !          89449:             return false;
1.1       misho    89450:         }
1.1.1.2 ! misho    89451: 
        !          89452:         $opt = array('attribs' => array('name' => $name, 'prompt' => $prompt));
        !          89453:         if ($default !== null) {
        !          89454:             $opt['attribs']['default'] = $default;
        !          89455:         }
        !          89456: 
        !          89457:         $this->_isValid = 0;
        !          89458:         $r = $this->_mergeTag($r, $opt,
        !          89459:             array(
        !          89460:                 'configureoption' => array('binarypackage', 'filelist'),
        !          89461:             ));
        !          89462:     }
        !          89463: 
        !          89464:     /**
        !          89465:      * Set an installation condition based on php version for the current release set
        !          89466:      * @param string minimum version
        !          89467:      * @param string maximum version
        !          89468:      * @param false|array incompatible versions of PHP
        !          89469:      */
        !          89470:     function setPhpInstallCondition($min, $max, $exclude = false)
        !          89471:     {
        !          89472:         $r = &$this->_getCurrentRelease();
        !          89473:         if ($r === null) {
1.1       misho    89474:             return false;
                   89475:         }
1.1.1.2 ! misho    89476:         $this->_isValid = 0;
        !          89477:         if (isset($r['installconditions']['php'])) {
        !          89478:             unset($r['installconditions']['php']);
1.1       misho    89479:         }
1.1.1.2 ! misho    89480:         $dep = array('min' => $min, 'max' => $max);
        !          89481:         if ($exclude) {
        !          89482:             if (is_array($exclude) && count($exclude) == 1) {
        !          89483:                 $exclude = $exclude[0];
1.1       misho    89484:             }
1.1.1.2 ! misho    89485:             $dep['exclude'] = $exclude;
        !          89486:         }
        !          89487:         if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
        !          89488:             $r = $this->_mergeTag($r, $dep,
        !          89489:                 array(
        !          89490:                     'installconditions' => array('configureoption', 'binarypackage',
        !          89491:                         'filelist'),
        !          89492:                     'php' => array('extension', 'os', 'arch')
        !          89493:                 ));
        !          89494:         } else {
        !          89495:             $r = $this->_mergeTag($r, $dep,
        !          89496:                 array(
        !          89497:                     'installconditions' => array('filelist'),
        !          89498:                     'php' => array('extension', 'os', 'arch')
        !          89499:                 ));
        !          89500:         }
        !          89501:     }
        !          89502: 
        !          89503:     /**
        !          89504:      * @param optional|required optional, required
        !          89505:      * @param string extension name
        !          89506:      * @param string minimum version
        !          89507:      * @param string maximum version
        !          89508:      * @param string recommended version
        !          89509:      * @param array incompatible versions
        !          89510:      */
        !          89511:     function addExtensionInstallCondition($name, $min = false, $max = false, $recommended = false,
        !          89512:                                           $exclude = false)
        !          89513:     {
        !          89514:         $r = &$this->_getCurrentRelease();
        !          89515:         if ($r === null) {
        !          89516:             return false;
        !          89517:         }
        !          89518:         $this->_isValid = 0;
        !          89519:         $dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
        !          89520:         if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
        !          89521:             $r = $this->_mergeTag($r, $dep,
        !          89522:                 array(
        !          89523:                     'installconditions' => array('configureoption', 'binarypackage',
        !          89524:                         'filelist'),
        !          89525:                     'extension' => array('os', 'arch')
        !          89526:                 ));
        !          89527:         } else {
        !          89528:             $r = $this->_mergeTag($r, $dep,
        !          89529:                 array(
        !          89530:                     'installconditions' => array('filelist'),
        !          89531:                     'extension' => array('os', 'arch')
        !          89532:                 ));
1.1       misho    89533:         }
                   89534:     }
                   89535: 
                   89536:     /**
1.1.1.2 ! misho    89537:      * Set an installation condition based on operating system for the current release set
        !          89538:      * @param string OS name
        !          89539:      * @param bool whether this OS is incompatible with the current release
1.1       misho    89540:      */
1.1.1.2 ! misho    89541:     function setOsInstallCondition($name, $conflicts = false)
1.1       misho    89542:     {
1.1.1.2 ! misho    89543:         $r = &$this->_getCurrentRelease();
        !          89544:         if ($r === null) {
1.1       misho    89545:             return false;
                   89546:         }
1.1.1.2 ! misho    89547:         $this->_isValid = 0;
        !          89548:         if (isset($r['installconditions']['os'])) {
        !          89549:             unset($r['installconditions']['os']);
1.1       misho    89550:         }
1.1.1.2 ! misho    89551:         $dep = array('name' => $name);
        !          89552:         if ($conflicts) {
        !          89553:             $dep['conflicts'] = '';
        !          89554:         }
        !          89555:         if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
        !          89556:             $r = $this->_mergeTag($r, $dep,
        !          89557:                 array(
        !          89558:                     'installconditions' => array('configureoption', 'binarypackage',
        !          89559:                         'filelist'),
        !          89560:                     'os' => array('arch')
        !          89561:                 ));
        !          89562:         } else {
        !          89563:             $r = $this->_mergeTag($r, $dep,
        !          89564:                 array(
        !          89565:                     'installconditions' => array('filelist'),
        !          89566:                     'os' => array('arch')
        !          89567:                 ));
1.1       misho    89568:         }
1.1.1.2 ! misho    89569:     }
1.1       misho    89570: 
1.1.1.2 ! misho    89571:     /**
        !          89572:      * Set an installation condition based on architecture for the current release set
        !          89573:      * @param string architecture pattern
        !          89574:      * @param bool whether this arch is incompatible with the current release
        !          89575:      */
        !          89576:     function setArchInstallCondition($pattern, $conflicts = false)
        !          89577:     {
        !          89578:         $r = &$this->_getCurrentRelease();
        !          89579:         if ($r === null) {
        !          89580:             return false;
        !          89581:         }
        !          89582:         $this->_isValid = 0;
        !          89583:         if (isset($r['installconditions']['arch'])) {
        !          89584:             unset($r['installconditions']['arch']);
        !          89585:         }
        !          89586:         $dep = array('pattern' => $pattern);
        !          89587:         if ($conflicts) {
        !          89588:             $dep['conflicts'] = '';
        !          89589:         }
        !          89590:         if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
        !          89591:             $r = $this->_mergeTag($r, $dep,
        !          89592:                 array(
        !          89593:                     'installconditions' => array('configureoption', 'binarypackage',
        !          89594:                         'filelist'),
        !          89595:                     'arch' => array()
        !          89596:                 ));
        !          89597:         } else {
        !          89598:             $r = $this->_mergeTag($r, $dep,
        !          89599:                 array(
        !          89600:                     'installconditions' => array('filelist'),
        !          89601:                     'arch' => array()
        !          89602:                 ));
        !          89603:         }
        !          89604:     }
        !          89605: 
        !          89606:     /**
        !          89607:      * For extension binary releases, this is used to specify either the
        !          89608:      * static URI to a source package, or the package name and channel of the extsrc/zendextsrc
        !          89609:      * package it is based on.
        !          89610:      * @param string Package name, or full URI to source package (extsrc/zendextsrc type)
        !          89611:      */
        !          89612:     function setSourcePackage($packageOrUri)
        !          89613:     {
        !          89614:         $this->_isValid = 0;
        !          89615:         if (isset($this->_packageInfo['channel'])) {
        !          89616:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease',
        !          89617:                 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
        !          89618:                 'bundle', 'changelog'),
        !          89619:                 $packageOrUri, 'srcpackage');
        !          89620:         } else {
        !          89621:             $this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease',
        !          89622:                 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
        !          89623:                 'bundle', 'changelog'), $packageOrUri, 'srcuri');
        !          89624:         }
        !          89625:     }
        !          89626: 
        !          89627:     /**
        !          89628:      * Generate a valid change log entry from the current package.xml
        !          89629:      * @param string|false
        !          89630:      */
        !          89631:     function generateChangeLogEntry($notes = false)
        !          89632:     {
        !          89633:         return array(
        !          89634:             'version' =>
        !          89635:                 array(
        !          89636:                     'release' => $this->getVersion('release'),
        !          89637:                     'api' => $this->getVersion('api'),
        !          89638:                     ),
        !          89639:             'stability' =>
        !          89640:                 $this->getStability(),
        !          89641:             'date' => $this->getDate(),
        !          89642:             'license' => $this->getLicense(true),
        !          89643:             'notes' => $notes ? $notes : $this->getNotes()
        !          89644:             );
        !          89645:     }
        !          89646: 
        !          89647:     /**
        !          89648:      * @param string release version to set change log notes for
        !          89649:      * @param array output of {@link generateChangeLogEntry()}
        !          89650:      */
        !          89651:     function setChangelogEntry($releaseversion, $contents)
        !          89652:     {
        !          89653:         if (!isset($this->_packageInfo['changelog'])) {
        !          89654:             $this->_packageInfo['changelog']['release'] = $contents;
        !          89655:             return;
        !          89656:         }
        !          89657:         if (!isset($this->_packageInfo['changelog']['release'][0])) {
        !          89658:             if ($this->_packageInfo['changelog']['release']['version']['release'] == $releaseversion) {
        !          89659:                 $this->_packageInfo['changelog']['release'] = array(
        !          89660:                     $this->_packageInfo['changelog']['release']);
        !          89661:             } else {
        !          89662:                 $this->_packageInfo['changelog']['release'] = array(
        !          89663:                     $this->_packageInfo['changelog']['release']);
        !          89664:                 return $this->_packageInfo['changelog']['release'][] = $contents;
1.1       misho    89665:             }
1.1.1.2 ! misho    89666:         }
        !          89667:         foreach($this->_packageInfo['changelog']['release'] as $index => $changelog) {
        !          89668:             if (isset($changelog['version']) &&
        !          89669:                   strnatcasecmp($changelog['version']['release'], $releaseversion) == 0) {
        !          89670:                 $curlog = $index;
1.1       misho    89671:             }
1.1.1.2 ! misho    89672:         }
        !          89673:         if (isset($curlog)) {
        !          89674:             $this->_packageInfo['changelog']['release'][$curlog] = $contents;
        !          89675:         } else {
        !          89676:             $this->_packageInfo['changelog']['release'][] = $contents;
1.1       misho    89677:         }
                   89678:     }
                   89679: 
1.1.1.2 ! misho    89680:     /**
        !          89681:      * Remove the changelog entirely
        !          89682:      */
        !          89683:     function clearChangeLog()
        !          89684:     {
        !          89685:         unset($this->_packageInfo['changelog']);
        !          89686:     }
        !          89687: }<?php
1.1       misho    89688: /**
1.1.1.2 ! misho    89689:  * PEAR_PackageFile_v2, package.xml version 2.0, read/write version
1.1       misho    89690:  *
                   89691:  * PHP versions 4 and 5
                   89692:  *
                   89693:  * @category   pear
                   89694:  * @package    PEAR
                   89695:  * @author     Greg Beaver <cellog@php.net>
                   89696:  * @copyright  1997-2009 The Authors
                   89697:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    89698:  * @version    CVS: $Id: Validator.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    89699:  * @link       http://pear.php.net/package/PEAR
1.1.1.2 ! misho    89700:  * @since      File available since Release 1.4.0a8
1.1       misho    89701:  */
                   89702: /**
1.1.1.2 ! misho    89703:  * Private validation class used by PEAR_PackageFile_v2 - do not use directly, its
        !          89704:  * sole purpose is to split up the PEAR/PackageFile/v2.php file to make it smaller
1.1       misho    89705:  * @category   pear
                   89706:  * @package    PEAR
                   89707:  * @author     Greg Beaver <cellog@php.net>
                   89708:  * @copyright  1997-2009 The Authors
                   89709:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    89710:  * @version    Release: 1.9.4
1.1       misho    89711:  * @link       http://pear.php.net/package/PEAR
1.1.1.2 ! misho    89712:  * @since      Class available since Release 1.4.0a8
        !          89713:  * @access private
1.1       misho    89714:  */
1.1.1.2 ! misho    89715: class PEAR_PackageFile_v2_Validator
1.1       misho    89716: {
                   89717:     /**
                   89718:      * @var array
                   89719:      */
1.1.1.2 ! misho    89720:     var $_packageInfo;
1.1       misho    89721:     /**
1.1.1.2 ! misho    89722:      * @var PEAR_PackageFile_v2
1.1       misho    89723:      */
1.1.1.2 ! misho    89724:     var $_pf;
1.1       misho    89725:     /**
                   89726:      * @var PEAR_ErrorStack
                   89727:      */
                   89728:     var $_stack;
                   89729:     /**
1.1.1.2 ! misho    89730:      * @var int
1.1       misho    89731:      */
1.1.1.2 ! misho    89732:     var $_isValid = 0;
1.1       misho    89733:     /**
1.1.1.2 ! misho    89734:      * @var int
1.1       misho    89735:      */
1.1.1.2 ! misho    89736:     var $_filesValid = 0;
1.1       misho    89737:     /**
1.1.1.2 ! misho    89738:      * @var int
1.1       misho    89739:      */
1.1.1.2 ! misho    89740:     var $_curState = 0;
1.1       misho    89741:     /**
1.1.1.2 ! misho    89742:      * @param PEAR_PackageFile_v2
        !          89743:      * @param int
1.1       misho    89744:      */
1.1.1.2 ! misho    89745:     function validate(&$pf, $state = PEAR_VALIDATE_NORMAL)
1.1       misho    89746:     {
1.1.1.2 ! misho    89747:         $this->_pf = &$pf;
        !          89748:         $this->_curState = $state;
        !          89749:         $this->_packageInfo = $this->_pf->getArray();
        !          89750:         $this->_isValid = $this->_pf->_isValid;
        !          89751:         $this->_filesValid = $this->_pf->_filesValid;
        !          89752:         $this->_stack = &$pf->_stack;
        !          89753:         $this->_stack->getErrors(true);
        !          89754:         if (($this->_isValid & $state) == $state) {
        !          89755:             return true;
1.1       misho    89756:         }
1.1.1.2 ! misho    89757:         if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) {
        !          89758:             return false;
1.1       misho    89759:         }
1.1.1.2 ! misho    89760:         if (!isset($this->_packageInfo['attribs']['version']) ||
        !          89761:               ($this->_packageInfo['attribs']['version'] != '2.0' &&
        !          89762:                $this->_packageInfo['attribs']['version'] != '2.1')
        !          89763:         ) {
        !          89764:             $this->_noPackageVersion();
        !          89765:         }
        !          89766:         $structure =
        !          89767:         array(
        !          89768:             'name',
        !          89769:             'channel|uri',
        !          89770:             '*extends', // can't be multiple, but this works fine
        !          89771:             'summary',
        !          89772:             'description',
        !          89773:             '+lead', // these all need content checks
        !          89774:             '*developer',
        !          89775:             '*contributor',
        !          89776:             '*helper',
        !          89777:             'date',
        !          89778:             '*time',
        !          89779:             'version',
        !          89780:             'stability',
        !          89781:             'license->?uri->?filesource',
        !          89782:             'notes',
        !          89783:             'contents', //special validation needed
        !          89784:             '*compatible',
        !          89785:             'dependencies', //special validation needed
        !          89786:             '*usesrole',
        !          89787:             '*usestask', // reserve these for 1.4.0a1 to implement
        !          89788:                          // this will allow a package.xml to gracefully say it
        !          89789:                          // needs a certain package installed in order to implement a role or task
        !          89790:             '*providesextension',
        !          89791:             '*srcpackage|*srcuri',
        !          89792:             '+phprelease|+extsrcrelease|+extbinrelease|' .
        !          89793:                 '+zendextsrcrelease|+zendextbinrelease|bundle', //special validation needed
        !          89794:             '*changelog',
        !          89795:         );
        !          89796:         $test = $this->_packageInfo;
        !          89797:         if (isset($test['dependencies']) &&
        !          89798:               isset($test['dependencies']['required']) &&
        !          89799:               isset($test['dependencies']['required']['pearinstaller']) &&
        !          89800:               isset($test['dependencies']['required']['pearinstaller']['min']) &&
        !          89801:               version_compare('1.9.4',
        !          89802:                 $test['dependencies']['required']['pearinstaller']['min'], '<')
        !          89803:         ) {
        !          89804:             $this->_pearVersionTooLow($test['dependencies']['required']['pearinstaller']['min']);
        !          89805:             return false;
1.1       misho    89806:         }
1.1.1.2 ! misho    89807:         // ignore post-installation array fields
        !          89808:         if (array_key_exists('filelist', $test)) {
        !          89809:             unset($test['filelist']);
1.1       misho    89810:         }
1.1.1.2 ! misho    89811:         if (array_key_exists('_lastmodified', $test)) {
        !          89812:             unset($test['_lastmodified']);
1.1       misho    89813:         }
1.1.1.2 ! misho    89814:         if (array_key_exists('#binarypackage', $test)) {
        !          89815:             unset($test['#binarypackage']);
1.1       misho    89816:         }
1.1.1.2 ! misho    89817:         if (array_key_exists('old', $test)) {
        !          89818:             unset($test['old']);
1.1       misho    89819:         }
1.1.1.2 ! misho    89820:         if (array_key_exists('_lastversion', $test)) {
        !          89821:             unset($test['_lastversion']);
        !          89822:         }
        !          89823:         if (!$this->_stupidSchemaValidate($structure, $test, '<package>')) {
1.1       misho    89824:             return false;
                   89825:         }
1.1.1.2 ! misho    89826:         if (empty($this->_packageInfo['name'])) {
        !          89827:             $this->_tagCannotBeEmpty('name');
1.1       misho    89828:         }
1.1.1.2 ! misho    89829:         $test = isset($this->_packageInfo['uri']) ? 'uri' :'channel';
        !          89830:         if (empty($this->_packageInfo[$test])) {
        !          89831:             $this->_tagCannotBeEmpty($test);
1.1       misho    89832:         }
1.1.1.2 ! misho    89833:         if (is_array($this->_packageInfo['license']) &&
        !          89834:               (!isset($this->_packageInfo['license']['_content']) ||
        !          89835:               empty($this->_packageInfo['license']['_content']))) {
        !          89836:             $this->_tagCannotBeEmpty('license');
        !          89837:         } elseif (empty($this->_packageInfo['license'])) {
        !          89838:             $this->_tagCannotBeEmpty('license');
1.1       misho    89839:         }
1.1.1.2 ! misho    89840:         if (empty($this->_packageInfo['summary'])) {
        !          89841:             $this->_tagCannotBeEmpty('summary');
1.1       misho    89842:         }
1.1.1.2 ! misho    89843:         if (empty($this->_packageInfo['description'])) {
        !          89844:             $this->_tagCannotBeEmpty('description');
1.1       misho    89845:         }
1.1.1.2 ! misho    89846:         if (empty($this->_packageInfo['date'])) {
        !          89847:             $this->_tagCannotBeEmpty('date');
1.1       misho    89848:         }
1.1.1.2 ! misho    89849:         if (empty($this->_packageInfo['notes'])) {
        !          89850:             $this->_tagCannotBeEmpty('notes');
        !          89851:         }
        !          89852:         if (isset($this->_packageInfo['time']) && empty($this->_packageInfo['time'])) {
        !          89853:             $this->_tagCannotBeEmpty('time');
        !          89854:         }
        !          89855:         if (isset($this->_packageInfo['dependencies'])) {
        !          89856:             $this->_validateDependencies();
        !          89857:         }
        !          89858:         if (isset($this->_packageInfo['compatible'])) {
        !          89859:             $this->_validateCompatible();
        !          89860:         }
        !          89861:         if (!isset($this->_packageInfo['bundle'])) {
        !          89862:             if (empty($this->_packageInfo['contents'])) {
        !          89863:                 $this->_tagCannotBeEmpty('contents');
        !          89864:             }
        !          89865:             if (!isset($this->_packageInfo['contents']['dir'])) {
        !          89866:                 $this->_filelistMustContainDir('contents');
        !          89867:                 return false;
        !          89868:             }
        !          89869:             if (isset($this->_packageInfo['contents']['file'])) {
        !          89870:                 $this->_filelistCannotContainFile('contents');
        !          89871:                 return false;
        !          89872:             }
        !          89873:         }
        !          89874:         $this->_validateMaintainers();
        !          89875:         $this->_validateStabilityVersion();
        !          89876:         $fail = false;
        !          89877:         if (array_key_exists('usesrole', $this->_packageInfo)) {
        !          89878:             $roles = $this->_packageInfo['usesrole'];
        !          89879:             if (!is_array($roles) || !isset($roles[0])) {
        !          89880:                 $roles = array($roles);
        !          89881:             }
        !          89882:             foreach ($roles as $role) {
        !          89883:                 if (!isset($role['role'])) {
        !          89884:                     $this->_usesroletaskMustHaveRoleTask('usesrole', 'role');
        !          89885:                     $fail = true;
        !          89886:                 } else {
        !          89887:                     if (!isset($role['channel'])) {
        !          89888:                         if (!isset($role['uri'])) {
        !          89889:                             $this->_usesroletaskMustHaveChannelOrUri($role['role'], 'usesrole');
        !          89890:                             $fail = true;
        !          89891:                         }
        !          89892:                     } elseif (!isset($role['package'])) {
        !          89893:                         $this->_usesroletaskMustHavePackage($role['role'], 'usesrole');
        !          89894:                         $fail = true;
1.1       misho    89895:                     }
                   89896:                 }
                   89897:             }
                   89898:         }
1.1.1.2 ! misho    89899:         if (array_key_exists('usestask', $this->_packageInfo)) {
        !          89900:             $roles = $this->_packageInfo['usestask'];
        !          89901:             if (!is_array($roles) || !isset($roles[0])) {
        !          89902:                 $roles = array($roles);
        !          89903:             }
        !          89904:             foreach ($roles as $role) {
        !          89905:                 if (!isset($role['task'])) {
        !          89906:                     $this->_usesroletaskMustHaveRoleTask('usestask', 'task');
        !          89907:                     $fail = true;
        !          89908:                 } else {
        !          89909:                     if (!isset($role['channel'])) {
        !          89910:                         if (!isset($role['uri'])) {
        !          89911:                             $this->_usesroletaskMustHaveChannelOrUri($role['task'], 'usestask');
        !          89912:                             $fail = true;
        !          89913:                         }
        !          89914:                     } elseif (!isset($role['package'])) {
        !          89915:                         $this->_usesroletaskMustHavePackage($role['task'], 'usestask');
        !          89916:                         $fail = true;
        !          89917:                     }
        !          89918:                 }
1.1       misho    89919:             }
                   89920:         }
                   89921: 
1.1.1.2 ! misho    89922:         if ($fail) {
        !          89923:             return false;
        !          89924:         }
1.1       misho    89925: 
1.1.1.2 ! misho    89926:         $list = $this->_packageInfo['contents'];
        !          89927:         if (isset($list['dir']) && is_array($list['dir']) && isset($list['dir'][0])) {
        !          89928:             $this->_multipleToplevelDirNotAllowed();
        !          89929:             return $this->_isValid = 0;
        !          89930:         }
1.1       misho    89931: 
1.1.1.2 ! misho    89932:         $this->_validateFilelist();
        !          89933:         $this->_validateRelease();
        !          89934:         if (!$this->_stack->hasErrors()) {
        !          89935:             $chan = $this->_pf->_registry->getChannel($this->_pf->getChannel(), true);
        !          89936:             if (PEAR::isError($chan)) {
        !          89937:                 $this->_unknownChannel($this->_pf->getChannel());
        !          89938:             } else {
        !          89939:                 $valpack = $chan->getValidationPackage();
        !          89940:                 // for channel validator packages, always use the default PEAR validator.
        !          89941:                 // otherwise, they can't be installed or packaged
        !          89942:                 $validator = $chan->getValidationObject($this->_pf->getPackage());
        !          89943:                 if (!$validator) {
        !          89944:                     $this->_stack->push(__FUNCTION__, 'error',
        !          89945:                         array('channel' => $chan->getName(),
        !          89946:                               'package' => $this->_pf->getPackage(),
        !          89947:                               'name'    => $valpack['_content'],
        !          89948:                               'version' => $valpack['attribs']['version']),
        !          89949:                         'package "%channel%/%package%" cannot be properly validated without ' .
        !          89950:                         'validation package "%channel%/%name%-%version%"');
        !          89951:                     return $this->_isValid = 0;
        !          89952:                 }
        !          89953:                 $validator->setPackageFile($this->_pf);
        !          89954:                 $validator->validate($state);
        !          89955:                 $failures = $validator->getFailures();
        !          89956:                 foreach ($failures['errors'] as $error) {
        !          89957:                     $this->_stack->push(__FUNCTION__, 'error', $error,
        !          89958:                         'Channel validator error: field "%field%" - %reason%');
        !          89959:                 }
        !          89960:                 foreach ($failures['warnings'] as $warning) {
        !          89961:                     $this->_stack->push(__FUNCTION__, 'warning', $warning,
        !          89962:                         'Channel validator warning: field "%field%" - %reason%');
        !          89963:                 }
        !          89964:             }
        !          89965:         }
1.1       misho    89966: 
1.1.1.2 ! misho    89967:         $this->_pf->_isValid = $this->_isValid = !$this->_stack->hasErrors('error');
        !          89968:         if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$this->_filesValid) {
        !          89969:             if ($this->_pf->getPackageType() == 'bundle') {
        !          89970:                 if ($this->_analyzeBundledPackages()) {
        !          89971:                     $this->_filesValid = $this->_pf->_filesValid = true;
        !          89972:                 } else {
        !          89973:                     $this->_pf->_isValid = $this->_isValid = 0;
        !          89974:                 }
        !          89975:             } else {
        !          89976:                 if (!$this->_analyzePhpFiles()) {
        !          89977:                     $this->_pf->_isValid = $this->_isValid = 0;
        !          89978:                 } else {
        !          89979:                     $this->_filesValid = $this->_pf->_filesValid = true;
        !          89980:                 }
        !          89981:             }
        !          89982:         }
1.1       misho    89983: 
1.1.1.2 ! misho    89984:         if ($this->_isValid) {
        !          89985:             return $this->_pf->_isValid = $this->_isValid = $state;
        !          89986:         }
1.1       misho    89987: 
1.1.1.2 ! misho    89988:         return $this->_pf->_isValid = $this->_isValid = 0;
1.1       misho    89989:     }
                   89990: 
1.1.1.2 ! misho    89991:     function _stupidSchemaValidate($structure, $xml, $root)
1.1       misho    89992:     {
1.1.1.2 ! misho    89993:         if (!is_array($xml)) {
        !          89994:             $xml = array();
1.1       misho    89995:         }
1.1.1.2 ! misho    89996:         $keys = array_keys($xml);
        !          89997:         reset($keys);
        !          89998:         $key = current($keys);
        !          89999:         while ($key == 'attribs' || $key == '_contents') {
        !          90000:             $key = next($keys);
1.1       misho    90001:         }
1.1.1.2 ! misho    90002:         $unfoundtags = $optionaltags = array();
        !          90003:         $ret = true;
        !          90004:         $mismatch = false;
        !          90005:         foreach ($structure as $struc) {
        !          90006:             if ($key) {
        !          90007:                 $tag = $xml[$key];
        !          90008:             }
        !          90009:             $test = $this->_processStructure($struc);
        !          90010:             if (isset($test['choices'])) {
        !          90011:                 $loose = true;
        !          90012:                 foreach ($test['choices'] as $choice) {
        !          90013:                     if ($key == $choice['tag']) {
        !          90014:                         $key = next($keys);
        !          90015:                         while ($key == 'attribs' || $key == '_contents') {
        !          90016:                             $key = next($keys);
        !          90017:                         }
        !          90018:                         $unfoundtags = $optionaltags = array();
        !          90019:                         $mismatch = false;
        !          90020:                         if ($key && $key != $choice['tag'] && isset($choice['multiple'])) {
        !          90021:                             $unfoundtags[] = $choice['tag'];
        !          90022:                             $optionaltags[] = $choice['tag'];
        !          90023:                             if ($key) {
        !          90024:                                 $mismatch = true;
        !          90025:                             }
        !          90026:                         }
        !          90027:                         $ret &= $this->_processAttribs($choice, $tag, $root);
        !          90028:                         continue 2;
        !          90029:                     } else {
        !          90030:                         $unfoundtags[] = $choice['tag'];
        !          90031:                         $mismatch = true;
        !          90032:                     }
        !          90033:                     if (!isset($choice['multiple']) || $choice['multiple'] != '*') {
        !          90034:                         $loose = false;
        !          90035:                     } else {
        !          90036:                         $optionaltags[] = $choice['tag'];
        !          90037:                     }
        !          90038:                 }
        !          90039:                 if (!$loose) {
        !          90040:                     $this->_invalidTagOrder($unfoundtags, $key, $root);
        !          90041:                     return false;
        !          90042:                 }
        !          90043:             } else {
        !          90044:                 if ($key != $test['tag']) {
        !          90045:                     if (isset($test['multiple']) && $test['multiple'] != '*') {
        !          90046:                         $unfoundtags[] = $test['tag'];
        !          90047:                         $this->_invalidTagOrder($unfoundtags, $key, $root);
        !          90048:                         return false;
        !          90049:                     } else {
        !          90050:                         if ($key) {
        !          90051:                             $mismatch = true;
        !          90052:                         }
        !          90053:                         $unfoundtags[] = $test['tag'];
        !          90054:                         $optionaltags[] = $test['tag'];
        !          90055:                     }
        !          90056:                     if (!isset($test['multiple'])) {
        !          90057:                         $this->_invalidTagOrder($unfoundtags, $key, $root);
        !          90058:                         return false;
        !          90059:                     }
        !          90060:                     continue;
        !          90061:                 } else {
        !          90062:                     $unfoundtags = $optionaltags = array();
        !          90063:                     $mismatch = false;
        !          90064:                 }
        !          90065:                 $key = next($keys);
        !          90066:                 while ($key == 'attribs' || $key == '_contents') {
        !          90067:                     $key = next($keys);
        !          90068:                 }
        !          90069:                 if ($key && $key != $test['tag'] && isset($test['multiple'])) {
        !          90070:                     $unfoundtags[] = $test['tag'];
        !          90071:                     $optionaltags[] = $test['tag'];
        !          90072:                     $mismatch = true;
        !          90073:                 }
        !          90074:                 $ret &= $this->_processAttribs($test, $tag, $root);
        !          90075:                 continue;
        !          90076:             }
1.1       misho    90077:         }
1.1.1.2 ! misho    90078:         if (!$mismatch && count($optionaltags)) {
        !          90079:             // don't error out on any optional tags
        !          90080:             $unfoundtags = array_diff($unfoundtags, $optionaltags);
        !          90081:         }
        !          90082:         if (count($unfoundtags)) {
        !          90083:             $this->_invalidTagOrder($unfoundtags, $key, $root);
        !          90084:         } elseif ($key) {
        !          90085:             // unknown tags
        !          90086:             $this->_invalidTagOrder('*no tags allowed here*', $key, $root);
        !          90087:             while ($key = next($keys)) {
        !          90088:                 $this->_invalidTagOrder('*no tags allowed here*', $key, $root);
        !          90089:             }
        !          90090:         }
        !          90091:         return $ret;
1.1       misho    90092:     }
                   90093: 
1.1.1.2 ! misho    90094:     function _processAttribs($choice, $tag, $context)
1.1       misho    90095:     {
1.1.1.2 ! misho    90096:         if (isset($choice['attribs'])) {
        !          90097:             if (!is_array($tag)) {
        !          90098:                 $tag = array($tag);
        !          90099:             }
        !          90100:             $tags = $tag;
        !          90101:             if (!isset($tags[0])) {
        !          90102:                 $tags = array($tags);
        !          90103:             }
        !          90104:             $ret = true;
        !          90105:             foreach ($tags as $i => $tag) {
        !          90106:                 if (!is_array($tag) || !isset($tag['attribs'])) {
        !          90107:                     foreach ($choice['attribs'] as $attrib) {
        !          90108:                         if ($attrib{0} != '?') {
        !          90109:                             $ret &= $this->_tagHasNoAttribs($choice['tag'],
        !          90110:                                 $context);
        !          90111:                             continue 2;
        !          90112:                         }
        !          90113:                     }
        !          90114:                 }
        !          90115:                 foreach ($choice['attribs'] as $attrib) {
        !          90116:                     if ($attrib{0} != '?') {
        !          90117:                         if (!isset($tag['attribs'][$attrib])) {
        !          90118:                             $ret &= $this->_tagMissingAttribute($choice['tag'],
        !          90119:                                 $attrib, $context);
        !          90120:                         }
        !          90121:                     }
        !          90122:                 }
        !          90123:             }
        !          90124:             return $ret;
1.1       misho    90125:         }
1.1.1.2 ! misho    90126:         return true;
1.1       misho    90127:     }
                   90128: 
1.1.1.2 ! misho    90129:     function _processStructure($key)
1.1       misho    90130:     {
1.1.1.2 ! misho    90131:         $ret = array();
        !          90132:         if (count($pieces = explode('|', $key)) > 1) {
        !          90133:             $ret['choices'] = array();
        !          90134:             foreach ($pieces as $piece) {
        !          90135:                 $ret['choices'][] = $this->_processStructure($piece);
        !          90136:             }
        !          90137:             return $ret;
        !          90138:         }
        !          90139:         $multi = $key{0};
        !          90140:         if ($multi == '+' || $multi == '*') {
        !          90141:             $ret['multiple'] = $key{0};
        !          90142:             $key = substr($key, 1);
        !          90143:         }
        !          90144:         if (count($attrs = explode('->', $key)) > 1) {
        !          90145:             $ret['tag'] = array_shift($attrs);
        !          90146:             $ret['attribs'] = $attrs;
        !          90147:         } else {
        !          90148:             $ret['tag'] = $key;
        !          90149:         }
        !          90150:         return $ret;
1.1       misho    90151:     }
                   90152: 
1.1.1.2 ! misho    90153:     function _validateStabilityVersion()
1.1       misho    90154:     {
1.1.1.2 ! misho    90155:         $structure = array('release', 'api');
        !          90156:         $a = $this->_stupidSchemaValidate($structure, $this->_packageInfo['version'], '<version>');
        !          90157:         $a &= $this->_stupidSchemaValidate($structure, $this->_packageInfo['stability'], '<stability>');
        !          90158:         if ($a) {
        !          90159:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
        !          90160:                   $this->_packageInfo['version']['release'])) {
        !          90161:                 $this->_invalidVersion('release', $this->_packageInfo['version']['release']);
        !          90162:             }
        !          90163:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
        !          90164:                   $this->_packageInfo['version']['api'])) {
        !          90165:                 $this->_invalidVersion('api', $this->_packageInfo['version']['api']);
        !          90166:             }
        !          90167:             if (!in_array($this->_packageInfo['stability']['release'],
        !          90168:                   array('snapshot', 'devel', 'alpha', 'beta', 'stable'))) {
        !          90169:                 $this->_invalidState('release', $this->_packageInfo['stability']['release']);
        !          90170:             }
        !          90171:             if (!in_array($this->_packageInfo['stability']['api'],
        !          90172:                   array('devel', 'alpha', 'beta', 'stable'))) {
        !          90173:                 $this->_invalidState('api', $this->_packageInfo['stability']['api']);
        !          90174:             }
1.1       misho    90175:         }
                   90176:     }
                   90177: 
1.1.1.2 ! misho    90178:     function _validateMaintainers()
1.1       misho    90179:     {
1.1.1.2 ! misho    90180:         $structure =
        !          90181:             array(
        !          90182:                 'name',
        !          90183:                 'user',
        !          90184:                 'email',
        !          90185:                 'active',
        !          90186:             );
        !          90187:         foreach (array('lead', 'developer', 'contributor', 'helper') as $type) {
        !          90188:             if (!isset($this->_packageInfo[$type])) {
1.1       misho    90189:                 continue;
                   90190:             }
1.1.1.2 ! misho    90191:             if (isset($this->_packageInfo[$type][0])) {
        !          90192:                 foreach ($this->_packageInfo[$type] as $lead) {
        !          90193:                     $this->_stupidSchemaValidate($structure, $lead, '<' . $type . '>');
1.1       misho    90194:                 }
1.1.1.2 ! misho    90195:             } else {
        !          90196:                 $this->_stupidSchemaValidate($structure, $this->_packageInfo[$type],
        !          90197:                     '<' . $type . '>');
1.1       misho    90198:             }
                   90199:         }
                   90200:     }
                   90201: 
1.1.1.2 ! misho    90202:     function _validatePhpDep($dep, $installcondition = false)
1.1       misho    90203:     {
1.1.1.2 ! misho    90204:         $structure = array(
        !          90205:             'min',
        !          90206:             '*max',
        !          90207:             '*exclude',
        !          90208:         );
        !          90209:         $type = $installcondition ? '<installcondition><php>' : '<dependencies><required><php>';
        !          90210:         $this->_stupidSchemaValidate($structure, $dep, $type);
        !          90211:         if (isset($dep['min'])) {
        !          90212:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
        !          90213:                   $dep['min'])) {
        !          90214:                 $this->_invalidVersion($type . '<min>', $dep['min']);
        !          90215:             }
1.1       misho    90216:         }
1.1.1.2 ! misho    90217:         if (isset($dep['max'])) {
        !          90218:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
        !          90219:                   $dep['max'])) {
        !          90220:                 $this->_invalidVersion($type . '<max>', $dep['max']);
1.1       misho    90221:             }
                   90222:         }
1.1.1.2 ! misho    90223:         if (isset($dep['exclude'])) {
        !          90224:             if (!is_array($dep['exclude'])) {
        !          90225:                 $dep['exclude'] = array($dep['exclude']);
1.1       misho    90226:             }
1.1.1.2 ! misho    90227:             foreach ($dep['exclude'] as $exclude) {
        !          90228:                 if (!preg_match(
        !          90229:                      '/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
        !          90230:                      $exclude)) {
        !          90231:                     $this->_invalidVersion($type . '<exclude>', $exclude);
1.1       misho    90232:                 }
                   90233:             }
                   90234:         }
                   90235:     }
                   90236: 
1.1.1.2 ! misho    90237:     function _validatePearinstallerDep($dep)
1.1       misho    90238:     {
1.1.1.2 ! misho    90239:         $structure = array(
        !          90240:             'min',
        !          90241:             '*max',
        !          90242:             '*recommended',
        !          90243:             '*exclude',
        !          90244:         );
        !          90245:         $this->_stupidSchemaValidate($structure, $dep, '<dependencies><required><pearinstaller>');
        !          90246:         if (isset($dep['min'])) {
        !          90247:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
        !          90248:                   $dep['min'])) {
        !          90249:                 $this->_invalidVersion('<dependencies><required><pearinstaller><min>',
        !          90250:                     $dep['min']);
1.1       misho    90251:             }
                   90252:         }
1.1.1.2 ! misho    90253:         if (isset($dep['max'])) {
        !          90254:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
        !          90255:                   $dep['max'])) {
        !          90256:                 $this->_invalidVersion('<dependencies><required><pearinstaller><max>',
        !          90257:                     $dep['max']);
        !          90258:             }
1.1       misho    90259:         }
1.1.1.2 ! misho    90260:         if (isset($dep['recommended'])) {
        !          90261:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
        !          90262:                   $dep['recommended'])) {
        !          90263:                 $this->_invalidVersion('<dependencies><required><pearinstaller><recommended>',
        !          90264:                     $dep['recommended']);
1.1       misho    90265:             }
1.1.1.2 ! misho    90266:         }
        !          90267:         if (isset($dep['exclude'])) {
        !          90268:             if (!is_array($dep['exclude'])) {
        !          90269:                 $dep['exclude'] = array($dep['exclude']);
        !          90270:             }
        !          90271:             foreach ($dep['exclude'] as $exclude) {
        !          90272:                 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
        !          90273:                       $exclude)) {
        !          90274:                     $this->_invalidVersion('<dependencies><required><pearinstaller><exclude>',
        !          90275:                         $exclude);
1.1       misho    90276:                 }
                   90277:             }
                   90278:         }
                   90279:     }
                   90280: 
1.1.1.2 ! misho    90281:     function _validatePackageDep($dep, $group, $type = '<package>')
1.1       misho    90282:     {
1.1.1.2 ! misho    90283:         if (isset($dep['uri'])) {
        !          90284:             if (isset($dep['conflicts'])) {
        !          90285:                 $structure = array(
        !          90286:                     'name',
        !          90287:                     'uri',
        !          90288:                     'conflicts',
        !          90289:                     '*providesextension',
        !          90290:                 );
        !          90291:             } else {
        !          90292:                 $structure = array(
        !          90293:                     'name',
        !          90294:                     'uri',
        !          90295:                     '*providesextension',
        !          90296:                 );
        !          90297:             }
        !          90298:         } else {
        !          90299:             if (isset($dep['conflicts'])) {
        !          90300:                 $structure = array(
        !          90301:                     'name',
        !          90302:                     'channel',
        !          90303:                     '*min',
        !          90304:                     '*max',
        !          90305:                     '*exclude',
        !          90306:                     'conflicts',
        !          90307:                     '*providesextension',
        !          90308:                 );
        !          90309:             } else {
        !          90310:                 $structure = array(
        !          90311:                     'name',
        !          90312:                     'channel',
        !          90313:                     '*min',
        !          90314:                     '*max',
        !          90315:                     '*recommended',
        !          90316:                     '*exclude',
        !          90317:                     '*nodefault',
        !          90318:                     '*providesextension',
        !          90319:                 );
        !          90320:             }
1.1       misho    90321:         }
1.1.1.2 ! misho    90322:         if (isset($dep['name'])) {
        !          90323:             $type .= '<name>' . $dep['name'] . '</name>';
        !          90324:         }
        !          90325:         $this->_stupidSchemaValidate($structure, $dep, '<dependencies>' . $group . $type);
        !          90326:         if (isset($dep['uri']) && (isset($dep['min']) || isset($dep['max']) ||
        !          90327:               isset($dep['recommended']) || isset($dep['exclude']))) {
        !          90328:             $this->_uriDepsCannotHaveVersioning('<dependencies>' . $group . $type);
        !          90329:         }
        !          90330:         if (isset($dep['channel']) && strtolower($dep['channel']) == '__uri') {
        !          90331:             $this->_DepchannelCannotBeUri('<dependencies>' . $group . $type);
        !          90332:         }
        !          90333:         if (isset($dep['min'])) {
        !          90334:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
        !          90335:                   $dep['min'])) {
        !          90336:                 $this->_invalidVersion('<dependencies>' . $group . $type . '<min>', $dep['min']);
1.1       misho    90337:             }
1.1.1.2 ! misho    90338:         }
        !          90339:         if (isset($dep['max'])) {
        !          90340:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
        !          90341:                   $dep['max'])) {
        !          90342:                 $this->_invalidVersion('<dependencies>' . $group . $type . '<max>', $dep['max']);
1.1       misho    90343:             }
                   90344:         }
1.1.1.2 ! misho    90345:         if (isset($dep['recommended'])) {
        !          90346:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
        !          90347:                   $dep['recommended'])) {
        !          90348:                 $this->_invalidVersion('<dependencies>' . $group . $type . '<recommended>',
        !          90349:                     $dep['recommended']);
1.1       misho    90350:             }
1.1.1.2 ! misho    90351:         }
        !          90352:         if (isset($dep['exclude'])) {
        !          90353:             if (!is_array($dep['exclude'])) {
        !          90354:                 $dep['exclude'] = array($dep['exclude']);
        !          90355:             }
        !          90356:             foreach ($dep['exclude'] as $exclude) {
        !          90357:                 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
        !          90358:                       $exclude)) {
        !          90359:                     $this->_invalidVersion('<dependencies>' . $group . $type . '<exclude>',
        !          90360:                         $exclude);
1.1       misho    90361:                 }
                   90362:             }
                   90363:         }
                   90364:     }
                   90365: 
1.1.1.2 ! misho    90366:     function _validateSubpackageDep($dep, $group)
1.1       misho    90367:     {
1.1.1.2 ! misho    90368:         $this->_validatePackageDep($dep, $group, '<subpackage>');
        !          90369:         if (isset($dep['providesextension'])) {
        !          90370:             $this->_subpackageCannotProvideExtension(isset($dep['name']) ? $dep['name'] : '');
1.1       misho    90371:         }
1.1.1.2 ! misho    90372:         if (isset($dep['conflicts'])) {
        !          90373:             $this->_subpackagesCannotConflict(isset($dep['name']) ? $dep['name'] : '');
1.1       misho    90374:         }
                   90375:     }
                   90376: 
1.1.1.2 ! misho    90377:     function _validateExtensionDep($dep, $group = false, $installcondition = false)
1.1       misho    90378:     {
1.1.1.2 ! misho    90379:         if (isset($dep['conflicts'])) {
        !          90380:             $structure = array(
        !          90381:                 'name',
        !          90382:                 '*min',
        !          90383:                 '*max',
        !          90384:                 '*exclude',
        !          90385:                 'conflicts',
        !          90386:             );
        !          90387:         } else {
        !          90388:             $structure = array(
        !          90389:                 'name',
        !          90390:                 '*min',
        !          90391:                 '*max',
        !          90392:                 '*recommended',
        !          90393:                 '*exclude',
        !          90394:             );
1.1       misho    90395:         }
1.1.1.2 ! misho    90396:         if ($installcondition) {
        !          90397:             $type = '<installcondition><extension>';
1.1       misho    90398:         } else {
1.1.1.2 ! misho    90399:             $type = '<dependencies>' . $group . '<extension>';
1.1       misho    90400:         }
1.1.1.2 ! misho    90401:         if (isset($dep['name'])) {
        !          90402:             $type .= '<name>' . $dep['name'] . '</name>';
1.1       misho    90403:         }
1.1.1.2 ! misho    90404:         $this->_stupidSchemaValidate($structure, $dep, $type);
        !          90405:         if (isset($dep['min'])) {
        !          90406:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
        !          90407:                   $dep['min'])) {
        !          90408:                 $this->_invalidVersion(substr($type, 1) . '<min', $dep['min']);
        !          90409:             }
1.1       misho    90410:         }
1.1.1.2 ! misho    90411:         if (isset($dep['max'])) {
        !          90412:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
        !          90413:                   $dep['max'])) {
        !          90414:                 $this->_invalidVersion(substr($type, 1) . '<max', $dep['max']);
        !          90415:             }
1.1       misho    90416:         }
1.1.1.2 ! misho    90417:         if (isset($dep['recommended'])) {
        !          90418:             if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
        !          90419:                   $dep['recommended'])) {
        !          90420:                 $this->_invalidVersion(substr($type, 1) . '<recommended', $dep['recommended']);
1.1       misho    90421:             }
                   90422:         }
1.1.1.2 ! misho    90423:         if (isset($dep['exclude'])) {
        !          90424:             if (!is_array($dep['exclude'])) {
        !          90425:                 $dep['exclude'] = array($dep['exclude']);
        !          90426:             }
        !          90427:             foreach ($dep['exclude'] as $exclude) {
        !          90428:                 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
        !          90429:                       $exclude)) {
        !          90430:                     $this->_invalidVersion(substr($type, 1) . '<exclude', $exclude);
        !          90431:                 }
1.1       misho    90432:             }
                   90433:         }
                   90434:     }
                   90435: 
1.1.1.2 ! misho    90436:     function _validateOsDep($dep, $installcondition = false)
1.1       misho    90437:     {
1.1.1.2 ! misho    90438:         $structure = array(
        !          90439:             'name',
        !          90440:             '*conflicts',
        !          90441:         );
        !          90442:         $type = $installcondition ? '<installcondition><os>' : '<dependencies><required><os>';
        !          90443:         if ($this->_stupidSchemaValidate($structure, $dep, $type)) {
        !          90444:             if ($dep['name'] == '*') {
        !          90445:                 if (array_key_exists('conflicts', $dep)) {
        !          90446:                     $this->_cannotConflictWithAllOs($type);
        !          90447:                 }
        !          90448:             }
        !          90449:         }
1.1       misho    90450:     }
                   90451: 
1.1.1.2 ! misho    90452:     function _validateArchDep($dep, $installcondition = false)
1.1       misho    90453:     {
1.1.1.2 ! misho    90454:         $structure = array(
        !          90455:             'pattern',
        !          90456:             '*conflicts',
        !          90457:         );
        !          90458:         $type = $installcondition ? '<installcondition><arch>' : '<dependencies><required><arch>';
        !          90459:         $this->_stupidSchemaValidate($structure, $dep, $type);
1.1       misho    90460:     }
                   90461: 
1.1.1.2 ! misho    90462:     function _validateInstallConditions($cond, $release)
1.1       misho    90463:     {
1.1.1.2 ! misho    90464:         $structure = array(
        !          90465:             '*php',
        !          90466:             '*extension',
        !          90467:             '*os',
        !          90468:             '*arch',
        !          90469:         );
        !          90470:         if (!$this->_stupidSchemaValidate($structure,
        !          90471:               $cond, $release)) {
        !          90472:             return false;
1.1       misho    90473:         }
1.1.1.2 ! misho    90474:         foreach (array('php', 'extension', 'os', 'arch') as $type) {
        !          90475:             if (isset($cond[$type])) {
        !          90476:                 $iter = $cond[$type];
        !          90477:                 if (!is_array($iter) || !isset($iter[0])) {
        !          90478:                     $iter = array($iter);
        !          90479:                 }
        !          90480:                 foreach ($iter as $package) {
        !          90481:                     if ($type == 'extension') {
        !          90482:                         $this->{"_validate{$type}Dep"}($package, false, true);
        !          90483:                     } else {
        !          90484:                         $this->{"_validate{$type}Dep"}($package, true);
        !          90485:                     }
        !          90486:                 }
        !          90487:             }
1.1       misho    90488:         }
                   90489:     }
                   90490: 
1.1.1.2 ! misho    90491:     function _validateDependencies()
1.1       misho    90492:     {
1.1.1.2 ! misho    90493:         $structure = array(
        !          90494:             'required',
        !          90495:             '*optional',
        !          90496:             '*group->name->hint'
        !          90497:         );
        !          90498:         if (!$this->_stupidSchemaValidate($structure,
        !          90499:               $this->_packageInfo['dependencies'], '<dependencies>')) {
        !          90500:             return false;
1.1       misho    90501:         }
1.1.1.2 ! misho    90502:         foreach (array('required', 'optional') as $simpledep) {
        !          90503:             if (isset($this->_packageInfo['dependencies'][$simpledep])) {
        !          90504:                 if ($simpledep == 'optional') {
        !          90505:                     $structure = array(
        !          90506:                         '*package',
        !          90507:                         '*subpackage',
        !          90508:                         '*extension',
        !          90509:                     );
        !          90510:                 } else {
        !          90511:                     $structure = array(
        !          90512:                         'php',
        !          90513:                         'pearinstaller',
        !          90514:                         '*package',
        !          90515:                         '*subpackage',
        !          90516:                         '*extension',
        !          90517:                         '*os',
        !          90518:                         '*arch',
        !          90519:                     );
        !          90520:                 }
        !          90521:                 if ($this->_stupidSchemaValidate($structure,
        !          90522:                       $this->_packageInfo['dependencies'][$simpledep],
        !          90523:                       "<dependencies><$simpledep>")) {
        !          90524:                     foreach (array('package', 'subpackage', 'extension') as $type) {
        !          90525:                         if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) {
        !          90526:                             $iter = $this->_packageInfo['dependencies'][$simpledep][$type];
        !          90527:                             if (!isset($iter[0])) {
        !          90528:                                 $iter = array($iter);
        !          90529:                             }
        !          90530:                             foreach ($iter as $package) {
        !          90531:                                 if ($type != 'extension') {
        !          90532:                                     if (isset($package['uri'])) {
        !          90533:                                         if (isset($package['channel'])) {
        !          90534:                                             $this->_UrlOrChannel($type,
        !          90535:                                                 $package['name']);
        !          90536:                                         }
        !          90537:                                     } else {
        !          90538:                                         if (!isset($package['channel'])) {
        !          90539:                                             $this->_NoChannel($type, $package['name']);
        !          90540:                                         }
        !          90541:                                     }
        !          90542:                                 }
        !          90543:                                 $this->{"_validate{$type}Dep"}($package, "<$simpledep>");
        !          90544:                             }
        !          90545:                         }
        !          90546:                     }
        !          90547:                     if ($simpledep == 'optional') {
        !          90548:                         continue;
        !          90549:                     }
        !          90550:                     foreach (array('php', 'pearinstaller', 'os', 'arch') as $type) {
        !          90551:                         if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) {
        !          90552:                             $iter = $this->_packageInfo['dependencies'][$simpledep][$type];
        !          90553:                             if (!isset($iter[0])) {
        !          90554:                                 $iter = array($iter);
        !          90555:                             }
        !          90556:                             foreach ($iter as $package) {
        !          90557:                                 $this->{"_validate{$type}Dep"}($package);
        !          90558:                             }
        !          90559:                         }
        !          90560:                     }
        !          90561:                 }
        !          90562:             }
        !          90563:         }
        !          90564:         if (isset($this->_packageInfo['dependencies']['group'])) {
        !          90565:             $groups = $this->_packageInfo['dependencies']['group'];
        !          90566:             if (!isset($groups[0])) {
        !          90567:                 $groups = array($groups);
        !          90568:             }
        !          90569:             $structure = array(
        !          90570:                 '*package',
        !          90571:                 '*subpackage',
        !          90572:                 '*extension',
        !          90573:             );
        !          90574:             foreach ($groups as $group) {
        !          90575:                 if ($this->_stupidSchemaValidate($structure, $group, '<group>')) {
        !          90576:                     if (!PEAR_Validate::validGroupName($group['attribs']['name'])) {
        !          90577:                         $this->_invalidDepGroupName($group['attribs']['name']);
        !          90578:                     }
        !          90579:                     foreach (array('package', 'subpackage', 'extension') as $type) {
        !          90580:                         if (isset($group[$type])) {
        !          90581:                             $iter = $group[$type];
        !          90582:                             if (!isset($iter[0])) {
        !          90583:                                 $iter = array($iter);
        !          90584:                             }
        !          90585:                             foreach ($iter as $package) {
        !          90586:                                 if ($type != 'extension') {
        !          90587:                                     if (isset($package['uri'])) {
        !          90588:                                         if (isset($package['channel'])) {
        !          90589:                                             $this->_UrlOrChannelGroup($type,
        !          90590:                                                 $package['name'],
        !          90591:                                                 $group['name']);
        !          90592:                                         }
        !          90593:                                     } else {
        !          90594:                                         if (!isset($package['channel'])) {
        !          90595:                                             $this->_NoChannelGroup($type,
        !          90596:                                                 $package['name'],
        !          90597:                                                 $group['name']);
        !          90598:                                         }
        !          90599:                                     }
        !          90600:                                 }
        !          90601:                                 $this->{"_validate{$type}Dep"}($package, '<group name="' .
        !          90602:                                     $group['attribs']['name'] . '">');
        !          90603:                             }
        !          90604:                         }
        !          90605:                     }
        !          90606:                 }
        !          90607:             }
1.1       misho    90608:         }
                   90609:     }
                   90610: 
1.1.1.2 ! misho    90611:     function _validateCompatible()
1.1       misho    90612:     {
1.1.1.2 ! misho    90613:         $compat = $this->_packageInfo['compatible'];
        !          90614:         if (!isset($compat[0])) {
        !          90615:             $compat = array($compat);
        !          90616:         }
        !          90617:         $required = array('name', 'channel', 'min', 'max', '*exclude');
        !          90618:         foreach ($compat as $package) {
        !          90619:             $type = '<compatible>';
        !          90620:             if (is_array($package) && array_key_exists('name', $package)) {
        !          90621:                 $type .= '<name>' . $package['name'] . '</name>';
        !          90622:             }
        !          90623:             $this->_stupidSchemaValidate($required, $package, $type);
        !          90624:             if (is_array($package) && array_key_exists('min', $package)) {
        !          90625:                 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
        !          90626:                       $package['min'])) {
        !          90627:                     $this->_invalidVersion(substr($type, 1) . '<min', $package['min']);
        !          90628:                 }
        !          90629:             }
        !          90630:             if (is_array($package) && array_key_exists('max', $package)) {
        !          90631:                 if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
        !          90632:                       $package['max'])) {
        !          90633:                     $this->_invalidVersion(substr($type, 1) . '<max', $package['max']);
        !          90634:                 }
        !          90635:             }
        !          90636:             if (is_array($package) && array_key_exists('exclude', $package)) {
        !          90637:                 if (!is_array($package['exclude'])) {
        !          90638:                     $package['exclude'] = array($package['exclude']);
        !          90639:                 }
        !          90640:                 foreach ($package['exclude'] as $exclude) {
        !          90641:                     if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
        !          90642:                           $exclude)) {
        !          90643:                         $this->_invalidVersion(substr($type, 1) . '<exclude', $exclude);
        !          90644:                     }
        !          90645:                 }
        !          90646:             }
1.1       misho    90647:         }
                   90648:     }
                   90649: 
1.1.1.2 ! misho    90650:     function _validateBundle($list)
1.1       misho    90651:     {
1.1.1.2 ! misho    90652:         if (!is_array($list) || !isset($list['bundledpackage'])) {
        !          90653:             return $this->_NoBundledPackages();
        !          90654:         }
        !          90655:         if (!is_array($list['bundledpackage']) || !isset($list['bundledpackage'][0])) {
        !          90656:             return $this->_AtLeast2BundledPackages();
        !          90657:         }
        !          90658:         foreach ($list['bundledpackage'] as $package) {
        !          90659:             if (!is_string($package)) {
        !          90660:                 $this->_bundledPackagesMustBeFilename();
        !          90661:             }
1.1       misho    90662:         }
                   90663:     }
                   90664: 
1.1.1.2 ! misho    90665:     function _validateFilelist($list = false, $allowignore = false, $dirs = '')
1.1       misho    90666:     {
1.1.1.2 ! misho    90667:         $iscontents = false;
        !          90668:         if (!$list) {
        !          90669:             $iscontents = true;
        !          90670:             $list = $this->_packageInfo['contents'];
        !          90671:             if (isset($this->_packageInfo['bundle'])) {
        !          90672:                 return $this->_validateBundle($list);
        !          90673:             }
1.1       misho    90674:         }
1.1.1.2 ! misho    90675:         if ($allowignore) {
        !          90676:             $struc = array(
        !          90677:                 '*install->name->as',
        !          90678:                 '*ignore->name'
        !          90679:             );
1.1       misho    90680:         } else {
1.1.1.2 ! misho    90681:             $struc = array(
        !          90682:                 '*dir->name->?baseinstalldir',
        !          90683:                 '*file->name->role->?baseinstalldir->?md5sum'
        !          90684:             );
        !          90685:             if (isset($list['dir']) && isset($list['file'])) {
        !          90686:                 // stave off validation errors without requiring a set order.
        !          90687:                 $_old = $list;
        !          90688:                 if (isset($list['attribs'])) {
        !          90689:                     $list = array('attribs' => $_old['attribs']);
        !          90690:                 }
        !          90691:                 $list['dir'] = $_old['dir'];
        !          90692:                 $list['file'] = $_old['file'];
1.1       misho    90693:             }
1.1.1.2 ! misho    90694:         }
        !          90695:         if (!isset($list['attribs']) || !isset($list['attribs']['name'])) {
        !          90696:             $unknown = $allowignore ? '<filelist>' : '<dir name="*unknown*">';
        !          90697:             $dirname = $iscontents ? '<contents>' : $unknown;
        !          90698:         } else {
        !          90699:             $dirname = '<dir name="' . $list['attribs']['name'] . '">';
        !          90700:             if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
        !          90701:                           str_replace('\\', '/', $list['attribs']['name']))) {
        !          90702:                 // file contains .. parent directory or . cur directory
        !          90703:                 $this->_invalidDirName($list['attribs']['name']);
        !          90704:             }
        !          90705:         }
        !          90706:         $res = $this->_stupidSchemaValidate($struc, $list, $dirname);
        !          90707:         if ($allowignore && $res) {
        !          90708:             $ignored_or_installed = array();
        !          90709:             $this->_pf->getFilelist();
        !          90710:             $fcontents = $this->_pf->getContents();
        !          90711:             $filelist = array();
        !          90712:             if (!isset($fcontents['dir']['file'][0])) {
        !          90713:                 $fcontents['dir']['file'] = array($fcontents['dir']['file']);
        !          90714:             }
        !          90715:             foreach ($fcontents['dir']['file'] as $file) {
        !          90716:                 $filelist[$file['attribs']['name']] = true;
        !          90717:             }
        !          90718:             if (isset($list['install'])) {
        !          90719:                 if (!isset($list['install'][0])) {
        !          90720:                     $list['install'] = array($list['install']);
        !          90721:                 }
        !          90722:                 foreach ($list['install'] as $file) {
        !          90723:                     if (!isset($filelist[$file['attribs']['name']])) {
        !          90724:                         $this->_notInContents($file['attribs']['name'], 'install');
        !          90725:                         continue;
        !          90726:                     }
        !          90727:                     if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
        !          90728:                         $this->_multipleInstallAs($file['attribs']['name']);
        !          90729:                     }
        !          90730:                     if (!isset($ignored_or_installed[$file['attribs']['name']])) {
        !          90731:                         $ignored_or_installed[$file['attribs']['name']] = array();
        !          90732:                     }
        !          90733:                     $ignored_or_installed[$file['attribs']['name']][] = 1;
        !          90734:                     if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
        !          90735:                                   str_replace('\\', '/', $file['attribs']['as']))) {
        !          90736:                         // file contains .. parent directory or . cur directory references
        !          90737:                         $this->_invalidFileInstallAs($file['attribs']['name'],
        !          90738:                             $file['attribs']['as']);
        !          90739:                     }
1.1       misho    90740:                 }
                   90741:             }
1.1.1.2 ! misho    90742:             if (isset($list['ignore'])) {
        !          90743:                 if (!isset($list['ignore'][0])) {
        !          90744:                     $list['ignore'] = array($list['ignore']);
        !          90745:                 }
        !          90746:                 foreach ($list['ignore'] as $file) {
        !          90747:                     if (!isset($filelist[$file['attribs']['name']])) {
        !          90748:                         $this->_notInContents($file['attribs']['name'], 'ignore');
        !          90749:                         continue;
        !          90750:                     }
        !          90751:                     if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
        !          90752:                         $this->_ignoreAndInstallAs($file['attribs']['name']);
        !          90753:                     }
        !          90754:                 }
        !          90755:             }
        !          90756:         }
        !          90757:         if (!$allowignore && isset($list['file'])) {
        !          90758:             if (is_string($list['file'])) {
        !          90759:                 $this->_oldStyleFileNotAllowed();
        !          90760:                 return false;
        !          90761:             }
        !          90762:             if (!isset($list['file'][0])) {
        !          90763:                 // single file
        !          90764:                 $list['file'] = array($list['file']);
        !          90765:             }
        !          90766:             foreach ($list['file'] as $i => $file)
        !          90767:             {
        !          90768:                 if (isset($file['attribs']) && isset($file['attribs']['name'])) {
        !          90769:                     if ($file['attribs']['name']{0} == '.' &&
        !          90770:                           $file['attribs']['name']{1} == '/') {
        !          90771:                         // name is something like "./doc/whatever.txt"
        !          90772:                         $this->_invalidFileName($file['attribs']['name'], $dirname);
        !          90773:                     }
        !          90774:                     if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
        !          90775:                                   str_replace('\\', '/', $file['attribs']['name']))) {
        !          90776:                         // file contains .. parent directory or . cur directory
        !          90777:                         $this->_invalidFileName($file['attribs']['name'], $dirname);
        !          90778:                     }
        !          90779:                 }
        !          90780:                 if (isset($file['attribs']) && isset($file['attribs']['role'])) {
        !          90781:                     if (!$this->_validateRole($file['attribs']['role'])) {
        !          90782:                         if (isset($this->_packageInfo['usesrole'])) {
        !          90783:                             $roles = $this->_packageInfo['usesrole'];
        !          90784:                             if (!isset($roles[0])) {
        !          90785:                                 $roles = array($roles);
        !          90786:                             }
        !          90787:                             foreach ($roles as $role) {
        !          90788:                                 if ($role['role'] = $file['attribs']['role']) {
        !          90789:                                     $msg = 'This package contains role "%role%" and requires ' .
        !          90790:                                         'package "%package%" to be used';
        !          90791:                                     if (isset($role['uri'])) {
        !          90792:                                         $params = array('role' => $role['role'],
        !          90793:                                             'package' => $role['uri']);
        !          90794:                                     } else {
        !          90795:                                         $params = array('role' => $role['role'],
        !          90796:                                             'package' => $this->_pf->_registry->
        !          90797:                                             parsedPackageNameToString(array('package' =>
        !          90798:                                                 $role['package'], 'channel' => $role['channel']),
        !          90799:                                                 true));
        !          90800:                                     }
        !          90801:                                     $this->_stack->push('_mustInstallRole', 'error', $params, $msg);
        !          90802:                                 }
        !          90803:                             }
        !          90804:                         }
        !          90805:                         $this->_invalidFileRole($file['attribs']['name'],
        !          90806:                             $dirname, $file['attribs']['role']);
        !          90807:                     }
        !          90808:                 }
        !          90809:                 if (!isset($file['attribs'])) {
        !          90810:                     continue;
        !          90811:                 }
        !          90812:                 $save = $file['attribs'];
        !          90813:                 if ($dirs) {
        !          90814:                     $save['name'] = $dirs . '/' . $save['name'];
        !          90815:                 }
        !          90816:                 unset($file['attribs']);
        !          90817:                 if (count($file) && $this->_curState != PEAR_VALIDATE_DOWNLOADING) { // has tasks
        !          90818:                     foreach ($file as $task => $value) {
        !          90819:                         if ($tagClass = $this->_pf->getTask($task)) {
        !          90820:                             if (!is_array($value) || !isset($value[0])) {
        !          90821:                                 $value = array($value);
        !          90822:                             }
        !          90823:                             foreach ($value as $v) {
        !          90824:                                 $ret = call_user_func(array($tagClass, 'validateXml'),
        !          90825:                                     $this->_pf, $v, $this->_pf->_config, $save);
        !          90826:                                 if (is_array($ret)) {
        !          90827:                                     $this->_invalidTask($task, $ret, isset($save['name']) ?
        !          90828:                                         $save['name'] : '');
        !          90829:                                 }
        !          90830:                             }
        !          90831:                         } else {
        !          90832:                             if (isset($this->_packageInfo['usestask'])) {
        !          90833:                                 $roles = $this->_packageInfo['usestask'];
        !          90834:                                 if (!isset($roles[0])) {
        !          90835:                                     $roles = array($roles);
        !          90836:                                 }
        !          90837:                                 foreach ($roles as $role) {
        !          90838:                                     if ($role['task'] = $task) {
        !          90839:                                         $msg = 'This package contains task "%task%" and requires ' .
        !          90840:                                             'package "%package%" to be used';
        !          90841:                                         if (isset($role['uri'])) {
        !          90842:                                             $params = array('task' => $role['task'],
        !          90843:                                                 'package' => $role['uri']);
        !          90844:                                         } else {
        !          90845:                                             $params = array('task' => $role['task'],
        !          90846:                                                 'package' => $this->_pf->_registry->
        !          90847:                                                 parsedPackageNameToString(array('package' =>
        !          90848:                                                     $role['package'], 'channel' => $role['channel']),
        !          90849:                                                     true));
        !          90850:                                         }
        !          90851:                                         $this->_stack->push('_mustInstallTask', 'error',
        !          90852:                                             $params, $msg);
        !          90853:                                     }
        !          90854:                                 }
        !          90855:                             }
        !          90856:                             $this->_unknownTask($task, $save['name']);
        !          90857:                         }
        !          90858:                     }
1.1       misho    90859:                 }
                   90860:             }
1.1.1.2 ! misho    90861:         }
        !          90862:         if (isset($list['ignore'])) {
        !          90863:             if (!$allowignore) {
        !          90864:                 $this->_ignoreNotAllowed('ignore');
        !          90865:             }
        !          90866:         }
        !          90867:         if (isset($list['install'])) {
        !          90868:             if (!$allowignore) {
        !          90869:                 $this->_ignoreNotAllowed('install');
        !          90870:             }
        !          90871:         }
        !          90872:         if (isset($list['file'])) {
        !          90873:             if ($allowignore) {
        !          90874:                 $this->_fileNotAllowed('file');
        !          90875:             }
        !          90876:         }
        !          90877:         if (isset($list['dir'])) {
        !          90878:             if ($allowignore) {
        !          90879:                 $this->_fileNotAllowed('dir');
        !          90880:             } else {
        !          90881:                 if (!isset($list['dir'][0])) {
        !          90882:                     $list['dir'] = array($list['dir']);
        !          90883:                 }
        !          90884:                 foreach ($list['dir'] as $dir) {
        !          90885:                     if (isset($dir['attribs']) && isset($dir['attribs']['name'])) {
        !          90886:                         if ($dir['attribs']['name'] == '/' ||
        !          90887:                               !isset($this->_packageInfo['contents']['dir']['dir'])) {
        !          90888:                             // always use nothing if the filelist has already been flattened
        !          90889:                             $newdirs = '';
        !          90890:                         } elseif ($dirs == '') {
        !          90891:                             $newdirs = $dir['attribs']['name'];
        !          90892:                         } else {
        !          90893:                             $newdirs = $dirs . '/' . $dir['attribs']['name'];
        !          90894:                         }
        !          90895:                     } else {
        !          90896:                         $newdirs = $dirs;
        !          90897:                     }
        !          90898:                     $this->_validateFilelist($dir, $allowignore, $newdirs);
1.1       misho    90899:                 }
                   90900:             }
                   90901:         }
                   90902:     }
                   90903: 
1.1.1.2 ! misho    90904:     function _validateRelease()
1.1       misho    90905:     {
1.1.1.2 ! misho    90906:         if (isset($this->_packageInfo['phprelease'])) {
        !          90907:             $release = 'phprelease';
        !          90908:             if (isset($this->_packageInfo['providesextension'])) {
        !          90909:                 $this->_cannotProvideExtension($release);
        !          90910:             }
        !          90911:             if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
        !          90912:                 $this->_cannotHaveSrcpackage($release);
        !          90913:             }
        !          90914:             $releases = $this->_packageInfo['phprelease'];
        !          90915:             if (!is_array($releases)) {
        !          90916:                 return true;
        !          90917:             }
        !          90918:             if (!isset($releases[0])) {
        !          90919:                 $releases = array($releases);
        !          90920:             }
        !          90921:             foreach ($releases as $rel) {
        !          90922:                 $this->_stupidSchemaValidate(array(
        !          90923:                     '*installconditions',
        !          90924:                     '*filelist',
        !          90925:                 ), $rel, '<phprelease>');
        !          90926:             }
1.1       misho    90927:         }
1.1.1.2 ! misho    90928:         foreach (array('', 'zend') as $prefix) {
        !          90929:             $releasetype = $prefix . 'extsrcrelease';
        !          90930:             if (isset($this->_packageInfo[$releasetype])) {
        !          90931:                 $release = $releasetype;
        !          90932:                 if (!isset($this->_packageInfo['providesextension'])) {
        !          90933:                     $this->_mustProvideExtension($release);
        !          90934:                 }
        !          90935:                 if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
        !          90936:                     $this->_cannotHaveSrcpackage($release);
        !          90937:                 }
        !          90938:                 $releases = $this->_packageInfo[$releasetype];
        !          90939:                 if (!is_array($releases)) {
        !          90940:                     return true;
        !          90941:                 }
        !          90942:                 if (!isset($releases[0])) {
        !          90943:                     $releases = array($releases);
        !          90944:                 }
        !          90945:                 foreach ($releases as $rel) {
        !          90946:                     $this->_stupidSchemaValidate(array(
        !          90947:                         '*installconditions',
        !          90948:                         '*configureoption->name->prompt->?default',
        !          90949:                         '*binarypackage',
        !          90950:                         '*filelist',
        !          90951:                     ), $rel, '<' . $releasetype . '>');
        !          90952:                     if (isset($rel['binarypackage'])) {
        !          90953:                         if (!is_array($rel['binarypackage']) || !isset($rel['binarypackage'][0])) {
        !          90954:                             $rel['binarypackage'] = array($rel['binarypackage']);
        !          90955:                         }
        !          90956:                         foreach ($rel['binarypackage'] as $bin) {
        !          90957:                             if (!is_string($bin)) {
        !          90958:                                 $this->_binaryPackageMustBePackagename();
        !          90959:                             }
        !          90960:                         }
        !          90961:                     }
        !          90962:                 }
        !          90963:             }
        !          90964:             $releasetype = 'extbinrelease';
        !          90965:             if (isset($this->_packageInfo[$releasetype])) {
        !          90966:                 $release = $releasetype;
        !          90967:                 if (!isset($this->_packageInfo['providesextension'])) {
        !          90968:                     $this->_mustProvideExtension($release);
        !          90969:                 }
        !          90970:                 if (isset($this->_packageInfo['channel']) &&
        !          90971:                       !isset($this->_packageInfo['srcpackage'])) {
        !          90972:                     $this->_mustSrcPackage($release);
        !          90973:                 }
        !          90974:                 if (isset($this->_packageInfo['uri']) && !isset($this->_packageInfo['srcuri'])) {
        !          90975:                     $this->_mustSrcuri($release);
        !          90976:                 }
        !          90977:                 $releases = $this->_packageInfo[$releasetype];
        !          90978:                 if (!is_array($releases)) {
        !          90979:                     return true;
        !          90980:                 }
        !          90981:                 if (!isset($releases[0])) {
        !          90982:                     $releases = array($releases);
        !          90983:                 }
        !          90984:                 foreach ($releases as $rel) {
        !          90985:                     $this->_stupidSchemaValidate(array(
        !          90986:                         '*installconditions',
        !          90987:                         '*filelist',
        !          90988:                     ), $rel, '<' . $releasetype . '>');
        !          90989:                 }
        !          90990:             }
        !          90991:         }
        !          90992:         if (isset($this->_packageInfo['bundle'])) {
        !          90993:             $release = 'bundle';
        !          90994:             if (isset($this->_packageInfo['providesextension'])) {
        !          90995:                 $this->_cannotProvideExtension($release);
        !          90996:             }
        !          90997:             if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
        !          90998:                 $this->_cannotHaveSrcpackage($release);
        !          90999:             }
        !          91000:             $releases = $this->_packageInfo['bundle'];
        !          91001:             if (!is_array($releases) || !isset($releases[0])) {
        !          91002:                 $releases = array($releases);
        !          91003:             }
        !          91004:             foreach ($releases as $rel) {
        !          91005:                 $this->_stupidSchemaValidate(array(
        !          91006:                     '*installconditions',
        !          91007:                     '*filelist',
        !          91008:                 ), $rel, '<bundle>');
        !          91009:             }
        !          91010:         }
        !          91011:         foreach ($releases as $rel) {
        !          91012:             if (is_array($rel) && array_key_exists('installconditions', $rel)) {
        !          91013:                 $this->_validateInstallConditions($rel['installconditions'],
        !          91014:                     "<$release><installconditions>");
        !          91015:             }
        !          91016:             if (is_array($rel) && array_key_exists('filelist', $rel)) {
        !          91017:                 if ($rel['filelist']) {
1.1       misho    91018: 
1.1.1.2 ! misho    91019:                     $this->_validateFilelist($rel['filelist'], true);
        !          91020:                 }
        !          91021:             }
1.1       misho    91022:         }
                   91023:     }
                   91024: 
1.1.1.2 ! misho    91025:     /**
        !          91026:      * This is here to allow role extension through plugins
        !          91027:      * @param string
        !          91028:      */
        !          91029:     function _validateRole($role)
1.1       misho    91030:     {
1.1.1.2 ! misho    91031:         return in_array($role, PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType()));
1.1       misho    91032:     }
                   91033: 
1.1.1.2 ! misho    91034:     function _pearVersionTooLow($version)
1.1       misho    91035:     {
1.1.1.2 ! misho    91036:         $this->_stack->push(__FUNCTION__, 'error',
        !          91037:             array('version' => $version),
        !          91038:             'This package.xml requires PEAR version %version% to parse properly, we are ' .
        !          91039:             'version 1.9.4');
1.1       misho    91040:     }
                   91041: 
1.1.1.2 ! misho    91042:     function _invalidTagOrder($oktags, $actual, $root)
1.1       misho    91043:     {
1.1.1.2 ! misho    91044:         $this->_stack->push(__FUNCTION__, 'error',
        !          91045:             array('oktags' => $oktags, 'actual' => $actual, 'root' => $root),
        !          91046:             'Invalid tag order in %root%, found <%actual%> expected one of "%oktags%"');
1.1       misho    91047:     }
                   91048: 
1.1.1.2 ! misho    91049:     function _ignoreNotAllowed($type)
1.1       misho    91050:     {
1.1.1.2 ! misho    91051:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
        !          91052:             '<%type%> is not allowed inside global <contents>, only inside ' .
        !          91053:             '<phprelease>/<extbinrelease>/<zendextbinrelease>, use <dir> and <file> only');
1.1       misho    91054:     }
                   91055: 
1.1.1.2 ! misho    91056:     function _fileNotAllowed($type)
1.1       misho    91057:     {
1.1.1.2 ! misho    91058:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
        !          91059:             '<%type%> is not allowed inside release <filelist>, only inside ' .
        !          91060:             '<contents>, use <ignore> and <install> only');
1.1       misho    91061:     }
                   91062: 
1.1.1.2 ! misho    91063:     function _oldStyleFileNotAllowed()
1.1       misho    91064:     {
1.1.1.2 ! misho    91065:         $this->_stack->push(__FUNCTION__, 'error', array(),
        !          91066:             'Old-style <file>name</file> is not allowed.  Use' .
        !          91067:             '<file name="name" role="role"/>');
1.1       misho    91068:     }
                   91069: 
1.1.1.2 ! misho    91070:     function _tagMissingAttribute($tag, $attr, $context)
1.1       misho    91071:     {
1.1.1.2 ! misho    91072:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag,
        !          91073:             'attribute' => $attr, 'context' => $context),
        !          91074:             'tag <%tag%> in context "%context%" has no attribute "%attribute%"');
1.1       misho    91075:     }
                   91076: 
1.1.1.2 ! misho    91077:     function _tagHasNoAttribs($tag, $context)
1.1       misho    91078:     {
1.1.1.2 ! misho    91079:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag,
        !          91080:             'context' => $context),
        !          91081:             'tag <%tag%> has no attributes in context "%context%"');
1.1       misho    91082:     }
                   91083: 
1.1.1.2 ! misho    91084:     function _invalidInternalStructure()
1.1       misho    91085:     {
1.1.1.2 ! misho    91086:         $this->_stack->push(__FUNCTION__, 'exception', array(),
        !          91087:             'internal array was not generated by compatible parser, or extreme parser error, cannot continue');
1.1       misho    91088:     }
                   91089: 
1.1.1.2 ! misho    91090:     function _invalidFileRole($file, $dir, $role)
1.1       misho    91091:     {
1.1.1.2 ! misho    91092:         $this->_stack->push(__FUNCTION__, 'error', array(
        !          91093:             'file' => $file, 'dir' => $dir, 'role' => $role,
        !          91094:             'roles' => PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType())),
        !          91095:             'File "%file%" in directory "%dir%" has invalid role "%role%", should be one of %roles%');
1.1       misho    91096:     }
                   91097: 
1.1.1.2 ! misho    91098:     function _invalidFileName($file, $dir)
1.1       misho    91099:     {
1.1.1.2 ! misho    91100:         $this->_stack->push(__FUNCTION__, 'error', array(
        !          91101:             'file' => $file),
        !          91102:             'File "%file%" in directory "%dir%" cannot begin with "./" or contain ".."');
1.1       misho    91103:     }
                   91104: 
1.1.1.2 ! misho    91105:     function _invalidFileInstallAs($file, $as)
1.1       misho    91106:     {
1.1.1.2 ! misho    91107:         $this->_stack->push(__FUNCTION__, 'error', array(
        !          91108:             'file' => $file, 'as' => $as),
        !          91109:             'File "%file%" <install as="%as%"/> cannot contain "./" or contain ".."');
1.1       misho    91110:     }
                   91111: 
1.1.1.2 ! misho    91112:     function _invalidDirName($dir)
1.1       misho    91113:     {
1.1.1.2 ! misho    91114:         $this->_stack->push(__FUNCTION__, 'error', array(
        !          91115:             'dir' => $file),
        !          91116:             'Directory "%dir%" cannot begin with "./" or contain ".."');
1.1       misho    91117:     }
                   91118: 
1.1.1.2 ! misho    91119:     function _filelistCannotContainFile($filelist)
1.1       misho    91120:     {
1.1.1.2 ! misho    91121:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist),
        !          91122:             '<%tag%> can only contain <dir>, contains <file>.  Use ' .
        !          91123:             '<dir name="/"> as the first dir element');
1.1       misho    91124:     }
                   91125: 
1.1.1.2 ! misho    91126:     function _filelistMustContainDir($filelist)
1.1       misho    91127:     {
1.1.1.2 ! misho    91128:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist),
        !          91129:             '<%tag%> must contain <dir>.  Use <dir name="/"> as the ' .
        !          91130:             'first dir element');
1.1       misho    91131:     }
                   91132: 
1.1.1.2 ! misho    91133:     function _tagCannotBeEmpty($tag)
1.1       misho    91134:     {
1.1.1.2 ! misho    91135:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag),
        !          91136:             '<%tag%> cannot be empty (<%tag%/>)');
1.1       misho    91137:     }
                   91138: 
1.1.1.2 ! misho    91139:     function _UrlOrChannel($type, $name)
1.1       misho    91140:     {
1.1.1.2 ! misho    91141:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
        !          91142:             'name' => $name),
        !          91143:             'Required dependency <%type%> "%name%" can have either url OR ' .
        !          91144:             'channel attributes, and not both');
1.1       misho    91145:     }
                   91146: 
1.1.1.2 ! misho    91147:     function _NoChannel($type, $name)
1.1       misho    91148:     {
1.1.1.2 ! misho    91149:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
        !          91150:             'name' => $name),
        !          91151:             'Required dependency <%type%> "%name%" must have either url OR ' .
        !          91152:             'channel attributes');
        !          91153:     }
1.1       misho    91154: 
1.1.1.2 ! misho    91155:     function _UrlOrChannelGroup($type, $name, $group)
        !          91156:     {
        !          91157:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
        !          91158:             'name' => $name, 'group' => $group),
        !          91159:             'Group "%group%" dependency <%type%> "%name%" can have either url OR ' .
        !          91160:             'channel attributes, and not both');
1.1       misho    91161:     }
                   91162: 
1.1.1.2 ! misho    91163:     function _NoChannelGroup($type, $name, $group)
1.1       misho    91164:     {
1.1.1.2 ! misho    91165:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
        !          91166:             'name' => $name, 'group' => $group),
        !          91167:             'Group "%group%" dependency <%type%> "%name%" must have either url OR ' .
        !          91168:             'channel attributes');
1.1       misho    91169:     }
                   91170: 
1.1.1.2 ! misho    91171:     function _unknownChannel($channel)
1.1       misho    91172:     {
1.1.1.2 ! misho    91173:         $this->_stack->push(__FUNCTION__, 'error', array('channel' => $channel),
        !          91174:             'Unknown channel "%channel%"');
1.1       misho    91175:     }
                   91176: 
1.1.1.2 ! misho    91177:     function _noPackageVersion()
1.1       misho    91178:     {
1.1.1.2 ! misho    91179:         $this->_stack->push(__FUNCTION__, 'error', array(),
        !          91180:             'package.xml <package> tag has no version attribute, or version is not 2.0');
1.1       misho    91181:     }
                   91182: 
1.1.1.2 ! misho    91183:     function _NoBundledPackages()
1.1       misho    91184:     {
1.1.1.2 ! misho    91185:         $this->_stack->push(__FUNCTION__, 'error', array(),
        !          91186:             'No <bundledpackage> tag was found in <contents>, required for bundle packages');
1.1       misho    91187:     }
                   91188: 
1.1.1.2 ! misho    91189:     function _AtLeast2BundledPackages()
1.1       misho    91190:     {
1.1.1.2 ! misho    91191:         $this->_stack->push(__FUNCTION__, 'error', array(),
        !          91192:             'At least 2 packages must be bundled in a bundle package');
1.1       misho    91193:     }
                   91194: 
1.1.1.2 ! misho    91195:     function _ChannelOrUri($name)
1.1       misho    91196:     {
1.1.1.2 ! misho    91197:         $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
        !          91198:             'Bundled package "%name%" can have either a uri or a channel, not both');
1.1       misho    91199:     }
                   91200: 
1.1.1.2 ! misho    91201:     function _noChildTag($child, $tag)
1.1       misho    91202:     {
1.1.1.2 ! misho    91203:         $this->_stack->push(__FUNCTION__, 'error', array('child' => $child, 'tag' => $tag),
        !          91204:             'Tag <%tag%> is missing child tag <%child%>');
1.1       misho    91205:     }
                   91206: 
1.1.1.2 ! misho    91207:     function _invalidVersion($type, $value)
1.1       misho    91208:     {
1.1.1.2 ! misho    91209:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value),
        !          91210:             'Version type <%type%> is not a valid version (%value%)');
1.1       misho    91211:     }
                   91212: 
1.1.1.2 ! misho    91213:     function _invalidState($type, $value)
1.1       misho    91214:     {
1.1.1.2 ! misho    91215:         $states = array('stable', 'beta', 'alpha', 'devel');
        !          91216:         if ($type != 'api') {
        !          91217:             $states[] = 'snapshot';
1.1       misho    91218:         }
1.1.1.2 ! misho    91219:         if (strtolower($value) == 'rc') {
        !          91220:             $this->_stack->push(__FUNCTION__, 'error',
        !          91221:                 array('version' => $this->_packageInfo['version']['release']),
        !          91222:                 'RC is not a state, it is a version postfix, try %version%RC1, stability beta');
1.1       misho    91223:         }
1.1.1.2 ! misho    91224:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value,
        !          91225:             'types' => $states),
        !          91226:             'Stability type <%type%> is not a valid stability (%value%), must be one of ' .
        !          91227:             '%types%');
1.1       misho    91228:     }
                   91229: 
1.1.1.2 ! misho    91230:     function _invalidTask($task, $ret, $file)
1.1       misho    91231:     {
1.1.1.2 ! misho    91232:         switch ($ret[0]) {
        !          91233:             case PEAR_TASK_ERROR_MISSING_ATTRIB :
        !          91234:                 $info = array('attrib' => $ret[1], 'task' => $task, 'file' => $file);
        !          91235:                 $msg = 'task <%task%> is missing attribute "%attrib%" in file %file%';
        !          91236:             break;
        !          91237:             case PEAR_TASK_ERROR_NOATTRIBS :
        !          91238:                 $info = array('task' => $task, 'file' => $file);
        !          91239:                 $msg = 'task <%task%> has no attributes in file %file%';
        !          91240:             break;
        !          91241:             case PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE :
        !          91242:                 $info = array('attrib' => $ret[1], 'values' => $ret[3],
        !          91243:                     'was' => $ret[2], 'task' => $task, 'file' => $file);
        !          91244:                 $msg = 'task <%task%> attribute "%attrib%" has the wrong value "%was%" '.
        !          91245:                     'in file %file%, expecting one of "%values%"';
        !          91246:             break;
        !          91247:             case PEAR_TASK_ERROR_INVALID :
        !          91248:                 $info = array('reason' => $ret[1], 'task' => $task, 'file' => $file);
        !          91249:                 $msg = 'task <%task%> in file %file% is invalid because of "%reason%"';
        !          91250:             break;
1.1       misho    91251:         }
1.1.1.2 ! misho    91252:         $this->_stack->push(__FUNCTION__, 'error', $info, $msg);
1.1       misho    91253:     }
                   91254: 
1.1.1.2 ! misho    91255:     function _unknownTask($task, $file)
1.1       misho    91256:     {
1.1.1.2 ! misho    91257:         $this->_stack->push(__FUNCTION__, 'error', array('task' => $task, 'file' => $file),
        !          91258:             'Unknown task "%task%" passed in file <file name="%file%">');
1.1       misho    91259:     }
                   91260: 
1.1.1.2 ! misho    91261:     function _subpackageCannotProvideExtension($name)
1.1       misho    91262:     {
1.1.1.2 ! misho    91263:         $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
        !          91264:             'Subpackage dependency "%name%" cannot use <providesextension>, ' .
        !          91265:             'only package dependencies can use this tag');
1.1       misho    91266:     }
                   91267: 
1.1.1.2 ! misho    91268:     function _subpackagesCannotConflict($name)
1.1       misho    91269:     {
1.1.1.2 ! misho    91270:         $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
        !          91271:             'Subpackage dependency "%name%" cannot use <conflicts/>, ' .
        !          91272:             'only package dependencies can use this tag');
1.1       misho    91273:     }
                   91274: 
1.1.1.2 ! misho    91275:     function _cannotProvideExtension($release)
1.1       misho    91276:     {
1.1.1.2 ! misho    91277:         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
        !          91278:             '<%release%> packages cannot use <providesextension>, only extbinrelease, extsrcrelease, zendextsrcrelease, and zendextbinrelease can provide a PHP extension');
1.1       misho    91279:     }
                   91280: 
1.1.1.2 ! misho    91281:     function _mustProvideExtension($release)
1.1       misho    91282:     {
1.1.1.2 ! misho    91283:         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
        !          91284:             '<%release%> packages must use <providesextension> to indicate which PHP extension is provided');
1.1       misho    91285:     }
                   91286: 
1.1.1.2 ! misho    91287:     function _cannotHaveSrcpackage($release)
1.1       misho    91288:     {
1.1.1.2 ! misho    91289:         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
        !          91290:             '<%release%> packages cannot specify a source code package, only extension binaries may use the <srcpackage> tag');
1.1       misho    91291:     }
                   91292: 
1.1.1.2 ! misho    91293:     function _mustSrcPackage($release)
1.1       misho    91294:     {
1.1.1.2 ! misho    91295:         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
        !          91296:             '<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcpackage>');
1.1       misho    91297:     }
                   91298: 
1.1.1.2 ! misho    91299:     function _mustSrcuri($release)
1.1       misho    91300:     {
1.1.1.2 ! misho    91301:         $this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
        !          91302:             '<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcuri>');
1.1       misho    91303:     }
                   91304: 
1.1.1.2 ! misho    91305:     function _uriDepsCannotHaveVersioning($type)
1.1       misho    91306:     {
1.1.1.2 ! misho    91307:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
        !          91308:             '%type%: dependencies with a <uri> tag cannot have any versioning information');
1.1       misho    91309:     }
                   91310: 
1.1.1.2 ! misho    91311:     function _conflictingDepsCannotHaveVersioning($type)
1.1       misho    91312:     {
1.1.1.2 ! misho    91313:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
        !          91314:             '%type%: conflicting dependencies cannot have versioning info, use <exclude> to ' .
        !          91315:             'exclude specific versions of a dependency');
1.1       misho    91316:     }
                   91317: 
1.1.1.2 ! misho    91318:     function _DepchannelCannotBeUri($type)
1.1       misho    91319:     {
1.1.1.2 ! misho    91320:         $this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
        !          91321:             '%type%: channel cannot be __uri, this is a pseudo-channel reserved for uri ' .
        !          91322:             'dependencies only');
1.1       misho    91323:     }
                   91324: 
1.1.1.2 ! misho    91325:     function _bundledPackagesMustBeFilename()
1.1       misho    91326:     {
1.1.1.2 ! misho    91327:         $this->_stack->push(__FUNCTION__, 'error', array(),
        !          91328:             '<bundledpackage> tags must contain only the filename of a package release ' .
        !          91329:             'in the bundle');
1.1       misho    91330:     }
                   91331: 
1.1.1.2 ! misho    91332:     function _binaryPackageMustBePackagename()
1.1       misho    91333:     {
1.1.1.2 ! misho    91334:         $this->_stack->push(__FUNCTION__, 'error', array(),
        !          91335:             '<binarypackage> tags must contain the name of a package that is ' .
        !          91336:             'a compiled version of this extsrc/zendextsrc package');
1.1       misho    91337:     }
                   91338: 
1.1.1.2 ! misho    91339:     function _fileNotFound($file)
1.1       misho    91340:     {
1.1.1.2 ! misho    91341:         $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
        !          91342:             'File "%file%" in package.xml does not exist');
1.1       misho    91343:     }
                   91344: 
1.1.1.2 ! misho    91345:     function _notInContents($file, $tag)
1.1       misho    91346:     {
1.1.1.2 ! misho    91347:         $this->_stack->push(__FUNCTION__, 'error', array('file' => $file, 'tag' => $tag),
        !          91348:             '<%tag% name="%file%"> is invalid, file is not in <contents>');
1.1       misho    91349:     }
                   91350: 
1.1.1.2 ! misho    91351:     function _cannotValidateNoPathSet()
1.1       misho    91352:     {
1.1.1.2 ! misho    91353:         $this->_stack->push(__FUNCTION__, 'error', array(),
        !          91354:             'Cannot validate files, no path to package file is set (use setPackageFile())');
1.1       misho    91355:     }
                   91356: 
1.1.1.2 ! misho    91357:     function _usesroletaskMustHaveChannelOrUri($role, $tag)
1.1       misho    91358:     {
1.1.1.2 ! misho    91359:         $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
        !          91360:             '<%tag%> for role "%role%" must contain either <uri>, or <channel> and <package>');
1.1       misho    91361:     }
                   91362: 
1.1.1.2 ! misho    91363:     function _usesroletaskMustHavePackage($role, $tag)
1.1       misho    91364:     {
1.1.1.2 ! misho    91365:         $this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
        !          91366:             '<%tag%> for role "%role%" must contain <package>');
1.1       misho    91367:     }
                   91368: 
1.1.1.2 ! misho    91369:     function _usesroletaskMustHaveRoleTask($tag, $type)
1.1       misho    91370:     {
1.1.1.2 ! misho    91371:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, 'type' => $type),
        !          91372:             '<%tag%> must contain <%type%> defining the %type% to be used');
1.1       misho    91373:     }
                   91374: 
1.1.1.2 ! misho    91375:     function _cannotConflictWithAllOs($type)
1.1       misho    91376:     {
1.1.1.2 ! misho    91377:         $this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag),
        !          91378:             '%tag% cannot conflict with all OSes');
1.1       misho    91379:     }
                   91380: 
1.1.1.2 ! misho    91381:     function _invalidDepGroupName($name)
1.1       misho    91382:     {
1.1.1.2 ! misho    91383:         $this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
        !          91384:             'Invalid dependency group name "%name%"');
1.1       misho    91385:     }
                   91386: 
1.1.1.2 ! misho    91387:     function _multipleToplevelDirNotAllowed()
1.1       misho    91388:     {
1.1.1.2 ! misho    91389:         $this->_stack->push(__FUNCTION__, 'error', array(),
        !          91390:             'Multiple top-level <dir> tags are not allowed.  Enclose them ' .
        !          91391:                 'in a <dir name="/">');
1.1       misho    91392:     }
                   91393: 
1.1.1.2 ! misho    91394:     function _multipleInstallAs($file)
1.1       misho    91395:     {
1.1.1.2 ! misho    91396:         $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
        !          91397:             'Only one <install> tag is allowed for file "%file%"');
1.1       misho    91398:     }
                   91399: 
1.1.1.2 ! misho    91400:     function _ignoreAndInstallAs($file)
1.1       misho    91401:     {
1.1.1.2 ! misho    91402:         $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
        !          91403:             'Cannot have both <ignore> and <install> tags for file "%file%"');
1.1       misho    91404:     }
1.1.1.2 ! misho    91405: 
        !          91406:     function _analyzeBundledPackages()
1.1       misho    91407:     {
1.1.1.2 ! misho    91408:         if (!$this->_isValid) {
1.1       misho    91409:             return false;
                   91410:         }
1.1.1.2 ! misho    91411:         if (!$this->_pf->getPackageType() == 'bundle') {
1.1       misho    91412:             return false;
                   91413:         }
1.1.1.2 ! misho    91414:         if (!isset($this->_pf->_packageFile)) {
1.1       misho    91415:             return false;
                   91416:         }
1.1.1.2 ! misho    91417:         $dir_prefix = dirname($this->_pf->_packageFile);
        !          91418:         $common = new PEAR_Common;
        !          91419:         $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
        !          91420:             array($common, 'log');
        !          91421:         $info = $this->_pf->getContents();
        !          91422:         $info = $info['bundledpackage'];
        !          91423:         if (!is_array($info)) {
        !          91424:             $info = array($info);
1.1       misho    91425:         }
1.1.1.2 ! misho    91426:         $pkg = &new PEAR_PackageFile($this->_pf->_config);
        !          91427:         foreach ($info as $package) {
        !          91428:             if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $package)) {
        !          91429:                 $this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $package);
        !          91430:                 $this->_isValid = 0;
        !          91431:                 continue;
        !          91432:             }
        !          91433:             call_user_func_array($log, array(1, "Analyzing bundled package $package"));
        !          91434:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          91435:             $ret = $pkg->fromAnyFile($dir_prefix . DIRECTORY_SEPARATOR . $package,
        !          91436:                 PEAR_VALIDATE_NORMAL);
        !          91437:             PEAR::popErrorHandling();
        !          91438:             if (PEAR::isError($ret)) {
        !          91439:                 call_user_func_array($log, array(0, "ERROR: package $package is not a valid " .
        !          91440:                     'package'));
        !          91441:                 $inf = $ret->getUserInfo();
        !          91442:                 if (is_array($inf)) {
        !          91443:                     foreach ($inf as $err) {
        !          91444:                         call_user_func_array($log, array(1, $err['message']));
        !          91445:                     }
        !          91446:                 }
        !          91447:                 return false;
        !          91448:             }
1.1       misho    91449:         }
1.1.1.2 ! misho    91450:         return true;
        !          91451:     }
        !          91452: 
        !          91453:     function _analyzePhpFiles()
        !          91454:     {
        !          91455:         if (!$this->_isValid) {
        !          91456:             return false;
1.1       misho    91457:         }
1.1.1.2 ! misho    91458:         if (!isset($this->_pf->_packageFile)) {
        !          91459:             $this->_cannotValidateNoPathSet();
        !          91460:             return false;
1.1       misho    91461:         }
1.1.1.2 ! misho    91462:         $dir_prefix = dirname($this->_pf->_packageFile);
        !          91463:         $common = new PEAR_Common;
        !          91464:         $log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
        !          91465:             array(&$common, 'log');
        !          91466:         $info = $this->_pf->getContents();
        !          91467:         if (!$info || !isset($info['dir']['file'])) {
        !          91468:             $this->_tagCannotBeEmpty('contents><dir');
        !          91469:             return false;
1.1       misho    91470:         }
1.1.1.2 ! misho    91471:         $info = $info['dir']['file'];
        !          91472:         if (isset($info['attribs'])) {
        !          91473:             $info = array($info);
1.1       misho    91474:         }
1.1.1.2 ! misho    91475:         $provides = array();
        !          91476:         foreach ($info as $fa) {
        !          91477:             $fa = $fa['attribs'];
        !          91478:             $file = $fa['name'];
        !          91479:             if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) {
        !          91480:                 $this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $file);
        !          91481:                 $this->_isValid = 0;
        !          91482:                 continue;
        !          91483:             }
        !          91484:             if (in_array($fa['role'], PEAR_Installer_Role::getPhpRoles()) && $dir_prefix) {
        !          91485:                 call_user_func_array($log, array(1, "Analyzing $file"));
        !          91486:                 $srcinfo = $this->analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file);
        !          91487:                 if ($srcinfo) {
        !          91488:                     $provides = array_merge($provides, $this->_buildProvidesArray($srcinfo));
1.1       misho    91489:                 }
                   91490:             }
                   91491:         }
1.1.1.2 ! misho    91492:         $this->_packageName = $pn = $this->_pf->getPackage();
        !          91493:         $pnl = strlen($pn);
        !          91494:         foreach ($provides as $key => $what) {
        !          91495:             if (isset($what['explicit']) || !$what) {
        !          91496:                 // skip conformance checks if the provides entry is
        !          91497:                 // specified in the package.xml file
        !          91498:                 continue;
1.1       misho    91499:             }
1.1.1.2 ! misho    91500:             extract($what);
        !          91501:             if ($type == 'class') {
        !          91502:                 if (!strncasecmp($name, $pn, $pnl)) {
        !          91503:                     continue;
        !          91504:                 }
        !          91505:                 $this->_stack->push(__FUNCTION__, 'warning',
        !          91506:                     array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn),
        !          91507:                     'in %file%: %type% "%name%" not prefixed with package name "%package%"');
        !          91508:             } elseif ($type == 'function') {
        !          91509:                 if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) {
        !          91510:                     continue;
1.1       misho    91511:                 }
1.1.1.2 ! misho    91512:                 $this->_stack->push(__FUNCTION__, 'warning',
        !          91513:                     array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn),
        !          91514:                     'in %file%: %type% "%name%" not prefixed with package name "%package%"');
1.1       misho    91515:             }
                   91516:         }
1.1.1.2 ! misho    91517:         return $this->_isValid;
        !          91518:     }
1.1       misho    91519: 
1.1.1.2 ! misho    91520:     /**
        !          91521:      * Analyze the source code of the given PHP file
        !          91522:      *
        !          91523:      * @param  string Filename of the PHP file
        !          91524:      * @param  boolean whether to analyze $file as the file contents
        !          91525:      * @return mixed
        !          91526:      */
        !          91527:     function analyzeSourceCode($file, $string = false)
        !          91528:     {
        !          91529:         if (!function_exists("token_get_all")) {
        !          91530:             $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
        !          91531:                 'Parser error: token_get_all() function must exist to analyze source code, PHP may have been compiled with --disable-tokenizer');
1.1       misho    91532:             return false;
                   91533:         }
                   91534: 
1.1.1.2 ! misho    91535:         if (!defined('T_DOC_COMMENT')) {
        !          91536:             define('T_DOC_COMMENT', T_COMMENT);
1.1       misho    91537:         }
                   91538: 
1.1.1.2 ! misho    91539:         if (!defined('T_INTERFACE')) {
        !          91540:             define('T_INTERFACE', -1);
1.1       misho    91541:         }
                   91542: 
1.1.1.2 ! misho    91543:         if (!defined('T_IMPLEMENTS')) {
        !          91544:             define('T_IMPLEMENTS', -1);
1.1       misho    91545:         }
                   91546: 
1.1.1.2 ! misho    91547:         if ($string) {
        !          91548:             $contents = $file;
        !          91549:         } else {
        !          91550:             if (!$fp = @fopen($file, "r")) {
        !          91551:                 return false;
        !          91552:             }
        !          91553:             fclose($fp);
        !          91554:             $contents = file_get_contents($file);
1.1       misho    91555:         }
                   91556: 
1.1.1.2 ! misho    91557:         // Silence this function so we can catch PHP Warnings and show our own custom message
        !          91558:         $tokens = @token_get_all($contents);
        !          91559:         if (isset($php_errormsg)) {
        !          91560:             if (isset($this->_stack)) {
        !          91561:                 $pn = $this->_pf->getPackage();
        !          91562:                 $this->_stack->push(__FUNCTION__, 'warning',
        !          91563:                         array('file' => $file, 'package' => $pn),
        !          91564:                         'in %file%: Could not process file for unkown reasons,' .
        !          91565:                         ' possibly a PHP parse error in %file% from %package%');
        !          91566:             }
1.1       misho    91567:         }
1.1.1.2 ! misho    91568: /*
        !          91569:         for ($i = 0; $i < sizeof($tokens); $i++) {
        !          91570:             @list($token, $data) = $tokens[$i];
        !          91571:             if (is_string($token)) {
        !          91572:                 var_dump($token);
        !          91573:             } else {
        !          91574:                 print token_name($token) . ' ';
        !          91575:                 var_dump(rtrim($data));
        !          91576:             }
1.1       misho    91577:         }
1.1.1.2 ! misho    91578: */
        !          91579:         $look_for = 0;
        !          91580:         $paren_level = 0;
        !          91581:         $bracket_level = 0;
        !          91582:         $brace_level = 0;
        !          91583:         $lastphpdoc = '';
        !          91584:         $current_class = '';
        !          91585:         $current_interface = '';
        !          91586:         $current_class_level = -1;
        !          91587:         $current_function = '';
        !          91588:         $current_function_level = -1;
        !          91589:         $declared_classes = array();
        !          91590:         $declared_interfaces = array();
        !          91591:         $declared_functions = array();
        !          91592:         $declared_methods = array();
        !          91593:         $used_classes = array();
        !          91594:         $used_functions = array();
        !          91595:         $extends = array();
        !          91596:         $implements = array();
        !          91597:         $nodeps = array();
        !          91598:         $inquote = false;
        !          91599:         $interface = false;
        !          91600:         for ($i = 0; $i < sizeof($tokens); $i++) {
        !          91601:             if (is_array($tokens[$i])) {
        !          91602:                 list($token, $data) = $tokens[$i];
        !          91603:             } else {
        !          91604:                 $token = $tokens[$i];
        !          91605:                 $data = '';
1.1       misho    91606:             }
1.1.1.2 ! misho    91607: 
        !          91608:             if ($inquote) {
        !          91609:                 if ($token != '"' && $token != T_END_HEREDOC) {
        !          91610:                     continue;
        !          91611:                 } else {
        !          91612:                     $inquote = false;
        !          91613:                     continue;
        !          91614:                 }
        !          91615:             }
        !          91616: 
        !          91617:             switch ($token) {
        !          91618:                 case T_WHITESPACE :
        !          91619:                     continue;
        !          91620:                 case ';':
        !          91621:                     if ($interface) {
        !          91622:                         $current_function = '';
        !          91623:                         $current_function_level = -1;
1.1       misho    91624:                     }
1.1.1.2 ! misho    91625:                     break;
        !          91626:                 case '"':
        !          91627:                 case T_START_HEREDOC:
        !          91628:                     $inquote = true;
        !          91629:                     break;
        !          91630:                 case T_CURLY_OPEN:
        !          91631:                 case T_DOLLAR_OPEN_CURLY_BRACES:
        !          91632:                 case '{': $brace_level++; continue 2;
        !          91633:                 case '}':
        !          91634:                     $brace_level--;
        !          91635:                     if ($current_class_level == $brace_level) {
        !          91636:                         $current_class = '';
        !          91637:                         $current_class_level = -1;
1.1       misho    91638:                     }
1.1.1.2 ! misho    91639:                     if ($current_function_level == $brace_level) {
        !          91640:                         $current_function = '';
        !          91641:                         $current_function_level = -1;
        !          91642:                     }
        !          91643:                     continue 2;
        !          91644:                 case '[': $bracket_level++; continue 2;
        !          91645:                 case ']': $bracket_level--; continue 2;
        !          91646:                 case '(': $paren_level++;   continue 2;
        !          91647:                 case ')': $paren_level--;   continue 2;
        !          91648:                 case T_INTERFACE:
        !          91649:                     $interface = true;
        !          91650:                 case T_CLASS:
        !          91651:                     if (($current_class_level != -1) || ($current_function_level != -1)) {
        !          91652:                         if (isset($this->_stack)) {
        !          91653:                             $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
        !          91654:                             'Parser error: invalid PHP found in file "%file%"');
        !          91655:                         } else {
        !          91656:                             PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"",
        !          91657:                                 PEAR_COMMON_ERROR_INVALIDPHP);
        !          91658:                         }
        !          91659: 
1.1       misho    91660:                         return false;
1.1.1.2 ! misho    91661:                     }
        !          91662:                 case T_FUNCTION:
        !          91663:                 case T_NEW:
        !          91664:                 case T_EXTENDS:
        !          91665:                 case T_IMPLEMENTS:
        !          91666:                     $look_for = $token;
        !          91667:                     continue 2;
        !          91668:                 case T_STRING:
        !          91669:                     if (version_compare(zend_version(), '2.0', '<')) {
        !          91670:                         if (in_array(strtolower($data),
        !          91671:                             array('public', 'private', 'protected', 'abstract',
        !          91672:                                   'interface', 'implements', 'throw')
        !          91673:                                  )
        !          91674:                         ) {
        !          91675:                             if (isset($this->_stack)) {
        !          91676:                                 $this->_stack->push(__FUNCTION__, 'warning', array(
        !          91677:                                     'file' => $file),
        !          91678:                                     'Error, PHP5 token encountered in %file%,' .
        !          91679:                                     ' analysis should be in PHP5');
        !          91680:                             } else {
        !          91681:                                 PEAR::raiseError('Error: PHP5 token encountered in ' . $file .
        !          91682:                                     'packaging should be done in PHP 5');
        !          91683:                                 return false;
        !          91684:                             }
1.1       misho    91685:                         }
                   91686:                     }
1.1.1.2 ! misho    91687: 
        !          91688:                     if ($look_for == T_CLASS) {
        !          91689:                         $current_class = $data;
        !          91690:                         $current_class_level = $brace_level;
        !          91691:                         $declared_classes[] = $current_class;
        !          91692:                     } elseif ($look_for == T_INTERFACE) {
        !          91693:                         $current_interface = $data;
        !          91694:                         $current_class_level = $brace_level;
        !          91695:                         $declared_interfaces[] = $current_interface;
        !          91696:                     } elseif ($look_for == T_IMPLEMENTS) {
        !          91697:                         $implements[$current_class] = $data;
        !          91698:                     } elseif ($look_for == T_EXTENDS) {
        !          91699:                         $extends[$current_class] = $data;
        !          91700:                     } elseif ($look_for == T_FUNCTION) {
        !          91701:                         if ($current_class) {
        !          91702:                             $current_function = "$current_class::$data";
        !          91703:                             $declared_methods[$current_class][] = $data;
        !          91704:                         } elseif ($current_interface) {
        !          91705:                             $current_function = "$current_interface::$data";
        !          91706:                             $declared_methods[$current_interface][] = $data;
        !          91707:                         } else {
        !          91708:                             $current_function = $data;
        !          91709:                             $declared_functions[] = $current_function;
        !          91710:                         }
        !          91711: 
        !          91712:                         $current_function_level = $brace_level;
        !          91713:                         $m = array();
        !          91714:                     } elseif ($look_for == T_NEW) {
        !          91715:                         $used_classes[$data] = true;
1.1       misho    91716:                     }
                   91717: 
1.1.1.2 ! misho    91718:                     $look_for = 0;
        !          91719:                     continue 2;
        !          91720:                 case T_VARIABLE:
        !          91721:                     $look_for = 0;
        !          91722:                     continue 2;
        !          91723:                 case T_DOC_COMMENT:
        !          91724:                 case T_COMMENT:
        !          91725:                     if (preg_match('!^/\*\*\s!', $data)) {
        !          91726:                         $lastphpdoc = $data;
        !          91727:                         if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) {
        !          91728:                             $nodeps = array_merge($nodeps, $m[1]);
1.1       misho    91729:                         }
                   91730:                     }
1.1.1.2 ! misho    91731:                     continue 2;
        !          91732:                 case T_DOUBLE_COLON:
        !          91733:                     $token = $tokens[$i - 1][0];
        !          91734:                     if (!($token == T_WHITESPACE || $token == T_STRING || $token == T_STATIC)) {
        !          91735:                         if (isset($this->_stack)) {
        !          91736:                             $this->_stack->push(__FUNCTION__, 'warning', array('file' => $file),
        !          91737:                                 'Parser error: invalid PHP found in file "%file%"');
        !          91738:                         } else {
        !          91739:                             PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"",
        !          91740:                                 PEAR_COMMON_ERROR_INVALIDPHP);
1.1       misho    91741:                         }
1.1.1.2 ! misho    91742: 
        !          91743:                         return false;
1.1       misho    91744:                     }
1.1.1.2 ! misho    91745: 
        !          91746:                     $class = $tokens[$i - 1][1];
        !          91747:                     if (strtolower($class) != 'parent') {
        !          91748:                         $used_classes[$class] = true;
        !          91749:                     }
        !          91750: 
        !          91751:                     continue 2;
1.1       misho    91752:             }
                   91753:         }
1.1.1.2 ! misho    91754: 
        !          91755:         return array(
        !          91756:             "source_file" => $file,
        !          91757:             "declared_classes" => $declared_classes,
        !          91758:             "declared_interfaces" => $declared_interfaces,
        !          91759:             "declared_methods" => $declared_methods,
        !          91760:             "declared_functions" => $declared_functions,
        !          91761:             "used_classes" => array_diff(array_keys($used_classes), $nodeps),
        !          91762:             "inheritance" => $extends,
        !          91763:             "implements" => $implements,
        !          91764:         );
1.1       misho    91765:     }
                   91766: 
1.1.1.2 ! misho    91767:     /**
        !          91768:      * Build a "provides" array from data returned by
        !          91769:      * analyzeSourceCode().  The format of the built array is like
        !          91770:      * this:
        !          91771:      *
        !          91772:      *  array(
        !          91773:      *    'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
        !          91774:      *    ...
        !          91775:      *  )
        !          91776:      *
        !          91777:      *
        !          91778:      * @param array $srcinfo array with information about a source file
        !          91779:      * as returned by the analyzeSourceCode() method.
        !          91780:      *
        !          91781:      * @return void
        !          91782:      *
        !          91783:      * @access private
        !          91784:      *
        !          91785:      */
        !          91786:     function _buildProvidesArray($srcinfo)
1.1       misho    91787:     {
1.1.1.2 ! misho    91788:         if (!$this->_isValid) {
        !          91789:             return array();
1.1       misho    91790:         }
                   91791: 
1.1.1.2 ! misho    91792:         $providesret = array();
        !          91793:         $file        = basename($srcinfo['source_file']);
        !          91794:         $pn          = isset($this->_pf) ? $this->_pf->getPackage() : '';
        !          91795:         $pnl         = strlen($pn);
        !          91796:         foreach ($srcinfo['declared_classes'] as $class) {
        !          91797:             $key = "class;$class";
        !          91798:             if (isset($providesret[$key])) {
        !          91799:                 continue;
1.1       misho    91800:             }
1.1.1.2 ! misho    91801: 
        !          91802:             $providesret[$key] =
        !          91803:                 array('file'=> $file, 'type' => 'class', 'name' => $class);
        !          91804:             if (isset($srcinfo['inheritance'][$class])) {
        !          91805:                 $providesret[$key]['extends'] =
        !          91806:                     $srcinfo['inheritance'][$class];
1.1       misho    91807:             }
                   91808:         }
                   91809: 
1.1.1.2 ! misho    91810:         foreach ($srcinfo['declared_methods'] as $class => $methods) {
        !          91811:             foreach ($methods as $method) {
        !          91812:                 $function = "$class::$method";
        !          91813:                 $key = "function;$function";
        !          91814:                 if ($method{0} == '_' || !strcasecmp($method, $class) ||
        !          91815:                     isset($providesret[$key])) {
        !          91816:                     continue;
1.1       misho    91817:                 }
                   91818: 
1.1.1.2 ! misho    91819:                 $providesret[$key] =
        !          91820:                     array('file'=> $file, 'type' => 'function', 'name' => $function);
1.1       misho    91821:             }
                   91822:         }
1.1.1.2 ! misho    91823: 
        !          91824:         foreach ($srcinfo['declared_functions'] as $function) {
        !          91825:             $key = "function;$function";
        !          91826:             if ($function{0} == '_' || isset($providesret[$key])) {
        !          91827:                 continue;
1.1       misho    91828:             }
1.1.1.2 ! misho    91829: 
        !          91830:             if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
        !          91831:                 $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
1.1       misho    91832:             }
1.1.1.2 ! misho    91833: 
        !          91834:             $providesret[$key] =
        !          91835:                 array('file'=> $file, 'type' => 'function', 'name' => $function);
1.1       misho    91836:         }
1.1.1.2 ! misho    91837: 
        !          91838:         return $providesret;
1.1       misho    91839:     }
1.1.1.2 ! misho    91840: }<?php
        !          91841: /**
        !          91842:  * PEAR_Packager for generating releases
        !          91843:  *
        !          91844:  * PHP versions 4 and 5
        !          91845:  *
        !          91846:  * @category   pear
        !          91847:  * @package    PEAR
        !          91848:  * @author     Stig Bakken <ssb@php.net>
        !          91849:  * @author     Tomas V. V. Cox <cox@idecnet.com>
        !          91850:  * @author     Greg Beaver <cellog@php.net>
        !          91851:  * @copyright  1997-2009 The Authors
        !          91852:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          91853:  * @version    CVS: $Id: Packager.php 313023 2011-07-06 19:17:11Z dufuz $
        !          91854:  * @link       http://pear.php.net/package/PEAR
        !          91855:  * @since      File available since Release 0.1
        !          91856:  */
1.1       misho    91857: 
1.1.1.2 ! misho    91858: /**
        !          91859:  * base class
        !          91860:  */
        !          91861: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
        !          91862: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile.php';
        !          91863: require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
        !          91864: 
        !          91865: /**
        !          91866:  * Administration class used to make a PEAR release tarball.
        !          91867:  *
        !          91868:  * @category   pear
        !          91869:  * @package    PEAR
        !          91870:  * @author     Greg Beaver <cellog@php.net>
        !          91871:  * @copyright  1997-2009 The Authors
        !          91872:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          91873:  * @version    Release: 1.9.4
        !          91874:  * @link       http://pear.php.net/package/PEAR
        !          91875:  * @since      Class available since Release 0.1
        !          91876:  */
        !          91877: class PEAR_Packager extends PEAR_Common
        !          91878: {
        !          91879:     /**
        !          91880:      * @var PEAR_Registry
        !          91881:      */
        !          91882:     var $_registry;
        !          91883: 
        !          91884:     function package($pkgfile = null, $compress = true, $pkg2 = null)
1.1       misho    91885:     {
1.1.1.2 ! misho    91886:         // {{{ validate supplied package.xml file
        !          91887:         if (empty($pkgfile)) {
        !          91888:             $pkgfile = 'package.xml';
1.1       misho    91889:         }
1.1.1.2 ! misho    91890: 
        !          91891:         PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          91892:         $pkg  = &new PEAR_PackageFile($this->config, $this->debug);
        !          91893:         $pf   = &$pkg->fromPackageFile($pkgfile, PEAR_VALIDATE_NORMAL);
        !          91894:         $main = &$pf;
        !          91895:         PEAR::staticPopErrorHandling();
        !          91896:         if (PEAR::isError($pf)) {
        !          91897:             if (is_array($pf->getUserInfo())) {
        !          91898:                 foreach ($pf->getUserInfo() as $error) {
        !          91899:                     $this->log(0, 'Error: ' . $error['message']);
        !          91900:                 }
1.1       misho    91901:             }
1.1.1.2 ! misho    91902: 
        !          91903:             $this->log(0, $pf->getMessage());
        !          91904:             return $this->raiseError("Cannot package, errors in package file");
1.1       misho    91905:         }
1.1.1.2 ! misho    91906: 
        !          91907:         foreach ($pf->getValidationWarnings() as $warning) {
        !          91908:             $this->log(1, 'Warning: ' . $warning['message']);
1.1       misho    91909:         }
1.1.1.2 ! misho    91910: 
        !          91911:         // }}}
        !          91912:         if ($pkg2) {
        !          91913:             $this->log(0, 'Attempting to process the second package file');
        !          91914:             PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
        !          91915:             $pf2 = &$pkg->fromPackageFile($pkg2, PEAR_VALIDATE_NORMAL);
        !          91916:             PEAR::staticPopErrorHandling();
        !          91917:             if (PEAR::isError($pf2)) {
        !          91918:                 if (is_array($pf2->getUserInfo())) {
        !          91919:                     foreach ($pf2->getUserInfo() as $error) {
        !          91920:                         $this->log(0, 'Error: ' . $error['message']);
        !          91921:                     }
1.1       misho    91922:                 }
1.1.1.2 ! misho    91923:                 $this->log(0, $pf2->getMessage());
        !          91924:                 return $this->raiseError("Cannot package, errors in second package file");
1.1       misho    91925:             }
                   91926: 
1.1.1.2 ! misho    91927:             foreach ($pf2->getValidationWarnings() as $warning) {
        !          91928:                 $this->log(1, 'Warning: ' . $warning['message']);
1.1       misho    91929:             }
1.1.1.2 ! misho    91930: 
        !          91931:             if ($pf2->getPackagexmlVersion() == '2.0' ||
        !          91932:                   $pf2->getPackagexmlVersion() == '2.1'
        !          91933:             ) {
        !          91934:                 $main  = &$pf2;
        !          91935:                 $other = &$pf;
1.1       misho    91936:             } else {
1.1.1.2 ! misho    91937:                 $main  = &$pf;
        !          91938:                 $other = &$pf2;
1.1       misho    91939:             }
1.1.1.2 ! misho    91940: 
        !          91941:             if ($main->getPackagexmlVersion() != '2.0' &&
        !          91942:                   $main->getPackagexmlVersion() != '2.1') {
        !          91943:                 return PEAR::raiseError('Error: cannot package two package.xml version 1.0, can ' .
        !          91944:                     'only package together a package.xml 1.0 and package.xml 2.0');
1.1       misho    91945:             }
1.1.1.2 ! misho    91946: 
        !          91947:             if ($other->getPackagexmlVersion() != '1.0') {
        !          91948:                 return PEAR::raiseError('Error: cannot package two package.xml version 2.0, can ' .
        !          91949:                     'only package together a package.xml 1.0 and package.xml 2.0');
1.1       misho    91950:             }
                   91951:         }
1.1.1.2 ! misho    91952: 
        !          91953:         $main->setLogger($this);
        !          91954:         if (!$main->validate(PEAR_VALIDATE_PACKAGING)) {
        !          91955:             foreach ($main->getValidationWarnings() as $warning) {
        !          91956:                 $this->log(0, 'Error: ' . $warning['message']);
1.1       misho    91957:             }
1.1.1.2 ! misho    91958:             return $this->raiseError("Cannot package, errors in package");
1.1       misho    91959:         }
                   91960: 
1.1.1.2 ! misho    91961:         foreach ($main->getValidationWarnings() as $warning) {
        !          91962:             $this->log(1, 'Warning: ' . $warning['message']);
1.1       misho    91963:         }
                   91964: 
1.1.1.2 ! misho    91965:         if ($pkg2) {
        !          91966:             $other->setLogger($this);
        !          91967:             $a = false;
        !          91968:             if (!$other->validate(PEAR_VALIDATE_NORMAL) || $a = !$main->isEquivalent($other)) {
        !          91969:                 foreach ($other->getValidationWarnings() as $warning) {
        !          91970:                     $this->log(0, 'Error: ' . $warning['message']);
        !          91971:                 }
        !          91972: 
        !          91973:                 foreach ($main->getValidationWarnings() as $warning) {
        !          91974:                     $this->log(0, 'Error: ' . $warning['message']);
        !          91975:                 }
        !          91976: 
        !          91977:                 if ($a) {
        !          91978:                     return $this->raiseError('The two package.xml files are not equivalent!');
        !          91979:                 }
        !          91980: 
        !          91981:                 return $this->raiseError("Cannot package, errors in package");
1.1       misho    91982:             }
1.1.1.2 ! misho    91983: 
        !          91984:             foreach ($other->getValidationWarnings() as $warning) {
        !          91985:                 $this->log(1, 'Warning: ' . $warning['message']);
1.1       misho    91986:             }
1.1.1.2 ! misho    91987: 
        !          91988:             $gen = &$main->getDefaultGenerator();
        !          91989:             $tgzfile = $gen->toTgz2($this, $other, $compress);
        !          91990:             if (PEAR::isError($tgzfile)) {
        !          91991:                 return $tgzfile;
1.1       misho    91992:             }
1.1.1.2 ! misho    91993: 
        !          91994:             $dest_package = basename($tgzfile);
        !          91995:             $pkgdir       = dirname($pkgfile);
        !          91996: 
        !          91997:             // TAR the Package -------------------------------------------
        !          91998:             $this->log(1, "Package $dest_package done");
        !          91999:             if (file_exists("$pkgdir/CVS/Root")) {
        !          92000:                 $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pf->getVersion());
        !          92001:                 $cvstag = "RELEASE_$cvsversion";
        !          92002:                 $this->log(1, 'Tag the released code with "pear cvstag ' .
        !          92003:                     $main->getPackageFile() . '"');
        !          92004:                 $this->log(1, "(or set the CVS tag $cvstag by hand)");
        !          92005:             } elseif (file_exists("$pkgdir/.svn")) {
        !          92006:                 $svnversion = preg_replace('/[^a-z0-9]/i', '.', $pf->getVersion());
        !          92007:                 $svntag = $pf->getName() . "-$svnversion";
        !          92008:                 $this->log(1, 'Tag the released code with "pear svntag ' .
        !          92009:                     $main->getPackageFile() . '"');
        !          92010:                 $this->log(1, "(or set the SVN tag $svntag by hand)");
1.1       misho    92011:             }
1.1.1.2 ! misho    92012:         } else { // this branch is executed for single packagefile packaging
        !          92013:             $gen = &$pf->getDefaultGenerator();
        !          92014:             $tgzfile = $gen->toTgz($this, $compress);
        !          92015:             if (PEAR::isError($tgzfile)) {
        !          92016:                 $this->log(0, $tgzfile->getMessage());
        !          92017:                 return $this->raiseError("Cannot package, errors in package");
        !          92018:             }
        !          92019: 
        !          92020:             $dest_package = basename($tgzfile);
        !          92021:             $pkgdir       = dirname($pkgfile);
        !          92022: 
        !          92023:             // TAR the Package -------------------------------------------
        !          92024:             $this->log(1, "Package $dest_package done");
        !          92025:             if (file_exists("$pkgdir/CVS/Root")) {
        !          92026:                 $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pf->getVersion());
        !          92027:                 $cvstag = "RELEASE_$cvsversion";
        !          92028:                 $this->log(1, "Tag the released code with `pear cvstag $pkgfile'");
        !          92029:                 $this->log(1, "(or set the CVS tag $cvstag by hand)");
        !          92030:             } elseif (file_exists("$pkgdir/.svn")) {
        !          92031:                 $svnversion = preg_replace('/[^a-z0-9]/i', '.', $pf->getVersion());
        !          92032:                 $svntag = $pf->getName() . "-$svnversion";
        !          92033:                 $this->log(1, "Tag the released code with `pear svntag $pkgfile'");
        !          92034:                 $this->log(1, "(or set the SVN tag $svntag by hand)");
1.1       misho    92035:             }
                   92036:         }
1.1.1.2 ! misho    92037: 
        !          92038:         return $dest_package;
1.1       misho    92039:     }
1.1.1.2 ! misho    92040: }<?php
        !          92041: /**
        !          92042:  * PEAR_Registry
        !          92043:  *
        !          92044:  * PHP versions 4 and 5
        !          92045:  *
        !          92046:  * @category   pear
        !          92047:  * @package    PEAR
        !          92048:  * @author     Stig Bakken <ssb@php.net>
        !          92049:  * @author     Tomas V. V. Cox <cox@idecnet.com>
        !          92050:  * @author     Greg Beaver <cellog@php.net>
        !          92051:  * @copyright  1997-2009 The Authors
        !          92052:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          92053:  * @version    CVS: $Id: Registry.php 313023 2011-07-06 19:17:11Z dufuz $
        !          92054:  * @link       http://pear.php.net/package/PEAR
        !          92055:  * @since      File available since Release 0.1
        !          92056:  */
        !          92057: 
        !          92058: /**
        !          92059:  * for PEAR_Error
        !          92060:  */
        !          92061: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
        !          92062: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/DependencyDB.php';
        !          92063: 
        !          92064: define('PEAR_REGISTRY_ERROR_LOCK',         -2);
        !          92065: define('PEAR_REGISTRY_ERROR_FORMAT',       -3);
        !          92066: define('PEAR_REGISTRY_ERROR_FILE',         -4);
        !          92067: define('PEAR_REGISTRY_ERROR_CONFLICT',     -5);
        !          92068: define('PEAR_REGISTRY_ERROR_CHANNEL_FILE', -6);
        !          92069: 
        !          92070: /**
        !          92071:  * Administration class used to maintain the installed package database.
        !          92072:  * @category   pear
        !          92073:  * @package    PEAR
        !          92074:  * @author     Stig Bakken <ssb@php.net>
        !          92075:  * @author     Tomas V. V. Cox <cox@idecnet.com>
        !          92076:  * @author     Greg Beaver <cellog@php.net>
        !          92077:  * @copyright  1997-2009 The Authors
        !          92078:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          92079:  * @version    Release: 1.9.4
        !          92080:  * @link       http://pear.php.net/package/PEAR
        !          92081:  * @since      Class available since Release 1.4.0a1
        !          92082:  */
        !          92083: class PEAR_Registry extends PEAR
        !          92084: {
        !          92085:     /**
        !          92086:      * File containing all channel information.
        !          92087:      * @var string
        !          92088:      */
        !          92089:     var $channels = '';
        !          92090: 
        !          92091:     /** Directory where registry files are stored.
        !          92092:      * @var string
        !          92093:      */
        !          92094:     var $statedir = '';
        !          92095: 
        !          92096:     /** File where the file map is stored
        !          92097:      * @var string
        !          92098:      */
        !          92099:     var $filemap = '';
        !          92100: 
        !          92101:     /** Directory where registry files for channels are stored.
        !          92102:      * @var string
        !          92103:      */
        !          92104:     var $channelsdir = '';
        !          92105: 
        !          92106:     /** Name of file used for locking the registry
        !          92107:      * @var string
        !          92108:      */
        !          92109:     var $lockfile = '';
        !          92110: 
        !          92111:     /** File descriptor used during locking
        !          92112:      * @var resource
        !          92113:      */
        !          92114:     var $lock_fp = null;
        !          92115: 
        !          92116:     /** Mode used during locking
        !          92117:      * @var int
        !          92118:      */
        !          92119:     var $lock_mode = 0; // XXX UNUSED
        !          92120: 
        !          92121:     /** Cache of package information.  Structure:
        !          92122:      * array(
        !          92123:      *   'package' => array('id' => ... ),
        !          92124:      *   ... )
        !          92125:      * @var array
        !          92126:      */
        !          92127:     var $pkginfo_cache = array();
1.1       misho    92128: 
1.1.1.2 ! misho    92129:     /** Cache of file map.  Structure:
        !          92130:      * array( '/path/to/file' => 'package', ... )
        !          92131:      * @var array
        !          92132:      */
        !          92133:     var $filemap_cache = array();
1.1       misho    92134: 
1.1.1.2 ! misho    92135:     /**
        !          92136:      * @var false|PEAR_ChannelFile
        !          92137:      */
        !          92138:     var $_pearChannel;
        !          92139: 
        !          92140:     /**
        !          92141:      * @var false|PEAR_ChannelFile
        !          92142:      */
        !          92143:     var $_peclChannel;
        !          92144: 
        !          92145:     /**
        !          92146:      * @var false|PEAR_ChannelFile
        !          92147:      */
        !          92148:     var $_docChannel;
        !          92149: 
        !          92150:     /**
        !          92151:      * @var PEAR_DependencyDB
        !          92152:      */
        !          92153:     var $_dependencyDB;
        !          92154: 
        !          92155:     /**
        !          92156:      * @var PEAR_Config
        !          92157:      */
        !          92158:     var $_config;
        !          92159: 
        !          92160:     /**
        !          92161:      * PEAR_Registry constructor.
        !          92162:      *
        !          92163:      * @param string (optional) PEAR install directory (for .php files)
        !          92164:      * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PEAR channel, if
        !          92165:      *        default values are not desired.  Only used the very first time a PEAR
        !          92166:      *        repository is initialized
        !          92167:      * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PECL channel, if
        !          92168:      *        default values are not desired.  Only used the very first time a PEAR
        !          92169:      *        repository is initialized
        !          92170:      *
        !          92171:      * @access public
        !          92172:      */
        !          92173:     function PEAR_Registry($pear_install_dir = PEAR_INSTALL_DIR, $pear_channel = false,
        !          92174:                            $pecl_channel = false)
1.1       misho    92175:     {
1.1.1.2 ! misho    92176:         parent::PEAR();
        !          92177:         $this->setInstallDir($pear_install_dir);
        !          92178:         $this->_pearChannel = $pear_channel;
        !          92179:         $this->_peclChannel = $pecl_channel;
        !          92180:         $this->_config      = false;
1.1       misho    92181:     }
                   92182: 
1.1.1.2 ! misho    92183:     function setInstallDir($pear_install_dir = PEAR_INSTALL_DIR)
1.1       misho    92184:     {
1.1.1.2 ! misho    92185:         $ds = DIRECTORY_SEPARATOR;
        !          92186:         $this->install_dir = $pear_install_dir;
        !          92187:         $this->channelsdir = $pear_install_dir.$ds.'.channels';
        !          92188:         $this->statedir    = $pear_install_dir.$ds.'.registry';
        !          92189:         $this->filemap     = $pear_install_dir.$ds.'.filemap';
        !          92190:         $this->lockfile    = $pear_install_dir.$ds.'.lock';
1.1       misho    92191:     }
                   92192: 
1.1.1.2 ! misho    92193:     function hasWriteAccess()
1.1       misho    92194:     {
1.1.1.2 ! misho    92195:         if (!file_exists($this->install_dir)) {
        !          92196:             $dir = $this->install_dir;
        !          92197:             while ($dir && $dir != '.') {
        !          92198:                 $olddir = $dir;
        !          92199:                 $dir    = dirname($dir);
        !          92200:                 if ($dir != '.' && file_exists($dir)) {
        !          92201:                     if (is_writeable($dir)) {
        !          92202:                         return true;
1.1       misho    92203:                     }
                   92204: 
1.1.1.2 ! misho    92205:                     return false;
1.1       misho    92206:                 }
1.1.1.2 ! misho    92207: 
        !          92208:                 if ($dir == $olddir) { // this can happen in safe mode
        !          92209:                     return @is_writable($dir);
1.1       misho    92210:                 }
                   92211:             }
1.1.1.2 ! misho    92212: 
        !          92213:             return false;
1.1       misho    92214:         }
1.1.1.2 ! misho    92215: 
        !          92216:         return is_writeable($this->install_dir);
1.1       misho    92217:     }
                   92218: 
1.1.1.2 ! misho    92219:     function setConfig(&$config, $resetInstallDir = true)
1.1       misho    92220:     {
1.1.1.2 ! misho    92221:         $this->_config = &$config;
        !          92222:         if ($resetInstallDir) {
        !          92223:             $this->setInstallDir($config->get('php_dir'));
1.1       misho    92224:         }
                   92225:     }
                   92226: 
1.1.1.2 ! misho    92227:     function _initializeChannelDirs()
1.1       misho    92228:     {
1.1.1.2 ! misho    92229:         static $running = false;
        !          92230:         if (!$running) {
        !          92231:             $running = true;
        !          92232:             $ds = DIRECTORY_SEPARATOR;
        !          92233:             if (!is_dir($this->channelsdir) ||
        !          92234:                   !file_exists($this->channelsdir . $ds . 'pear.php.net.reg') ||
        !          92235:                   !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') ||
        !          92236:                   !file_exists($this->channelsdir . $ds . 'doc.php.net.reg') ||
        !          92237:                   !file_exists($this->channelsdir . $ds . '__uri.reg')) {
        !          92238:                 if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
        !          92239:                     $pear_channel = $this->_pearChannel;
        !          92240:                     if (!is_a($pear_channel, 'PEAR_ChannelFile') || !$pear_channel->validate()) {
        !          92241:                         if (!class_exists('PEAR_ChannelFile')) {
        !          92242:                             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
        !          92243:                         }
        !          92244: 
        !          92245:                         $pear_channel = new PEAR_ChannelFile;
        !          92246:                         $pear_channel->setAlias('pear');
        !          92247:                         $pear_channel->setServer('pear.php.net');
        !          92248:                         $pear_channel->setSummary('PHP Extension and Application Repository');
        !          92249:                         $pear_channel->setDefaultPEARProtocols();
        !          92250:                         $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/');
        !          92251:                         $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/');
        !          92252:                         $pear_channel->setBaseURL('REST1.3', 'http://pear.php.net/rest/');
        !          92253:                         //$pear_channel->setBaseURL('REST1.4', 'http://pear.php.net/rest/');
        !          92254:                     } else {
        !          92255:                         $pear_channel->setServer('pear.php.net');
        !          92256:                         $pear_channel->setAlias('pear');
1.1       misho    92257:                     }
1.1.1.2 ! misho    92258: 
        !          92259:                     $pear_channel->validate();
        !          92260:                     $this->_addChannel($pear_channel);
1.1       misho    92261:                 }
1.1.1.2 ! misho    92262: 
        !          92263:                 if (!file_exists($this->channelsdir . $ds . 'pecl.php.net.reg')) {
        !          92264:                     $pecl_channel = $this->_peclChannel;
        !          92265:                     if (!is_a($pecl_channel, 'PEAR_ChannelFile') || !$pecl_channel->validate()) {
        !          92266:                         if (!class_exists('PEAR_ChannelFile')) {
        !          92267:                             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
        !          92268:                         }
        !          92269: 
        !          92270:                         $pecl_channel = new PEAR_ChannelFile;
        !          92271:                         $pecl_channel->setAlias('pecl');
        !          92272:                         $pecl_channel->setServer('pecl.php.net');
        !          92273:                         $pecl_channel->setSummary('PHP Extension Community Library');
        !          92274:                         $pecl_channel->setDefaultPEARProtocols();
        !          92275:                         $pecl_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/');
        !          92276:                         $pecl_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/');
        !          92277:                         $pecl_channel->setValidationPackage('PEAR_Validator_PECL', '1.0');
        !          92278:                     } else {
        !          92279:                         $pecl_channel->setServer('pecl.php.net');
        !          92280:                         $pecl_channel->setAlias('pecl');
1.1       misho    92281:                     }
1.1.1.2 ! misho    92282: 
        !          92283:                     $pecl_channel->validate();
        !          92284:                     $this->_addChannel($pecl_channel);
1.1       misho    92285:                 }
1.1.1.2 ! misho    92286: 
        !          92287:                 if (!file_exists($this->channelsdir . $ds . 'doc.php.net.reg')) {
        !          92288:                     $doc_channel = $this->_docChannel;
        !          92289:                     if (!is_a($doc_channel, 'PEAR_ChannelFile') || !$doc_channel->validate()) {
        !          92290:                         if (!class_exists('PEAR_ChannelFile')) {
        !          92291:                             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
        !          92292:                         }
        !          92293: 
        !          92294:                         $doc_channel = new PEAR_ChannelFile;
        !          92295:                         $doc_channel->setAlias('phpdocs');
        !          92296:                         $doc_channel->setServer('doc.php.net');
        !          92297:                         $doc_channel->setSummary('PHP Documentation Team');
        !          92298:                         $doc_channel->setDefaultPEARProtocols();
        !          92299:                         $doc_channel->setBaseURL('REST1.0', 'http://doc.php.net/rest/');
        !          92300:                         $doc_channel->setBaseURL('REST1.1', 'http://doc.php.net/rest/');
        !          92301:                         $doc_channel->setBaseURL('REST1.3', 'http://doc.php.net/rest/');
        !          92302:                     } else {
        !          92303:                         $doc_channel->setServer('doc.php.net');
        !          92304:                         $doc_channel->setAlias('doc');
1.1       misho    92305:                     }
1.1.1.2 ! misho    92306: 
        !          92307:                     $doc_channel->validate();
        !          92308:                     $this->_addChannel($doc_channel);
1.1       misho    92309:                 }
1.1.1.2 ! misho    92310: 
        !          92311:                 if (!file_exists($this->channelsdir . $ds . '__uri.reg')) {
        !          92312:                     if (!class_exists('PEAR_ChannelFile')) {
        !          92313:                         require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
1.1       misho    92314:                     }
1.1.1.2 ! misho    92315: 
        !          92316:                     $private = new PEAR_ChannelFile;
        !          92317:                     $private->setName('__uri');
        !          92318:                     $private->setDefaultPEARProtocols();
        !          92319:                     $private->setBaseURL('REST1.0', '****');
        !          92320:                     $private->setSummary('Pseudo-channel for static packages');
        !          92321:                     $this->_addChannel($private);
1.1       misho    92322:                 }
1.1.1.2 ! misho    92323:                 $this->_rebuildFileMap();
        !          92324:             }
        !          92325: 
        !          92326:             $running = false;
        !          92327:         }
        !          92328:     }
        !          92329: 
        !          92330:     function _initializeDirs()
        !          92331:     {
        !          92332:         $ds = DIRECTORY_SEPARATOR;
        !          92333:         // XXX Compatibility code should be removed in the future
        !          92334:         // rename all registry files if any to lowercase
        !          92335:         if (!OS_WINDOWS && file_exists($this->statedir) && is_dir($this->statedir) &&
        !          92336:               $handle = opendir($this->statedir)) {
        !          92337:             $dest = $this->statedir . $ds;
        !          92338:             while (false !== ($file = readdir($handle))) {
        !          92339:                 if (preg_match('/^.*[A-Z].*\.reg\\z/', $file)) {
        !          92340:                     rename($dest . $file, $dest . strtolower($file));
1.1       misho    92341:                 }
1.1.1.2 ! misho    92342:             }
        !          92343:             closedir($handle);
        !          92344:         }
        !          92345: 
        !          92346:         $this->_initializeChannelDirs();
        !          92347:         if (!file_exists($this->filemap)) {
        !          92348:             $this->_rebuildFileMap();
        !          92349:         }
        !          92350:         $this->_initializeDepDB();
        !          92351:     }
        !          92352: 
        !          92353:     function _initializeDepDB()
        !          92354:     {
        !          92355:         if (!isset($this->_dependencyDB)) {
        !          92356:             static $initializing = false;
        !          92357:             if (!$initializing) {
        !          92358:                 $initializing = true;
        !          92359:                 if (!$this->_config) { // never used?
        !          92360:                     $file = OS_WINDOWS ? 'pear.ini' : '.pearrc';
        !          92361:                     $this->_config = &new PEAR_Config($this->statedir . DIRECTORY_SEPARATOR .
        !          92362:                         $file);
        !          92363:                     $this->_config->setRegistry($this);
        !          92364:                     $this->_config->set('php_dir', $this->install_dir);
1.1       misho    92365:                 }
1.1.1.2 ! misho    92366: 
        !          92367:                 $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config);
        !          92368:                 if (PEAR::isError($this->_dependencyDB)) {
        !          92369:                     // attempt to recover by removing the dep db
        !          92370:                     if (file_exists($this->_config->get('php_dir', null, 'pear.php.net') .
        !          92371:                         DIRECTORY_SEPARATOR . '.depdb')) {
        !          92372:                         @unlink($this->_config->get('php_dir', null, 'pear.php.net') .
        !          92373:                             DIRECTORY_SEPARATOR . '.depdb');
        !          92374:                     }
        !          92375: 
        !          92376:                     $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config);
        !          92377:                     if (PEAR::isError($this->_dependencyDB)) {
        !          92378:                         echo $this->_dependencyDB->getMessage();
        !          92379:                         echo 'Unrecoverable error';
        !          92380:                         exit(1);
1.1       misho    92381:                     }
                   92382:                 }
1.1.1.2 ! misho    92383: 
        !          92384:                 $initializing = false;
1.1       misho    92385:             }
                   92386:         }
1.1.1.2 ! misho    92387:     }
        !          92388: 
        !          92389:     /**
        !          92390:      * PEAR_Registry destructor.  Makes sure no locks are forgotten.
        !          92391:      *
        !          92392:      * @access private
        !          92393:      */
        !          92394:     function _PEAR_Registry()
        !          92395:     {
        !          92396:         parent::_PEAR();
        !          92397:         if (is_resource($this->lock_fp)) {
        !          92398:             $this->_unlock();
1.1       misho    92399:         }
1.1.1.2 ! misho    92400:     }
        !          92401: 
        !          92402:     /**
        !          92403:      * Make sure the directory where we keep registry files exists.
        !          92404:      *
        !          92405:      * @return bool TRUE if directory exists, FALSE if it could not be
        !          92406:      * created
        !          92407:      *
        !          92408:      * @access private
        !          92409:      */
        !          92410:     function _assertStateDir($channel = false)
        !          92411:     {
        !          92412:         if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
        !          92413:             return $this->_assertChannelStateDir($channel);
        !          92414:         }
        !          92415: 
        !          92416:         static $init = false;
        !          92417:         if (!file_exists($this->statedir)) {
        !          92418:             if (!$this->hasWriteAccess()) {
        !          92419:                 return false;
1.1       misho    92420:             }
1.1.1.2 ! misho    92421: 
        !          92422:             require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
        !          92423:             if (!System::mkdir(array('-p', $this->statedir))) {
        !          92424:                 return $this->raiseError("could not create directory '{$this->statedir}'");
        !          92425:             }
        !          92426:             $init = true;
        !          92427:         } elseif (!is_dir($this->statedir)) {
        !          92428:             return $this->raiseError('Cannot create directory ' . $this->statedir . ', ' .
        !          92429:                 'it already exists and is not a directory');
1.1       misho    92430:         }
1.1.1.2 ! misho    92431: 
        !          92432:         $ds = DIRECTORY_SEPARATOR;
        !          92433:         if (!file_exists($this->channelsdir)) {
        !          92434:             if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg') ||
        !          92435:                   !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') ||
        !          92436:                   !file_exists($this->channelsdir . $ds . 'doc.php.net.reg') ||
        !          92437:                   !file_exists($this->channelsdir . $ds . '__uri.reg')) {
        !          92438:                 $init = true;
1.1       misho    92439:             }
1.1.1.2 ! misho    92440:         } elseif (!is_dir($this->channelsdir)) {
        !          92441:             return $this->raiseError('Cannot create directory ' . $this->channelsdir . ', ' .
        !          92442:                 'it already exists and is not a directory');
1.1       misho    92443:         }
1.1.1.2 ! misho    92444: 
        !          92445:         if ($init) {
        !          92446:             static $running = false;
        !          92447:             if (!$running) {
        !          92448:                 $running = true;
        !          92449:                 $this->_initializeDirs();
        !          92450:                 $running = false;
        !          92451:                 $init = false;
1.1       misho    92452:             }
1.1.1.2 ! misho    92453:         } else {
        !          92454:             $this->_initializeDepDB();
1.1       misho    92455:         }
1.1.1.2 ! misho    92456: 
        !          92457:         return true;
1.1       misho    92458:     }
                   92459: 
1.1.1.2 ! misho    92460:     /**
        !          92461:      * Make sure the directory where we keep registry files exists for a non-standard channel.
        !          92462:      *
        !          92463:      * @param string channel name
        !          92464:      * @return bool TRUE if directory exists, FALSE if it could not be
        !          92465:      * created
        !          92466:      *
        !          92467:      * @access private
        !          92468:      */
        !          92469:     function _assertChannelStateDir($channel)
1.1       misho    92470:     {
1.1.1.2 ! misho    92471:         $ds = DIRECTORY_SEPARATOR;
        !          92472:         if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
        !          92473:             if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
        !          92474:                 $this->_initializeChannelDirs();
1.1       misho    92475:             }
1.1.1.2 ! misho    92476:             return $this->_assertStateDir($channel);
        !          92477:         }
        !          92478: 
        !          92479:         $channelDir = $this->_channelDirectoryName($channel);
        !          92480:         if (!is_dir($this->channelsdir) ||
        !          92481:               !file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
        !          92482:             $this->_initializeChannelDirs();
        !          92483:         }
        !          92484: 
        !          92485:         if (!file_exists($channelDir)) {
        !          92486:             if (!$this->hasWriteAccess()) {
        !          92487:                 return false;
1.1       misho    92488:             }
1.1.1.2 ! misho    92489: 
        !          92490:             require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
        !          92491:             if (!System::mkdir(array('-p', $channelDir))) {
        !          92492:                 return $this->raiseError("could not create directory '" . $channelDir .
        !          92493:                     "'");
1.1       misho    92494:             }
1.1.1.2 ! misho    92495:         } elseif (!is_dir($channelDir)) {
        !          92496:             return $this->raiseError("could not create directory '" . $channelDir .
        !          92497:                 "', already exists and is not a directory");
        !          92498:         }
        !          92499: 
        !          92500:         return true;
        !          92501:     }
        !          92502: 
        !          92503:     /**
        !          92504:      * Make sure the directory where we keep registry files for channels exists
        !          92505:      *
        !          92506:      * @return bool TRUE if directory exists, FALSE if it could not be
        !          92507:      * created
        !          92508:      *
        !          92509:      * @access private
        !          92510:      */
        !          92511:     function _assertChannelDir()
        !          92512:     {
        !          92513:         if (!file_exists($this->channelsdir)) {
        !          92514:             if (!$this->hasWriteAccess()) {
        !          92515:                 return false;
1.1       misho    92516:             }
1.1.1.2 ! misho    92517: 
        !          92518:             require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
        !          92519:             if (!System::mkdir(array('-p', $this->channelsdir))) {
        !          92520:                 return $this->raiseError("could not create directory '{$this->channelsdir}'");
1.1       misho    92521:             }
1.1.1.2 ! misho    92522:         } elseif (!is_dir($this->channelsdir)) {
        !          92523:             return $this->raiseError("could not create directory '{$this->channelsdir}" .
        !          92524:                 "', it already exists and is not a directory");
1.1       misho    92525:         }
1.1.1.2 ! misho    92526: 
        !          92527:         if (!file_exists($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) {
        !          92528:             if (!$this->hasWriteAccess()) {
        !          92529:                 return false;
1.1       misho    92530:             }
1.1.1.2 ! misho    92531: 
        !          92532:             require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
        !          92533:             if (!System::mkdir(array('-p', $this->channelsdir . DIRECTORY_SEPARATOR . '.alias'))) {
        !          92534:                 return $this->raiseError("could not create directory '{$this->channelsdir}/.alias'");
1.1       misho    92535:             }
1.1.1.2 ! misho    92536:         } elseif (!is_dir($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) {
        !          92537:             return $this->raiseError("could not create directory '{$this->channelsdir}" .
        !          92538:                 "/.alias', it already exists and is not a directory");
1.1       misho    92539:         }
1.1.1.2 ! misho    92540: 
        !          92541:         return true;
        !          92542:     }
        !          92543: 
        !          92544:     /**
        !          92545:      * Get the name of the file where data for a given package is stored.
        !          92546:      *
        !          92547:      * @param string channel name, or false if this is a PEAR package
        !          92548:      * @param string package name
        !          92549:      *
        !          92550:      * @return string registry file name
        !          92551:      *
        !          92552:      * @access public
        !          92553:      */
        !          92554:     function _packageFileName($package, $channel = false)
        !          92555:     {
        !          92556:         if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
        !          92557:             return $this->_channelDirectoryName($channel) . DIRECTORY_SEPARATOR .
        !          92558:                 strtolower($package) . '.reg';
        !          92559:         }
        !          92560: 
        !          92561:         return $this->statedir . DIRECTORY_SEPARATOR . strtolower($package) . '.reg';
        !          92562:     }
        !          92563: 
        !          92564:     /**
        !          92565:      * Get the name of the file where data for a given channel is stored.
        !          92566:      * @param string channel name
        !          92567:      * @return string registry file name
        !          92568:      */
        !          92569:     function _channelFileName($channel, $noaliases = false)
        !          92570:     {
        !          92571:         if (!$noaliases) {
        !          92572:             if (file_exists($this->_getChannelAliasFileName($channel))) {
        !          92573:                 $channel = implode('', file($this->_getChannelAliasFileName($channel)));
1.1       misho    92574:             }
1.1.1.2 ! misho    92575:         }
        !          92576:         return $this->channelsdir . DIRECTORY_SEPARATOR . str_replace('/', '_',
        !          92577:             strtolower($channel)) . '.reg';
        !          92578:     }
        !          92579: 
        !          92580:     /**
        !          92581:      * @param string
        !          92582:      * @return string
        !          92583:      */
        !          92584:     function _getChannelAliasFileName($alias)
        !          92585:     {
        !          92586:         return $this->channelsdir . DIRECTORY_SEPARATOR . '.alias' .
        !          92587:               DIRECTORY_SEPARATOR . str_replace('/', '_', strtolower($alias)) . '.txt';
        !          92588:     }
        !          92589: 
        !          92590:     /**
        !          92591:      * Get the name of a channel from its alias
        !          92592:      */
        !          92593:     function _getChannelFromAlias($channel)
        !          92594:     {
        !          92595:         if (!$this->_channelExists($channel)) {
        !          92596:             if ($channel == 'pear.php.net') {
        !          92597:                 return 'pear.php.net';
1.1       misho    92598:             }
1.1.1.2 ! misho    92599: 
        !          92600:             if ($channel == 'pecl.php.net') {
        !          92601:                 return 'pecl.php.net';
1.1       misho    92602:             }
1.1.1.2 ! misho    92603: 
        !          92604:             if ($channel == 'doc.php.net') {
        !          92605:                 return 'doc.php.net';
        !          92606:             }
        !          92607: 
        !          92608:             if ($channel == '__uri') {
        !          92609:                 return '__uri';
1.1       misho    92610:             }
1.1.1.2 ! misho    92611: 
        !          92612:             return false;
1.1       misho    92613:         }
1.1.1.2 ! misho    92614: 
        !          92615:         $channel = strtolower($channel);
        !          92616:         if (file_exists($this->_getChannelAliasFileName($channel))) {
        !          92617:             // translate an alias to an actual channel
        !          92618:             return implode('', file($this->_getChannelAliasFileName($channel)));
        !          92619:         }
        !          92620: 
        !          92621:         return $channel;
        !          92622:     }
        !          92623: 
        !          92624:     /**
        !          92625:      * Get the alias of a channel from its alias or its name
        !          92626:      */
        !          92627:     function _getAlias($channel)
        !          92628:     {
        !          92629:         if (!$this->_channelExists($channel)) {
        !          92630:             if ($channel == 'pear.php.net') {
        !          92631:                 return 'pear';
1.1       misho    92632:             }
                   92633: 
1.1.1.2 ! misho    92634:             if ($channel == 'pecl.php.net') {
        !          92635:                 return 'pecl';
        !          92636:             }
        !          92637: 
        !          92638:             if ($channel == 'doc.php.net') {
        !          92639:                 return 'phpdocs';
1.1       misho    92640:             }
1.1.1.2 ! misho    92641: 
        !          92642:             return false;
        !          92643:         }
        !          92644: 
        !          92645:         $channel = $this->_getChannel($channel);
        !          92646:         if (PEAR::isError($channel)) {
        !          92647:             return $channel;
1.1       misho    92648:         }
1.1.1.2 ! misho    92649: 
        !          92650:         return $channel->getAlias();
1.1       misho    92651:     }
                   92652: 
                   92653:     /**
1.1.1.2 ! misho    92654:      * Get the name of the file where data for a given package is stored.
        !          92655:      *
        !          92656:      * @param string channel name, or false if this is a PEAR package
        !          92657:      * @param string package name
        !          92658:      *
        !          92659:      * @return string registry file name
        !          92660:      *
        !          92661:      * @access public
1.1       misho    92662:      */
1.1.1.2 ! misho    92663:     function _channelDirectoryName($channel)
1.1       misho    92664:     {
1.1.1.2 ! misho    92665:         if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
        !          92666:             return $this->statedir;
        !          92667:         }
        !          92668: 
        !          92669:         $ch = $this->_getChannelFromAlias($channel);
        !          92670:         if (!$ch) {
        !          92671:             $ch = $channel;
        !          92672:         }
        !          92673: 
        !          92674:         return $this->statedir . DIRECTORY_SEPARATOR . strtolower('.channel.' .
        !          92675:             str_replace('/', '_', $ch));
1.1       misho    92676:     }
                   92677: 
1.1.1.2 ! misho    92678:     function _openPackageFile($package, $mode, $channel = false)
        !          92679:     {
        !          92680:         if (!$this->_assertStateDir($channel)) {
        !          92681:             return null;
        !          92682:         }
        !          92683: 
        !          92684:         if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) {
        !          92685:             return null;
        !          92686:         }
        !          92687: 
        !          92688:         $file = $this->_packageFileName($package, $channel);
        !          92689:         if (!file_exists($file) && $mode == 'r' || $mode == 'rb') {
        !          92690:             return null;
        !          92691:         }
        !          92692: 
        !          92693:         $fp = @fopen($file, $mode);
        !          92694:         if (!$fp) {
        !          92695:             return null;
        !          92696:         }
1.1       misho    92697: 
1.1.1.2 ! misho    92698:         return $fp;
1.1       misho    92699:     }
                   92700: 
1.1.1.2 ! misho    92701:     function _closePackageFile($fp)
1.1       misho    92702:     {
1.1.1.2 ! misho    92703:         fclose($fp);
1.1       misho    92704:     }
                   92705: 
1.1.1.2 ! misho    92706:     function _openChannelFile($channel, $mode)
1.1       misho    92707:     {
1.1.1.2 ! misho    92708:         if (!$this->_assertChannelDir()) {
        !          92709:             return null;
        !          92710:         }
1.1       misho    92711: 
1.1.1.2 ! misho    92712:         if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) {
        !          92713:             return null;
        !          92714:         }
1.1       misho    92715: 
1.1.1.2 ! misho    92716:         $file = $this->_channelFileName($channel);
        !          92717:         if (!file_exists($file) && $mode == 'r' || $mode == 'rb') {
        !          92718:             return null;
        !          92719:         }
1.1       misho    92720: 
1.1.1.2 ! misho    92721:         $fp = @fopen($file, $mode);
        !          92722:         if (!$fp) {
        !          92723:             return null;
        !          92724:         }
1.1       misho    92725: 
1.1.1.2 ! misho    92726:         return $fp;
1.1       misho    92727:     }
                   92728: 
1.1.1.2 ! misho    92729:     function _closeChannelFile($fp)
1.1       misho    92730:     {
1.1.1.2 ! misho    92731:         fclose($fp);
1.1       misho    92732:     }
                   92733: 
1.1.1.2 ! misho    92734:     function _rebuildFileMap()
1.1       misho    92735:     {
1.1.1.2 ! misho    92736:         if (!class_exists('PEAR_Installer_Role')) {
        !          92737:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Installer/Role.php';
        !          92738:         }
1.1       misho    92739: 
1.1.1.2 ! misho    92740:         $channels = $this->_listAllPackages();
        !          92741:         $files = array();
        !          92742:         foreach ($channels as $channel => $packages) {
        !          92743:             foreach ($packages as $package) {
        !          92744:                 $version = $this->_packageInfo($package, 'version', $channel);
        !          92745:                 $filelist = $this->_packageInfo($package, 'filelist', $channel);
        !          92746:                 if (!is_array($filelist)) {
        !          92747:                     continue;
        !          92748:                 }
1.1       misho    92749: 
1.1.1.2 ! misho    92750:                 foreach ($filelist as $name => $attrs) {
        !          92751:                     if (isset($attrs['attribs'])) {
        !          92752:                         $attrs = $attrs['attribs'];
        !          92753:                     }
1.1       misho    92754: 
1.1.1.2 ! misho    92755:                     // it is possible for conflicting packages in different channels to
        !          92756:                     // conflict with data files/doc files
        !          92757:                     if ($name == 'dirtree') {
        !          92758:                         continue;
        !          92759:                     }
1.1       misho    92760: 
1.1.1.2 ! misho    92761:                     if (isset($attrs['role']) && !in_array($attrs['role'],
        !          92762:                           PEAR_Installer_Role::getInstallableRoles())) {
        !          92763:                         // these are not installed
        !          92764:                         continue;
        !          92765:                     }
1.1       misho    92766: 
1.1.1.2 ! misho    92767:                     if (isset($attrs['role']) && !in_array($attrs['role'],
        !          92768:                           PEAR_Installer_Role::getBaseinstallRoles())) {
        !          92769:                         $attrs['baseinstalldir'] = $package;
        !          92770:                     }
1.1       misho    92771: 
1.1.1.2 ! misho    92772:                     if (isset($attrs['baseinstalldir'])) {
        !          92773:                         $file = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name;
        !          92774:                     } else {
        !          92775:                         $file = $name;
        !          92776:                     }
1.1       misho    92777: 
1.1.1.2 ! misho    92778:                     $file = preg_replace(',^/+,', '', $file);
        !          92779:                     if ($channel != 'pear.php.net') {
        !          92780:                         if (!isset($files[$attrs['role']])) {
        !          92781:                             $files[$attrs['role']] = array();
        !          92782:                         }
        !          92783:                         $files[$attrs['role']][$file] = array(strtolower($channel),
        !          92784:                             strtolower($package));
        !          92785:                     } else {
        !          92786:                         if (!isset($files[$attrs['role']])) {
        !          92787:                             $files[$attrs['role']] = array();
        !          92788:                         }
        !          92789:                         $files[$attrs['role']][$file] = strtolower($package);
        !          92790:                     }
        !          92791:                 }
        !          92792:             }
        !          92793:         }
1.1       misho    92794: 
                   92795: 
1.1.1.2 ! misho    92796:         $this->_assertStateDir();
        !          92797:         if (!$this->hasWriteAccess()) {
        !          92798:             return false;
        !          92799:         }
1.1       misho    92800: 
1.1.1.2 ! misho    92801:         $fp = @fopen($this->filemap, 'wb');
        !          92802:         if (!$fp) {
        !          92803:             return false;
        !          92804:         }
1.1       misho    92805: 
1.1.1.2 ! misho    92806:         $this->filemap_cache = $files;
        !          92807:         fwrite($fp, serialize($files));
        !          92808:         fclose($fp);
        !          92809:         return true;
1.1       misho    92810:     }
                   92811: 
1.1.1.2 ! misho    92812:     function _readFileMap()
1.1       misho    92813:     {
1.1.1.2 ! misho    92814:         if (!file_exists($this->filemap)) {
        !          92815:             return array();
        !          92816:         }
1.1       misho    92817: 
1.1.1.2 ! misho    92818:         $fp = @fopen($this->filemap, 'r');
        !          92819:         if (!$fp) {
        !          92820:             return $this->raiseError('PEAR_Registry: could not open filemap "' . $this->filemap . '"', PEAR_REGISTRY_ERROR_FILE, null, null, $php_errormsg);
        !          92821:         }
1.1       misho    92822: 
1.1.1.2 ! misho    92823:         clearstatcache();
        !          92824:         $rt = get_magic_quotes_runtime();
        !          92825:         set_magic_quotes_runtime(0);
        !          92826:         $fsize = filesize($this->filemap);
        !          92827:         fclose($fp);
        !          92828:         $data = file_get_contents($this->filemap);
        !          92829:         set_magic_quotes_runtime($rt);
        !          92830:         $tmp = unserialize($data);
        !          92831:         if (!$tmp && $fsize > 7) {
        !          92832:             return $this->raiseError('PEAR_Registry: invalid filemap data', PEAR_REGISTRY_ERROR_FORMAT, null, null, $data);
        !          92833:         }
1.1       misho    92834: 
1.1.1.2 ! misho    92835:         $this->filemap_cache = $tmp;
        !          92836:         return true;
1.1       misho    92837:     }
                   92838: 
1.1.1.2 ! misho    92839:     /**
        !          92840:      * Lock the registry.
        !          92841:      *
        !          92842:      * @param integer lock mode, one of LOCK_EX, LOCK_SH or LOCK_UN.
        !          92843:      *                See flock manual for more information.
        !          92844:      *
        !          92845:      * @return bool TRUE on success, FALSE if locking failed, or a
        !          92846:      *              PEAR error if some other error occurs (such as the
        !          92847:      *              lock file not being writable).
        !          92848:      *
        !          92849:      * @access private
        !          92850:      */
        !          92851:     function _lock($mode = LOCK_EX)
1.1       misho    92852:     {
1.1.1.2 ! misho    92853:         if (stristr(php_uname(), 'Windows 9')) {
        !          92854:             return true;
        !          92855:         }
1.1       misho    92856: 
1.1.1.2 ! misho    92857:         if ($mode != LOCK_UN && is_resource($this->lock_fp)) {
        !          92858:             // XXX does not check type of lock (LOCK_SH/LOCK_EX)
        !          92859:             return true;
1.1       misho    92860:         }
1.1.1.2 ! misho    92861: 
        !          92862:         if (!$this->_assertStateDir()) {
        !          92863:             if ($mode == LOCK_EX) {
        !          92864:                 return $this->raiseError('Registry directory is not writeable by the current user');
        !          92865:             }
        !          92866: 
        !          92867:             return true;
1.1       misho    92868:         }
                   92869: 
1.1.1.2 ! misho    92870:         $open_mode = 'w';
        !          92871:         // XXX People reported problems with LOCK_SH and 'w'
        !          92872:         if ($mode === LOCK_SH || $mode === LOCK_UN) {
        !          92873:             if (!file_exists($this->lockfile)) {
        !          92874:                 touch($this->lockfile);
        !          92875:             }
        !          92876:             $open_mode = 'r';
1.1       misho    92877:         }
                   92878: 
1.1.1.2 ! misho    92879:         if (!is_resource($this->lock_fp)) {
        !          92880:             $this->lock_fp = @fopen($this->lockfile, $open_mode);
        !          92881:         }
1.1       misho    92882: 
1.1.1.2 ! misho    92883:         if (!is_resource($this->lock_fp)) {
        !          92884:             $this->lock_fp = null;
        !          92885:             return $this->raiseError("could not create lock file" .
        !          92886:                                      (isset($php_errormsg) ? ": " . $php_errormsg : ""));
        !          92887:         }
1.1       misho    92888: 
1.1.1.2 ! misho    92889:         if (!(int)flock($this->lock_fp, $mode)) {
        !          92890:             switch ($mode) {
        !          92891:                 case LOCK_SH: $str = 'shared';    break;
        !          92892:                 case LOCK_EX: $str = 'exclusive'; break;
        !          92893:                 case LOCK_UN: $str = 'unlock';    break;
        !          92894:                 default:      $str = 'unknown';   break;
        !          92895:             }
1.1       misho    92896: 
1.1.1.2 ! misho    92897:             //is resource at this point, close it on error.
        !          92898:             fclose($this->lock_fp);
        !          92899:             $this->lock_fp = null;
        !          92900:             return $this->raiseError("could not acquire $str lock ($this->lockfile)",
        !          92901:                                      PEAR_REGISTRY_ERROR_LOCK);
        !          92902:         }
1.1       misho    92903: 
1.1.1.2 ! misho    92904:         return true;
1.1       misho    92905:     }
                   92906: 
1.1.1.2 ! misho    92907:     function _unlock()
1.1       misho    92908:     {
1.1.1.2 ! misho    92909:         $ret = $this->_lock(LOCK_UN);
        !          92910:         if (is_resource($this->lock_fp)) {
        !          92911:             fclose($this->lock_fp);
        !          92912:         }
1.1       misho    92913: 
1.1.1.2 ! misho    92914:         $this->lock_fp = null;
        !          92915:         return $ret;
1.1       misho    92916:     }
                   92917: 
1.1.1.2 ! misho    92918:     function _packageExists($package, $channel = false)
1.1       misho    92919:     {
1.1.1.2 ! misho    92920:         return file_exists($this->_packageFileName($package, $channel));
1.1       misho    92921:     }
                   92922: 
1.1.1.2 ! misho    92923:     /**
        !          92924:      * Determine whether a channel exists in the registry
        !          92925:      *
        !          92926:      * @param string Channel name
        !          92927:      * @param bool if true, then aliases will be ignored
        !          92928:      * @return boolean
        !          92929:      */
        !          92930:     function _channelExists($channel, $noaliases = false)
1.1       misho    92931:     {
1.1.1.2 ! misho    92932:         $a = file_exists($this->_channelFileName($channel, $noaliases));
        !          92933:         if (!$a && $channel == 'pear.php.net') {
        !          92934:             return true;
        !          92935:         }
1.1       misho    92936: 
1.1.1.2 ! misho    92937:         if (!$a && $channel == 'pecl.php.net') {
        !          92938:             return true;
        !          92939:         }
1.1       misho    92940: 
1.1.1.2 ! misho    92941:         if (!$a && $channel == 'doc.php.net') {
        !          92942:             return true;
        !          92943:         }
1.1       misho    92944: 
1.1.1.2 ! misho    92945:         return $a;
1.1       misho    92946:     }
                   92947: 
1.1.1.2 ! misho    92948:     /**
        !          92949:      * Determine whether a mirror exists within the deafult channel in the registry
        !          92950:      *
        !          92951:      * @param string Channel name
        !          92952:      * @param string Mirror name
        !          92953:      *
        !          92954:      * @return boolean
        !          92955:      */
        !          92956:     function _mirrorExists($channel, $mirror)
1.1       misho    92957:     {
1.1.1.2 ! misho    92958:         $data = $this->_channelInfo($channel);
        !          92959:         if (!isset($data['servers']['mirror'])) {
        !          92960:             return false;
        !          92961:         }
1.1       misho    92962: 
1.1.1.2 ! misho    92963:         foreach ($data['servers']['mirror'] as $m) {
        !          92964:             if ($m['attribs']['host'] == $mirror) {
        !          92965:                 return true;
        !          92966:             }
        !          92967:         }
1.1       misho    92968: 
1.1.1.2 ! misho    92969:         return false;
1.1       misho    92970:     }
                   92971: 
1.1.1.2 ! misho    92972:     /**
        !          92973:      * @param PEAR_ChannelFile Channel object
        !          92974:      * @param donotuse
        !          92975:      * @param string Last-Modified HTTP tag from remote request
        !          92976:      * @return boolean|PEAR_Error True on creation, false if it already exists
        !          92977:      */
        !          92978:     function _addChannel($channel, $update = false, $lastmodified = false)
1.1       misho    92979:     {
1.1.1.2 ! misho    92980:         if (!is_a($channel, 'PEAR_ChannelFile')) {
        !          92981:             return false;
        !          92982:         }
1.1       misho    92983: 
1.1.1.2 ! misho    92984:         if (!$channel->validate()) {
        !          92985:             return false;
        !          92986:         }
1.1       misho    92987: 
1.1.1.2 ! misho    92988:         if (file_exists($this->_channelFileName($channel->getName()))) {
        !          92989:             if (!$update) {
        !          92990:                 return false;
        !          92991:             }
1.1       misho    92992: 
1.1.1.2 ! misho    92993:             $checker = $this->_getChannel($channel->getName());
        !          92994:             if (PEAR::isError($checker)) {
        !          92995:                 return $checker;
        !          92996:             }
        !          92997: 
        !          92998:             if ($channel->getAlias() != $checker->getAlias()) {
        !          92999:                 if (file_exists($this->_getChannelAliasFileName($checker->getAlias()))) {
        !          93000:                     @unlink($this->_getChannelAliasFileName($checker->getAlias()));
        !          93001:                 }
        !          93002:             }
        !          93003:         } else {
        !          93004:             if ($update && !in_array($channel->getName(), array('pear.php.net', 'pecl.php.net', 'doc.php.net'))) {
        !          93005:                 return false;
        !          93006:             }
        !          93007:         }
1.1       misho    93008: 
1.1.1.2 ! misho    93009:         $ret = $this->_assertChannelDir();
        !          93010:         if (PEAR::isError($ret)) {
        !          93011:             return $ret;
        !          93012:         }
1.1       misho    93013: 
1.1.1.2 ! misho    93014:         $ret = $this->_assertChannelStateDir($channel->getName());
        !          93015:         if (PEAR::isError($ret)) {
        !          93016:             return $ret;
        !          93017:         }
1.1       misho    93018: 
1.1.1.2 ! misho    93019:         if ($channel->getAlias() != $channel->getName()) {
        !          93020:             if (file_exists($this->_getChannelAliasFileName($channel->getAlias())) &&
        !          93021:                   $this->_getChannelFromAlias($channel->getAlias()) != $channel->getName()) {
        !          93022:                 $channel->setAlias($channel->getName());
        !          93023:             }
1.1       misho    93024: 
1.1.1.2 ! misho    93025:             if (!$this->hasWriteAccess()) {
        !          93026:                 return false;
        !          93027:             }
1.1       misho    93028: 
1.1.1.2 ! misho    93029:             $fp = @fopen($this->_getChannelAliasFileName($channel->getAlias()), 'w');
        !          93030:             if (!$fp) {
        !          93031:                 return false;
        !          93032:             }
1.1       misho    93033: 
1.1.1.2 ! misho    93034:             fwrite($fp, $channel->getName());
        !          93035:             fclose($fp);
1.1       misho    93036:         }
1.1.1.2 ! misho    93037: 
        !          93038:         if (!$this->hasWriteAccess()) {
1.1       misho    93039:             return false;
                   93040:         }
1.1.1.2 ! misho    93041: 
        !          93042:         $fp = @fopen($this->_channelFileName($channel->getName()), 'wb');
        !          93043:         if (!$fp) {
1.1       misho    93044:             return false;
                   93045:         }
1.1.1.2 ! misho    93046: 
        !          93047:         $info = $channel->toArray();
        !          93048:         if ($lastmodified) {
        !          93049:             $info['_lastmodified'] = $lastmodified;
        !          93050:         } else {
        !          93051:             $info['_lastmodified'] = date('r');
1.1       misho    93052:         }
1.1.1.2 ! misho    93053: 
        !          93054:         fwrite($fp, serialize($info));
        !          93055:         fclose($fp);
        !          93056:         return true;
        !          93057:     }
        !          93058: 
        !          93059:     /**
        !          93060:      * Deletion fails if there are any packages installed from the channel
        !          93061:      * @param string|PEAR_ChannelFile channel name
        !          93062:      * @return boolean|PEAR_Error True on deletion, false if it doesn't exist
        !          93063:      */
        !          93064:     function _deleteChannel($channel)
        !          93065:     {
        !          93066:         if (!is_string($channel)) {
        !          93067:             if (!is_a($channel, 'PEAR_ChannelFile')) {
        !          93068:                 return false;
1.1       misho    93069:             }
1.1.1.2 ! misho    93070: 
        !          93071:             if (!$channel->validate()) {
1.1       misho    93072:                 return false;
                   93073:             }
1.1.1.2 ! misho    93074:             $channel = $channel->getName();
1.1       misho    93075:         }
                   93076: 
1.1.1.2 ! misho    93077:         if ($this->_getChannelFromAlias($channel) == '__uri') {
1.1       misho    93078:             return false;
                   93079:         }
1.1.1.2 ! misho    93080: 
        !          93081:         if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') {
1.1       misho    93082:             return false;
                   93083:         }
1.1.1.2 ! misho    93084: 
        !          93085:         if ($this->_getChannelFromAlias($channel) == 'doc.php.net') {
1.1       misho    93086:             return false;
                   93087:         }
1.1.1.2 ! misho    93088: 
        !          93089:         if (!$this->_channelExists($channel)) {
        !          93090:             return false;
1.1       misho    93091:         }
                   93092: 
1.1.1.2 ! misho    93093:         if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
1.1       misho    93094:             return false;
                   93095:         }
                   93096: 
1.1.1.2 ! misho    93097:         $channel = $this->_getChannelFromAlias($channel);
        !          93098:         if ($channel == 'pear.php.net') {
        !          93099:             return false;
1.1       misho    93100:         }
                   93101: 
1.1.1.2 ! misho    93102:         $test = $this->_listChannelPackages($channel);
        !          93103:         if (count($test)) {
        !          93104:             return false;
1.1       misho    93105:         }
                   93106: 
1.1.1.2 ! misho    93107:         $test = @rmdir($this->_channelDirectoryName($channel));
        !          93108:         if (!$test) {
        !          93109:             return false;
1.1       misho    93110:         }
                   93111: 
1.1.1.2 ! misho    93112:         $file = $this->_getChannelAliasFileName($this->_getAlias($channel));
        !          93113:         if (file_exists($file)) {
        !          93114:             $test = @unlink($file);
        !          93115:             if (!$test) {
1.1       misho    93116:                 return false;
                   93117:             }
                   93118:         }
                   93119: 
1.1.1.2 ! misho    93120:         $file = $this->_channelFileName($channel);
        !          93121:         $ret = true;
        !          93122:         if (file_exists($file)) {
        !          93123:             $ret = @unlink($file);
1.1       misho    93124:         }
                   93125: 
1.1.1.2 ! misho    93126:         return $ret;
        !          93127:     }
1.1       misho    93128: 
1.1.1.2 ! misho    93129:     /**
        !          93130:      * Determine whether a channel exists in the registry
        !          93131:      * @param string Channel Alias
        !          93132:      * @return boolean
        !          93133:      */
        !          93134:     function _isChannelAlias($alias)
        !          93135:     {
        !          93136:         return file_exists($this->_getChannelAliasFileName($alias));
        !          93137:     }
1.1       misho    93138: 
1.1.1.2 ! misho    93139:     /**
        !          93140:      * @param string|null
        !          93141:      * @param string|null
        !          93142:      * @param string|null
        !          93143:      * @return array|null
        !          93144:      * @access private
        !          93145:      */
        !          93146:     function _packageInfo($package = null, $key = null, $channel = 'pear.php.net')
        !          93147:     {
        !          93148:         if ($package === null) {
        !          93149:             if ($channel === null) {
        !          93150:                 $channels = $this->_listChannels();
        !          93151:                 $ret = array();
        !          93152:                 foreach ($channels as $channel) {
        !          93153:                     $channel = strtolower($channel);
        !          93154:                     $ret[$channel] = array();
        !          93155:                     $packages = $this->_listPackages($channel);
        !          93156:                     foreach ($packages as $package) {
        !          93157:                         $ret[$channel][] = $this->_packageInfo($package, null, $channel);
1.1       misho    93158:                     }
1.1.1.2 ! misho    93159:                 }
1.1       misho    93160: 
1.1.1.2 ! misho    93161:                 return $ret;
        !          93162:             }
1.1       misho    93163: 
1.1.1.2 ! misho    93164:             $ps = $this->_listPackages($channel);
        !          93165:             if (!count($ps)) {
        !          93166:                 return array();
        !          93167:             }
        !          93168:             return array_map(array(&$this, '_packageInfo'),
        !          93169:                              $ps, array_fill(0, count($ps), null),
        !          93170:                              array_fill(0, count($ps), $channel));
        !          93171:         }
1.1       misho    93172: 
1.1.1.2 ! misho    93173:         $fp = $this->_openPackageFile($package, 'r', $channel);
        !          93174:         if ($fp === null) {
        !          93175:             return null;
        !          93176:         }
1.1       misho    93177: 
1.1.1.2 ! misho    93178:         $rt = get_magic_quotes_runtime();
        !          93179:         set_magic_quotes_runtime(0);
        !          93180:         clearstatcache();
        !          93181:         $this->_closePackageFile($fp);
        !          93182:         $data = file_get_contents($this->_packageFileName($package, $channel));
        !          93183:         set_magic_quotes_runtime($rt);
        !          93184:         $data = unserialize($data);
        !          93185:         if ($key === null) {
        !          93186:             return $data;
        !          93187:         }
1.1       misho    93188: 
1.1.1.2 ! misho    93189:         // compatibility for package.xml version 2.0
        !          93190:         if (isset($data['old'][$key])) {
        !          93191:             return $data['old'][$key];
        !          93192:         }
1.1       misho    93193: 
1.1.1.2 ! misho    93194:         if (isset($data[$key])) {
        !          93195:             return $data[$key];
1.1       misho    93196:         }
                   93197: 
1.1.1.2 ! misho    93198:         return null;
1.1       misho    93199:     }
                   93200: 
                   93201:     /**
1.1.1.2 ! misho    93202:      * @param string Channel name
        !          93203:      * @param bool whether to strictly retrieve info of channels, not just aliases
        !          93204:      * @return array|null
1.1       misho    93205:      */
1.1.1.2 ! misho    93206:     function _channelInfo($channel, $noaliases = false)
        !          93207:     {
        !          93208:         if (!$this->_channelExists($channel, $noaliases)) {
        !          93209:             return null;
        !          93210:         }
        !          93211: 
        !          93212:         $fp = $this->_openChannelFile($channel, 'r');
        !          93213:         if ($fp === null) {
        !          93214:             return null;
        !          93215:         }
        !          93216: 
        !          93217:         $rt = get_magic_quotes_runtime();
        !          93218:         set_magic_quotes_runtime(0);
        !          93219:         clearstatcache();
        !          93220:         $this->_closeChannelFile($fp);
        !          93221:         $data = file_get_contents($this->_channelFileName($channel));
        !          93222:         set_magic_quotes_runtime($rt);
        !          93223:         $data = unserialize($data);
        !          93224:         return $data;
        !          93225:     }
        !          93226: 
        !          93227:     function _listChannels()
1.1       misho    93228:     {
1.1.1.2 ! misho    93229:         $channellist = array();
        !          93230:         if (!file_exists($this->channelsdir) || !is_dir($this->channelsdir)) {
        !          93231:             return array('pear.php.net', 'pecl.php.net', 'doc.php.net', '__uri');
1.1       misho    93232:         }
                   93233: 
1.1.1.2 ! misho    93234:         $dp = opendir($this->channelsdir);
        !          93235:         while ($ent = readdir($dp)) {
        !          93236:             if ($ent{0} == '.' || substr($ent, -4) != '.reg') {
1.1       misho    93237:                 continue;
                   93238:             }
                   93239: 
1.1.1.2 ! misho    93240:             if ($ent == '__uri.reg') {
        !          93241:                 $channellist[] = '__uri';
        !          93242:                 continue;
1.1       misho    93243:             }
1.1.1.2 ! misho    93244: 
        !          93245:             $channellist[] = str_replace('_', '/', substr($ent, 0, -4));
1.1       misho    93246:         }
                   93247: 
1.1.1.2 ! misho    93248:         closedir($dp);
        !          93249:         if (!in_array('pear.php.net', $channellist)) {
        !          93250:             $channellist[] = 'pear.php.net';
        !          93251:         }
1.1       misho    93252: 
1.1.1.2 ! misho    93253:         if (!in_array('pecl.php.net', $channellist)) {
        !          93254:             $channellist[] = 'pecl.php.net';
1.1       misho    93255:         }
                   93256: 
1.1.1.2 ! misho    93257:         if (!in_array('doc.php.net', $channellist)) {
        !          93258:             $channellist[] = 'doc.php.net';
        !          93259:         }
1.1       misho    93260: 
                   93261: 
1.1.1.2 ! misho    93262:         if (!in_array('__uri', $channellist)) {
        !          93263:             $channellist[] = '__uri';
1.1       misho    93264:         }
                   93265: 
1.1.1.2 ! misho    93266:         natsort($channellist);
        !          93267:         return $channellist;
1.1       misho    93268:     }
                   93269: 
1.1.1.2 ! misho    93270:     function _listPackages($channel = false)
        !          93271:     {
        !          93272:         if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
        !          93273:             return $this->_listChannelPackages($channel);
        !          93274:         }
1.1       misho    93275: 
1.1.1.2 ! misho    93276:         if (!file_exists($this->statedir) || !is_dir($this->statedir)) {
        !          93277:             return array();
        !          93278:         }
1.1       misho    93279: 
1.1.1.2 ! misho    93280:         $pkglist = array();
        !          93281:         $dp = opendir($this->statedir);
        !          93282:         if (!$dp) {
        !          93283:             return $pkglist;
        !          93284:         }
1.1       misho    93285: 
1.1.1.2 ! misho    93286:         while ($ent = readdir($dp)) {
        !          93287:             if ($ent{0} == '.' || substr($ent, -4) != '.reg') {
        !          93288:                 continue;
        !          93289:             }
1.1       misho    93290: 
1.1.1.2 ! misho    93291:             $pkglist[] = substr($ent, 0, -4);
        !          93292:         }
        !          93293:         closedir($dp);
        !          93294:         return $pkglist;
        !          93295:     }
1.1       misho    93296: 
1.1.1.2 ! misho    93297:     function _listChannelPackages($channel)
        !          93298:     {
        !          93299:         $pkglist = array();
        !          93300:         if (!file_exists($this->_channelDirectoryName($channel)) ||
        !          93301:               !is_dir($this->_channelDirectoryName($channel))) {
        !          93302:             return array();
        !          93303:         }
1.1       misho    93304: 
1.1.1.2 ! misho    93305:         $dp = opendir($this->_channelDirectoryName($channel));
        !          93306:         if (!$dp) {
        !          93307:             return $pkglist;
        !          93308:         }
1.1       misho    93309: 
1.1.1.2 ! misho    93310:         while ($ent = readdir($dp)) {
        !          93311:             if ($ent{0} == '.' || substr($ent, -4) != '.reg') {
        !          93312:                 continue;
        !          93313:             }
        !          93314:             $pkglist[] = substr($ent, 0, -4);
        !          93315:         }
1.1       misho    93316: 
1.1.1.2 ! misho    93317:         closedir($dp);
        !          93318:         return $pkglist;
        !          93319:     }
1.1       misho    93320: 
1.1.1.2 ! misho    93321:     function _listAllPackages()
        !          93322:     {
        !          93323:         $ret = array();
        !          93324:         foreach ($this->_listChannels() as $channel) {
        !          93325:             $ret[$channel] = $this->_listPackages($channel);
        !          93326:         }
1.1       misho    93327: 
1.1.1.2 ! misho    93328:         return $ret;
        !          93329:     }
1.1       misho    93330: 
                   93331:     /**
1.1.1.2 ! misho    93332:      * Add an installed package to the registry
        !          93333:      * @param string package name
        !          93334:      * @param array package info (parsed by PEAR_Common::infoFrom*() methods)
        !          93335:      * @return bool success of saving
        !          93336:      * @access private
1.1       misho    93337:      */
1.1.1.2 ! misho    93338:     function _addPackage($package, $info)
        !          93339:     {
        !          93340:         if ($this->_packageExists($package)) {
        !          93341:             return false;
        !          93342:         }
1.1       misho    93343: 
1.1.1.2 ! misho    93344:         $fp = $this->_openPackageFile($package, 'wb');
        !          93345:         if ($fp === null) {
        !          93346:             return false;
        !          93347:         }
1.1       misho    93348: 
1.1.1.2 ! misho    93349:         $info['_lastmodified'] = time();
        !          93350:         fwrite($fp, serialize($info));
        !          93351:         $this->_closePackageFile($fp);
        !          93352:         if (isset($info['filelist'])) {
        !          93353:             $this->_rebuildFileMap();
        !          93354:         }
1.1       misho    93355: 
1.1.1.2 ! misho    93356:         return true;
        !          93357:     }
1.1       misho    93358: 
                   93359:     /**
1.1.1.2 ! misho    93360:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
        !          93361:      * @return bool
        !          93362:      * @access private
1.1       misho    93363:      */
1.1.1.2 ! misho    93364:     function _addPackage2($info)
1.1       misho    93365:     {
1.1.1.2 ! misho    93366:         if (!is_a($info, 'PEAR_PackageFile_v1') && !is_a($info, 'PEAR_PackageFile_v2')) {
        !          93367:             return false;
        !          93368:         }
1.1       misho    93369: 
1.1.1.2 ! misho    93370:         if (!$info->validate()) {
        !          93371:             if (class_exists('PEAR_Common')) {
        !          93372:                 $ui = PEAR_Frontend::singleton();
        !          93373:                 if ($ui) {
        !          93374:                     foreach ($info->getValidationWarnings() as $err) {
        !          93375:                         $ui->log($err['message'], true);
1.1       misho    93376:                     }
                   93377:                 }
                   93378:             }
                   93379:             return false;
                   93380:         }
                   93381: 
1.1.1.2 ! misho    93382:         $channel = $info->getChannel();
        !          93383:         $package = $info->getPackage();
        !          93384:         $save = $info;
        !          93385:         if ($this->_packageExists($package, $channel)) {
        !          93386:             return false;
1.1       misho    93387:         }
                   93388: 
1.1.1.2 ! misho    93389:         if (!$this->_channelExists($channel, true)) {
        !          93390:             return false;
        !          93391:         }
1.1       misho    93392: 
1.1.1.2 ! misho    93393:         $info = $info->toArray(true);
        !          93394:         if (!$info) {
        !          93395:             return false;
        !          93396:         }
1.1       misho    93397: 
1.1.1.2 ! misho    93398:         $fp = $this->_openPackageFile($package, 'wb', $channel);
        !          93399:         if ($fp === null) {
        !          93400:             return false;
        !          93401:         }
1.1       misho    93402: 
1.1.1.2 ! misho    93403:         $info['_lastmodified'] = time();
        !          93404:         fwrite($fp, serialize($info));
        !          93405:         $this->_closePackageFile($fp);
        !          93406:         $this->_rebuildFileMap();
        !          93407:         return true;
        !          93408:     }
1.1       misho    93409: 
1.1.1.2 ! misho    93410:     /**
        !          93411:      * @param string Package name
        !          93412:      * @param array parsed package.xml 1.0
        !          93413:      * @param bool this parameter is only here for BC.  Don't use it.
        !          93414:      * @access private
        !          93415:      */
        !          93416:     function _updatePackage($package, $info, $merge = true)
        !          93417:     {
        !          93418:         $oldinfo = $this->_packageInfo($package);
        !          93419:         if (empty($oldinfo)) {
        !          93420:             return false;
        !          93421:         }
1.1       misho    93422: 
1.1.1.2 ! misho    93423:         $fp = $this->_openPackageFile($package, 'w');
        !          93424:         if ($fp === null) {
        !          93425:             return false;
        !          93426:         }
1.1       misho    93427: 
1.1.1.2 ! misho    93428:         if (is_object($info)) {
        !          93429:             $info = $info->toArray();
1.1       misho    93430:         }
1.1.1.2 ! misho    93431:         $info['_lastmodified'] = time();
1.1       misho    93432: 
1.1.1.2 ! misho    93433:         $newinfo = $info;
        !          93434:         if ($merge) {
        !          93435:             $info = array_merge($oldinfo, $info);
        !          93436:         } else {
        !          93437:             $diff = $info;
1.1       misho    93438:         }
                   93439: 
1.1.1.2 ! misho    93440:         fwrite($fp, serialize($info));
        !          93441:         $this->_closePackageFile($fp);
        !          93442:         if (isset($newinfo['filelist'])) {
1.1       misho    93443:             $this->_rebuildFileMap();
                   93444:         }
                   93445: 
1.1.1.2 ! misho    93446:         return true;
        !          93447:     }
1.1       misho    93448: 
1.1.1.2 ! misho    93449:     /**
        !          93450:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
        !          93451:      * @return bool
        !          93452:      * @access private
        !          93453:      */
        !          93454:     function _updatePackage2($info)
        !          93455:     {
        !          93456:         if (!$this->_packageExists($info->getPackage(), $info->getChannel())) {
        !          93457:             return false;
        !          93458:         }
1.1       misho    93459: 
1.1.1.2 ! misho    93460:         $fp = $this->_openPackageFile($info->getPackage(), 'w', $info->getChannel());
        !          93461:         if ($fp === null) {
        !          93462:             return false;
1.1       misho    93463:         }
1.1.1.2 ! misho    93464: 
        !          93465:         $save = $info;
        !          93466:         $info = $save->getArray(true);
        !          93467:         $info['_lastmodified'] = time();
        !          93468:         fwrite($fp, serialize($info));
        !          93469:         $this->_closePackageFile($fp);
        !          93470:         $this->_rebuildFileMap();
        !          93471:         return true;
1.1       misho    93472:     }
                   93473: 
                   93474:     /**
1.1.1.2 ! misho    93475:      * @param string Package name
        !          93476:      * @param string Channel name
        !          93477:      * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
1.1       misho    93478:      * @access private
                   93479:      */
1.1.1.2 ! misho    93480:     function &_getPackage($package, $channel = 'pear.php.net')
1.1       misho    93481:     {
1.1.1.2 ! misho    93482:         $info = $this->_packageInfo($package, null, $channel);
        !          93483:         if ($info === null) {
        !          93484:             return $info;
        !          93485:         }
        !          93486: 
        !          93487:         $a = $this->_config;
        !          93488:         if (!$a) {
        !          93489:             $this->_config = &new PEAR_Config;
        !          93490:             $this->_config->set('php_dir', $this->statedir);
        !          93491:         }
        !          93492: 
        !          93493:         if (!class_exists('PEAR_PackageFile')) {
        !          93494:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile.php';
1.1       misho    93495:         }
1.1.1.2 ! misho    93496: 
        !          93497:         $pkg = &new PEAR_PackageFile($this->_config);
        !          93498:         $pf = &$pkg->fromArray($info);
        !          93499:         return $pf;
1.1       misho    93500:     }
                   93501: 
                   93502:     /**
1.1.1.2 ! misho    93503:      * @param string channel name
        !          93504:      * @param bool whether to strictly retrieve channel names
        !          93505:      * @return PEAR_ChannelFile|PEAR_Error
1.1       misho    93506:      * @access private
                   93507:      */
1.1.1.2 ! misho    93508:     function &_getChannel($channel, $noaliases = false)
1.1       misho    93509:     {
1.1.1.2 ! misho    93510:         $ch = false;
        !          93511:         if ($this->_channelExists($channel, $noaliases)) {
        !          93512:             $chinfo = $this->_channelInfo($channel, $noaliases);
        !          93513:             if ($chinfo) {
        !          93514:                 if (!class_exists('PEAR_ChannelFile')) {
        !          93515:                     require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
        !          93516:                 }
        !          93517: 
        !          93518:                 $ch = &PEAR_ChannelFile::fromArrayWithErrors($chinfo);
        !          93519:             }
1.1       misho    93520:         }
                   93521: 
1.1.1.2 ! misho    93522:         if ($ch) {
        !          93523:             if ($ch->validate()) {
        !          93524:                 return $ch;
1.1       misho    93525:             }
                   93526: 
1.1.1.2 ! misho    93527:             foreach ($ch->getErrors(true) as $err) {
        !          93528:                 $message = $err['message'] . "\n";
1.1       misho    93529:             }
1.1.1.2 ! misho    93530: 
        !          93531:             $ch = PEAR::raiseError($message);
        !          93532:             return $ch;
1.1       misho    93533:         }
                   93534: 
1.1.1.2 ! misho    93535:         if ($this->_getChannelFromAlias($channel) == 'pear.php.net') {
        !          93536:             // the registry is not properly set up, so use defaults
        !          93537:             if (!class_exists('PEAR_ChannelFile')) {
        !          93538:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
1.1       misho    93539:             }
1.1.1.2 ! misho    93540: 
        !          93541:             $pear_channel = new PEAR_ChannelFile;
        !          93542:             $pear_channel->setServer('pear.php.net');
        !          93543:             $pear_channel->setAlias('pear');
        !          93544:             $pear_channel->setSummary('PHP Extension and Application Repository');
        !          93545:             $pear_channel->setDefaultPEARProtocols();
        !          93546:             $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/');
        !          93547:             $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/');
        !          93548:             $pear_channel->setBaseURL('REST1.3', 'http://pear.php.net/rest/');
        !          93549:             return $pear_channel;
1.1       misho    93550:         }
                   93551: 
1.1.1.2 ! misho    93552:         if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') {
        !          93553:             // the registry is not properly set up, so use defaults
        !          93554:             if (!class_exists('PEAR_ChannelFile')) {
        !          93555:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
1.1       misho    93556:             }
1.1.1.2 ! misho    93557:             $pear_channel = new PEAR_ChannelFile;
        !          93558:             $pear_channel->setServer('pecl.php.net');
        !          93559:             $pear_channel->setAlias('pecl');
        !          93560:             $pear_channel->setSummary('PHP Extension Community Library');
        !          93561:             $pear_channel->setDefaultPEARProtocols();
        !          93562:             $pear_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/');
        !          93563:             $pear_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/');
        !          93564:             $pear_channel->setValidationPackage('PEAR_Validator_PECL', '1.0');
        !          93565:             return $pear_channel;
1.1       misho    93566:         }
                   93567: 
1.1.1.2 ! misho    93568:         if ($this->_getChannelFromAlias($channel) == 'doc.php.net') {
        !          93569:             // the registry is not properly set up, so use defaults
        !          93570:             if (!class_exists('PEAR_ChannelFile')) {
        !          93571:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
1.1       misho    93572:             }
                   93573: 
1.1.1.2 ! misho    93574:             $doc_channel = new PEAR_ChannelFile;
        !          93575:             $doc_channel->setServer('doc.php.net');
        !          93576:             $doc_channel->setAlias('phpdocs');
        !          93577:             $doc_channel->setSummary('PHP Documentation Team');
        !          93578:             $doc_channel->setDefaultPEARProtocols();
        !          93579:             $doc_channel->setBaseURL('REST1.0', 'http://doc.php.net/rest/');
        !          93580:             $doc_channel->setBaseURL('REST1.1', 'http://doc.php.net/rest/');
        !          93581:             $doc_channel->setBaseURL('REST1.3', 'http://doc.php.net/rest/');
        !          93582:             return $doc_channel;
1.1       misho    93583:         }
                   93584: 
                   93585: 
1.1.1.2 ! misho    93586:         if ($this->_getChannelFromAlias($channel) == '__uri') {
        !          93587:             // the registry is not properly set up, so use defaults
        !          93588:             if (!class_exists('PEAR_ChannelFile')) {
        !          93589:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/ChannelFile.php';
1.1       misho    93590:             }
1.1.1.2 ! misho    93591: 
        !          93592:             $private = new PEAR_ChannelFile;
        !          93593:             $private->setName('__uri');
        !          93594:             $private->setDefaultPEARProtocols();
        !          93595:             $private->setBaseURL('REST1.0', '****');
        !          93596:             $private->setSummary('Pseudo-channel for static packages');
        !          93597:             return $private;
1.1       misho    93598:         }
                   93599: 
1.1.1.2 ! misho    93600:         return $ch;
1.1       misho    93601:     }
                   93602: 
                   93603:     /**
1.1.1.2 ! misho    93604:      * @param string Package name
        !          93605:      * @param string Channel name
        !          93606:      * @return bool
1.1       misho    93607:      */
1.1.1.2 ! misho    93608:     function packageExists($package, $channel = 'pear.php.net')
1.1       misho    93609:     {
1.1.1.2 ! misho    93610:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
        !          93611:             return $e;
1.1       misho    93612:         }
1.1.1.2 ! misho    93613:         $ret = $this->_packageExists($package, $channel);
        !          93614:         $this->_unlock();
        !          93615:         return $ret;
        !          93616:     }
1.1       misho    93617: 
1.1.1.2 ! misho    93618:     // }}}
1.1       misho    93619: 
1.1.1.2 ! misho    93620:     // {{{ channelExists()
1.1       misho    93621: 
1.1.1.2 ! misho    93622:     /**
        !          93623:      * @param string channel name
        !          93624:      * @param bool if true, then aliases will be ignored
        !          93625:      * @return bool
        !          93626:      */
        !          93627:     function channelExists($channel, $noaliases = false)
        !          93628:     {
        !          93629:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
        !          93630:             return $e;
        !          93631:         }
        !          93632:         $ret = $this->_channelExists($channel, $noaliases);
        !          93633:         $this->_unlock();
        !          93634:         return $ret;
1.1       misho    93635:     }
                   93636: 
1.1.1.2 ! misho    93637:     // }}}
        !          93638: 
1.1       misho    93639:     /**
1.1.1.2 ! misho    93640:      * @param string channel name mirror is in
        !          93641:      * @param string mirror name
1.1       misho    93642:      *
1.1.1.2 ! misho    93643:      * @return bool
1.1       misho    93644:      */
1.1.1.2 ! misho    93645:     function mirrorExists($channel, $mirror)
1.1       misho    93646:     {
1.1.1.2 ! misho    93647:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
        !          93648:             return $e;
1.1       misho    93649:         }
                   93650: 
1.1.1.2 ! misho    93651:         $ret = $this->_mirrorExists($channel, $mirror);
        !          93652:         $this->_unlock();
        !          93653:         return $ret;
1.1       misho    93654:     }
                   93655: 
1.1.1.2 ! misho    93656:     // {{{ isAlias()
        !          93657: 
1.1       misho    93658:     /**
1.1.1.2 ! misho    93659:      * Determines whether the parameter is an alias of a channel
        !          93660:      * @param string
        !          93661:      * @return bool
1.1       misho    93662:      */
1.1.1.2 ! misho    93663:     function isAlias($alias)
1.1       misho    93664:     {
1.1.1.2 ! misho    93665:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
        !          93666:             return $e;
1.1       misho    93667:         }
1.1.1.2 ! misho    93668:         $ret = $this->_isChannelAlias($alias);
        !          93669:         $this->_unlock();
        !          93670:         return $ret;
1.1       misho    93671:     }
                   93672: 
1.1.1.2 ! misho    93673:     // }}}
        !          93674:     // {{{ packageInfo()
        !          93675: 
1.1       misho    93676:     /**
1.1.1.2 ! misho    93677:      * @param string|null
        !          93678:      * @param string|null
1.1       misho    93679:      * @param string
1.1.1.2 ! misho    93680:      * @return array|null
1.1       misho    93681:      */
1.1.1.2 ! misho    93682:     function packageInfo($package = null, $key = null, $channel = 'pear.php.net')
1.1       misho    93683:     {
1.1.1.2 ! misho    93684:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
        !          93685:             return $e;
        !          93686:         }
        !          93687:         $ret = $this->_packageInfo($package, $key, $channel);
        !          93688:         $this->_unlock();
        !          93689:         return $ret;
1.1       misho    93690:     }
                   93691: 
1.1.1.2 ! misho    93692:     // }}}
        !          93693:     // {{{ channelInfo()
        !          93694: 
1.1       misho    93695:     /**
1.1.1.2 ! misho    93696:      * Retrieve a raw array of channel data.
        !          93697:      *
        !          93698:      * Do not use this, instead use {@link getChannel()} for normal
        !          93699:      * operations.  Array structure is undefined in this method
        !          93700:      * @param string channel name
        !          93701:      * @param bool whether to strictly retrieve information only on non-aliases
        !          93702:      * @return array|null|PEAR_Error
1.1       misho    93703:      */
1.1.1.2 ! misho    93704:     function channelInfo($channel = null, $noaliases = false)
1.1       misho    93705:     {
1.1.1.2 ! misho    93706:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
        !          93707:             return $e;
1.1       misho    93708:         }
1.1.1.2 ! misho    93709:         $ret = $this->_channelInfo($channel, $noaliases);
        !          93710:         $this->_unlock();
        !          93711:         return $ret;
        !          93712:     }
1.1       misho    93713: 
1.1.1.2 ! misho    93714:     // }}}
1.1       misho    93715: 
1.1.1.2 ! misho    93716:     /**
        !          93717:      * @param string
        !          93718:      */
        !          93719:     function channelName($channel)
        !          93720:     {
        !          93721:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
        !          93722:             return $e;
        !          93723:         }
        !          93724:         $ret = $this->_getChannelFromAlias($channel);
        !          93725:         $this->_unlock();
        !          93726:         return $ret;
1.1       misho    93727:     }
                   93728: 
                   93729:     /**
1.1.1.2 ! misho    93730:      * @param string
1.1       misho    93731:      */
1.1.1.2 ! misho    93732:     function channelAlias($channel)
1.1       misho    93733:     {
1.1.1.2 ! misho    93734:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
        !          93735:             return $e;
        !          93736:         }
        !          93737:         $ret = $this->_getAlias($channel);
        !          93738:         $this->_unlock();
        !          93739:         return $ret;
        !          93740:     }
        !          93741:     // {{{ listPackages()
1.1       misho    93742: 
1.1.1.2 ! misho    93743:     function listPackages($channel = false)
        !          93744:     {
        !          93745:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
        !          93746:             return $e;
        !          93747:         }
        !          93748:         $ret = $this->_listPackages($channel);
        !          93749:         $this->_unlock();
        !          93750:         return $ret;
        !          93751:     }
1.1       misho    93752: 
1.1.1.2 ! misho    93753:     // }}}
        !          93754:     // {{{ listAllPackages()
1.1       misho    93755: 
1.1.1.2 ! misho    93756:     function listAllPackages()
        !          93757:     {
        !          93758:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
        !          93759:             return $e;
1.1       misho    93760:         }
1.1.1.2 ! misho    93761:         $ret = $this->_listAllPackages();
        !          93762:         $this->_unlock();
        !          93763:         return $ret;
        !          93764:     }
1.1       misho    93765: 
1.1.1.2 ! misho    93766:     // }}}
        !          93767:     // {{{ listChannel()
1.1       misho    93768: 
1.1.1.2 ! misho    93769:     function listChannels()
        !          93770:     {
        !          93771:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
        !          93772:             return $e;
        !          93773:         }
        !          93774:         $ret = $this->_listChannels();
        !          93775:         $this->_unlock();
        !          93776:         return $ret;
1.1       misho    93777:     }
                   93778: 
1.1.1.2 ! misho    93779:     // }}}
        !          93780:     // {{{ addPackage()
        !          93781: 
1.1       misho    93782:     /**
1.1.1.2 ! misho    93783:      * Add an installed package to the registry
        !          93784:      * @param string|PEAR_PackageFile_v1|PEAR_PackageFile_v2 package name or object
        !          93785:      *               that will be passed to {@link addPackage2()}
        !          93786:      * @param array package info (parsed by PEAR_Common::infoFrom*() methods)
        !          93787:      * @return bool success of saving
1.1       misho    93788:      */
1.1.1.2 ! misho    93789:     function addPackage($package, $info)
1.1       misho    93790:     {
1.1.1.2 ! misho    93791:         if (is_object($info)) {
        !          93792:             return $this->addPackage2($info);
1.1       misho    93793:         }
1.1.1.2 ! misho    93794:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
        !          93795:             return $e;
1.1       misho    93796:         }
1.1.1.2 ! misho    93797:         $ret = $this->_addPackage($package, $info);
        !          93798:         $this->_unlock();
        !          93799:         if ($ret) {
        !          93800:             if (!class_exists('PEAR_PackageFile_v1')) {
        !          93801:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v1.php';
        !          93802:             }
        !          93803:             $pf = new PEAR_PackageFile_v1;
        !          93804:             $pf->setConfig($this->_config);
        !          93805:             $pf->fromArray($info);
        !          93806:             $this->_dependencyDB->uninstallPackage($pf);
        !          93807:             $this->_dependencyDB->installPackage($pf);
        !          93808:         }
        !          93809:         return $ret;
1.1       misho    93810:     }
                   93811: 
1.1.1.2 ! misho    93812:     // }}}
        !          93813:     // {{{ addPackage2()
        !          93814: 
        !          93815:     function addPackage2($info)
1.1       misho    93816:     {
1.1.1.2 ! misho    93817:         if (!is_object($info)) {
        !          93818:             return $this->addPackage($info['package'], $info);
        !          93819:         }
        !          93820:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
        !          93821:             return $e;
        !          93822:         }
        !          93823:         $ret = $this->_addPackage2($info);
        !          93824:         $this->_unlock();
        !          93825:         if ($ret) {
        !          93826:             $this->_dependencyDB->uninstallPackage($info);
        !          93827:             $this->_dependencyDB->installPackage($info);
1.1       misho    93828:         }
1.1.1.2 ! misho    93829:         return $ret;
        !          93830:     }
1.1       misho    93831: 
1.1.1.2 ! misho    93832:     // }}}
        !          93833:     // {{{ updateChannel()
        !          93834: 
        !          93835:     /**
        !          93836:      * For future expandibility purposes, separate this
        !          93837:      * @param PEAR_ChannelFile
        !          93838:      */
        !          93839:     function updateChannel($channel, $lastmodified = null)
        !          93840:     {
        !          93841:         if ($channel->getName() == '__uri') {
        !          93842:             return false;
1.1       misho    93843:         }
1.1.1.2 ! misho    93844:         return $this->addChannel($channel, $lastmodified, true);
        !          93845:     }
1.1       misho    93846: 
1.1.1.2 ! misho    93847:     // }}}
        !          93848:     // {{{ deleteChannel()
        !          93849: 
        !          93850:     /**
        !          93851:      * Deletion fails if there are any packages installed from the channel
        !          93852:      * @param string|PEAR_ChannelFile channel name
        !          93853:      * @return boolean|PEAR_Error True on deletion, false if it doesn't exist
        !          93854:      */
        !          93855:     function deleteChannel($channel)
        !          93856:     {
        !          93857:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
        !          93858:             return $e;
1.1       misho    93859:         }
                   93860: 
1.1.1.2 ! misho    93861:         $ret = $this->_deleteChannel($channel);
        !          93862:         $this->_unlock();
        !          93863:         if ($ret && is_a($this->_config, 'PEAR_Config')) {
        !          93864:             $this->_config->setChannels($this->listChannels());
1.1       misho    93865:         }
                   93866: 
1.1.1.2 ! misho    93867:         return $ret;
1.1       misho    93868:     }
                   93869: 
1.1.1.2 ! misho    93870:     // }}}
        !          93871:     // {{{ addChannel()
1.1       misho    93872: 
1.1.1.2 ! misho    93873:     /**
        !          93874:      * @param PEAR_ChannelFile Channel object
        !          93875:      * @param string Last-Modified header from HTTP for caching
        !          93876:      * @return boolean|PEAR_Error True on creation, false if it already exists
        !          93877:      */
        !          93878:     function addChannel($channel, $lastmodified = false, $update = false)
1.1       misho    93879:     {
1.1.1.2 ! misho    93880:         if (!is_a($channel, 'PEAR_ChannelFile') || !$channel->validate()) {
        !          93881:             return false;
1.1       misho    93882:         }
                   93883: 
1.1.1.2 ! misho    93884:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
        !          93885:             return $e;
1.1       misho    93886:         }
                   93887: 
1.1.1.2 ! misho    93888:         $ret = $this->_addChannel($channel, $update, $lastmodified);
        !          93889:         $this->_unlock();
        !          93890:         if (!$update && $ret && is_a($this->_config, 'PEAR_Config')) {
        !          93891:             $this->_config->setChannels($this->listChannels());
1.1       misho    93892:         }
                   93893: 
1.1.1.2 ! misho    93894:         return $ret;
1.1       misho    93895:     }
                   93896: 
1.1.1.2 ! misho    93897:     // }}}
        !          93898:     // {{{ deletePackage()
1.1       misho    93899: 
1.1.1.2 ! misho    93900:     function deletePackage($package, $channel = 'pear.php.net')
1.1       misho    93901:     {
1.1.1.2 ! misho    93902:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
        !          93903:             return $e;
1.1       misho    93904:         }
                   93905: 
1.1.1.2 ! misho    93906:         $file = $this->_packageFileName($package, $channel);
        !          93907:         $ret  = file_exists($file) ? @unlink($file) : false;
        !          93908:         $this->_rebuildFileMap();
        !          93909:         $this->_unlock();
        !          93910:         $p = array('channel' => $channel, 'package' => $package);
        !          93911:         $this->_dependencyDB->uninstallPackage($p);
        !          93912:         return $ret;
        !          93913:     }
1.1       misho    93914: 
1.1.1.2 ! misho    93915:     // }}}
        !          93916:     // {{{ updatePackage()
1.1       misho    93917: 
1.1.1.2 ! misho    93918:     function updatePackage($package, $info, $merge = true)
        !          93919:     {
        !          93920:         if (is_object($info)) {
        !          93921:             return $this->updatePackage2($info, $merge);
        !          93922:         }
        !          93923:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
        !          93924:             return $e;
        !          93925:         }
        !          93926:         $ret = $this->_updatePackage($package, $info, $merge);
        !          93927:         $this->_unlock();
        !          93928:         if ($ret) {
        !          93929:             if (!class_exists('PEAR_PackageFile_v1')) {
        !          93930:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v1.php';
        !          93931:             }
        !          93932:             $pf = new PEAR_PackageFile_v1;
        !          93933:             $pf->setConfig($this->_config);
        !          93934:             $pf->fromArray($this->packageInfo($package));
        !          93935:             $this->_dependencyDB->uninstallPackage($pf);
        !          93936:             $this->_dependencyDB->installPackage($pf);
        !          93937:         }
        !          93938:         return $ret;
        !          93939:     }
1.1       misho    93940: 
1.1.1.2 ! misho    93941:     // }}}
        !          93942:     // {{{ updatePackage2()
1.1       misho    93943: 
1.1.1.2 ! misho    93944:     function updatePackage2($info)
        !          93945:     {
1.1       misho    93946: 
1.1.1.2 ! misho    93947:         if (!is_object($info)) {
        !          93948:             return $this->updatePackage($info['package'], $info, $merge);
1.1       misho    93949:         }
                   93950: 
1.1.1.2 ! misho    93951:         if (!$info->validate(PEAR_VALIDATE_DOWNLOADING)) {
1.1       misho    93952:             return false;
                   93953:         }
                   93954: 
1.1.1.2 ! misho    93955:         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
        !          93956:             return $e;
1.1       misho    93957:         }
                   93958: 
1.1.1.2 ! misho    93959:         $ret = $this->_updatePackage2($info);
        !          93960:         $this->_unlock();
        !          93961:         if ($ret) {
        !          93962:             $this->_dependencyDB->uninstallPackage($info);
        !          93963:             $this->_dependencyDB->installPackage($info);
        !          93964:         }
        !          93965: 
        !          93966:         return $ret;
1.1       misho    93967:     }
                   93968: 
1.1.1.2 ! misho    93969:     // }}}
        !          93970:     // {{{ getChannel()
        !          93971:     /**
        !          93972:      * @param string channel name
        !          93973:      * @param bool whether to strictly return raw channels (no aliases)
        !          93974:      * @return PEAR_ChannelFile|PEAR_Error
        !          93975:      */
        !          93976:     function &getChannel($channel, $noaliases = false)
1.1       misho    93977:     {
1.1.1.2 ! misho    93978:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
        !          93979:             return $e;
1.1       misho    93980:         }
1.1.1.2 ! misho    93981:         $ret = &$this->_getChannel($channel, $noaliases);
        !          93982:         $this->_unlock();
        !          93983:         if (!$ret) {
        !          93984:             return PEAR::raiseError('Unknown channel: ' . $channel);
1.1       misho    93985:         }
1.1.1.2 ! misho    93986:         return $ret;
1.1       misho    93987:     }
                   93988: 
1.1.1.2 ! misho    93989:     // }}}
        !          93990:     // {{{ getPackage()
1.1       misho    93991:     /**
1.1.1.2 ! misho    93992:      * @param string package name
        !          93993:      * @param string channel name
        !          93994:      * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
1.1       misho    93995:      */
1.1.1.2 ! misho    93996:     function &getPackage($package, $channel = 'pear.php.net')
1.1       misho    93997:     {
1.1.1.2 ! misho    93998:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
        !          93999:             return $e;
1.1       misho    94000:         }
1.1.1.2 ! misho    94001:         $pf = &$this->_getPackage($package, $channel);
        !          94002:         $this->_unlock();
        !          94003:         return $pf;
        !          94004:     }
1.1       misho    94005: 
1.1.1.2 ! misho    94006:     // }}}
1.1       misho    94007: 
1.1.1.2 ! misho    94008:     /**
        !          94009:      * Get PEAR_PackageFile_v[1/2] objects representing the contents of
        !          94010:      * a dependency group that are installed.
        !          94011:      *
        !          94012:      * This is used at uninstall-time
        !          94013:      * @param array
        !          94014:      * @return array|false
        !          94015:      */
        !          94016:     function getInstalledGroup($group)
        !          94017:     {
        !          94018:         $ret = array();
        !          94019:         if (isset($group['package'])) {
        !          94020:             if (!isset($group['package'][0])) {
        !          94021:                 $group['package'] = array($group['package']);
1.1       misho    94022:             }
1.1.1.2 ! misho    94023:             foreach ($group['package'] as $package) {
        !          94024:                 $depchannel = isset($package['channel']) ? $package['channel'] : '__uri';
        !          94025:                 $p = &$this->getPackage($package['name'], $depchannel);
        !          94026:                 if ($p) {
        !          94027:                     $save = &$p;
        !          94028:                     $ret[] = &$save;
        !          94029:                 }
1.1       misho    94030:             }
                   94031:         }
1.1.1.2 ! misho    94032:         if (isset($group['subpackage'])) {
        !          94033:             if (!isset($group['subpackage'][0])) {
        !          94034:                 $group['subpackage'] = array($group['subpackage']);
        !          94035:             }
        !          94036:             foreach ($group['subpackage'] as $package) {
        !          94037:                 $depchannel = isset($package['channel']) ? $package['channel'] : '__uri';
        !          94038:                 $p = &$this->getPackage($package['name'], $depchannel);
        !          94039:                 if ($p) {
        !          94040:                     $save = &$p;
        !          94041:                     $ret[] = &$save;
        !          94042:                 }
1.1       misho    94043:             }
                   94044:         }
1.1.1.2 ! misho    94045:         if (!count($ret)) {
        !          94046:             return false;
1.1       misho    94047:         }
                   94048:         return $ret;
                   94049:     }
                   94050: 
1.1.1.2 ! misho    94051:     // {{{ getChannelValidator()
        !          94052:     /**
        !          94053:      * @param string channel name
        !          94054:      * @return PEAR_Validate|false
        !          94055:      */
        !          94056:     function &getChannelValidator($channel)
1.1       misho    94057:     {
1.1.1.2 ! misho    94058:         $chan = $this->getChannel($channel);
        !          94059:         if (PEAR::isError($chan)) {
        !          94060:             return $chan;
        !          94061:         }
        !          94062:         $val = $chan->getValidationObject();
        !          94063:         return $val;
1.1       misho    94064:     }
1.1.1.2 ! misho    94065:     // }}}
        !          94066:     // {{{ getChannels()
1.1       misho    94067:     /**
1.1.1.2 ! misho    94068:      * @param string channel name
        !          94069:      * @return array an array of PEAR_ChannelFile objects representing every installed channel
1.1       misho    94070:      */
1.1.1.2 ! misho    94071:     function &getChannels()
1.1       misho    94072:     {
1.1.1.2 ! misho    94073:         $ret = array();
        !          94074:         if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
        !          94075:             return $e;
1.1       misho    94076:         }
1.1.1.2 ! misho    94077:         foreach ($this->_listChannels() as $channel) {
        !          94078:             $e = &$this->_getChannel($channel);
        !          94079:             if (!$e || PEAR::isError($e)) {
        !          94080:                 continue;
        !          94081:             }
        !          94082:             $ret[] = $e;
1.1       misho    94083:         }
1.1.1.2 ! misho    94084:         $this->_unlock();
        !          94085:         return $ret;
1.1       misho    94086:     }
                   94087: 
1.1.1.2 ! misho    94088:     // }}}
        !          94089:     // {{{ checkFileMap()
        !          94090: 
1.1       misho    94091:     /**
1.1.1.2 ! misho    94092:      * Test whether a file or set of files belongs to a package.
1.1       misho    94093:      *
1.1.1.2 ! misho    94094:      * If an array is passed in
        !          94095:      * @param string|array file path, absolute or relative to the pear
        !          94096:      *                     install dir
        !          94097:      * @param string|array name of PEAR package or array('package' => name, 'channel' =>
        !          94098:      *                     channel) of a package that will be ignored
        !          94099:      * @param string API version - 1.1 will exclude any files belonging to a package
        !          94100:      * @param array private recursion variable
        !          94101:      * @return array|false which package and channel the file belongs to, or an empty
        !          94102:      *                     string if the file does not belong to an installed package,
        !          94103:      *                     or belongs to the second parameter's package
1.1       misho    94104:      */
1.1.1.2 ! misho    94105:     function checkFileMap($path, $package = false, $api = '1.0', $attrs = false)
1.1       misho    94106:     {
1.1.1.2 ! misho    94107:         if (is_array($path)) {
        !          94108:             static $notempty;
        !          94109:             if (empty($notempty)) {
        !          94110:                 if (!class_exists('PEAR_Installer_Role')) {
        !          94111:                     require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Installer/Role.php';
        !          94112:                 }
        !          94113:                 $notempty = create_function('$a','return !empty($a);');
        !          94114:             }
        !          94115:             $package = is_array($package) ? array(strtolower($package[0]), strtolower($package[1]))
        !          94116:                 : strtolower($package);
        !          94117:             $pkgs = array();
        !          94118:             foreach ($path as $name => $attrs) {
        !          94119:                 if (is_array($attrs)) {
        !          94120:                     if (isset($attrs['install-as'])) {
        !          94121:                         $name = $attrs['install-as'];
        !          94122:                     }
        !          94123:                     if (!in_array($attrs['role'], PEAR_Installer_Role::getInstallableRoles())) {
        !          94124:                         // these are not installed
        !          94125:                         continue;
        !          94126:                     }
        !          94127:                     if (!in_array($attrs['role'], PEAR_Installer_Role::getBaseinstallRoles())) {
        !          94128:                         $attrs['baseinstalldir'] = is_array($package) ? $package[1] : $package;
        !          94129:                     }
        !          94130:                     if (isset($attrs['baseinstalldir'])) {
        !          94131:                         $name = $attrs['baseinstalldir'] . DIRECTORY_SEPARATOR . $name;
        !          94132:                     }
        !          94133:                 }
        !          94134:                 $pkgs[$name] = $this->checkFileMap($name, $package, $api, $attrs);
        !          94135:                 if (PEAR::isError($pkgs[$name])) {
        !          94136:                     return $pkgs[$name];
        !          94137:                 }
        !          94138:             }
        !          94139:             return array_filter($pkgs, $notempty);
1.1       misho    94140:         }
1.1.1.2 ! misho    94141:         if (empty($this->filemap_cache)) {
        !          94142:             if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
        !          94143:                 return $e;
        !          94144:             }
        !          94145:             $err = $this->_readFileMap();
        !          94146:             $this->_unlock();
        !          94147:             if (PEAR::isError($err)) {
        !          94148:                 return $err;
1.1       misho    94149:             }
                   94150:         }
1.1.1.2 ! misho    94151:         if (!$attrs) {
        !          94152:             $attrs = array('role' => 'php'); // any old call would be for PHP role only
        !          94153:         }
        !          94154:         if (isset($this->filemap_cache[$attrs['role']][$path])) {
        !          94155:             if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) {
        !          94156:                 return false;
        !          94157:             }
        !          94158:             return $this->filemap_cache[$attrs['role']][$path];
        !          94159:         }
        !          94160:         $l = strlen($this->install_dir);
        !          94161:         if (substr($path, 0, $l) == $this->install_dir) {
        !          94162:             $path = preg_replace('!^'.DIRECTORY_SEPARATOR.'+!', '', substr($path, $l));
        !          94163:         }
        !          94164:         if (isset($this->filemap_cache[$attrs['role']][$path])) {
        !          94165:             if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) {
        !          94166:                 return false;
        !          94167:             }
        !          94168:             return $this->filemap_cache[$attrs['role']][$path];
        !          94169:         }
1.1       misho    94170:         return false;
                   94171:     }
                   94172: 
1.1.1.2 ! misho    94173:     // }}}
        !          94174:     // {{{ flush()
1.1       misho    94175:     /**
1.1.1.2 ! misho    94176:      * Force a reload of the filemap
        !          94177:      * @since 1.5.0RC3
1.1       misho    94178:      */
1.1.1.2 ! misho    94179:     function flushFileMap()
1.1       misho    94180:     {
1.1.1.2 ! misho    94181:         $this->filemap_cache = null;
        !          94182:         clearstatcache(); // ensure that the next read gets the full, current filemap
        !          94183:     }
1.1       misho    94184: 
1.1.1.2 ! misho    94185:     // }}}
        !          94186:     // {{{ apiVersion()
        !          94187:     /**
        !          94188:      * Get the expected API version.  Channels API is version 1.1, as it is backwards
        !          94189:      * compatible with 1.0
        !          94190:      * @return string
        !          94191:      */
        !          94192:     function apiVersion()
        !          94193:     {
        !          94194:         return '1.1';
        !          94195:     }
        !          94196:     // }}}
1.1       misho    94197: 
                   94198: 
1.1.1.2 ! misho    94199:     /**
        !          94200:      * Parse a package name, or validate a parsed package name array
        !          94201:      * @param string|array pass in an array of format
        !          94202:      *                     array(
        !          94203:      *                      'package' => 'pname',
        !          94204:      *                     ['channel' => 'channame',]
        !          94205:      *                     ['version' => 'version',]
        !          94206:      *                     ['state' => 'state',]
        !          94207:      *                     ['group' => 'groupname'])
        !          94208:      *                     or a string of format
        !          94209:      *                     [channel://][channame/]pname[-version|-state][/group=groupname]
        !          94210:      * @return array|PEAR_Error
        !          94211:      */
        !          94212:     function parsePackageName($param, $defaultchannel = 'pear.php.net')
        !          94213:     {
        !          94214:         $saveparam = $param;
        !          94215:         if (is_array($param)) {
        !          94216:             // convert to string for error messages
        !          94217:             $saveparam = $this->parsedPackageNameToString($param);
        !          94218:             // process the array
        !          94219:             if (!isset($param['package'])) {
        !          94220:                 return PEAR::raiseError('parsePackageName(): array $param ' .
        !          94221:                     'must contain a valid package name in index "param"',
        !          94222:                     'package', null, null, $param);
1.1       misho    94223:             }
1.1.1.2 ! misho    94224:             if (!isset($param['uri'])) {
        !          94225:                 if (!isset($param['channel'])) {
        !          94226:                     $param['channel'] = $defaultchannel;
1.1       misho    94227:                 }
1.1.1.2 ! misho    94228:             } else {
        !          94229:                 $param['channel'] = '__uri';
1.1       misho    94230:             }
                   94231:         } else {
1.1.1.2 ! misho    94232:             $components = @parse_url((string) $param);
        !          94233:             if (isset($components['scheme'])) {
        !          94234:                 if ($components['scheme'] == 'http') {
        !          94235:                     // uri package
        !          94236:                     $param = array('uri' => $param, 'channel' => '__uri');
        !          94237:                 } elseif($components['scheme'] != 'channel') {
        !          94238:                     return PEAR::raiseError('parsePackageName(): only channel:// uris may ' .
        !          94239:                         'be downloaded, not "' . $param . '"', 'invalid', null, null, $param);
        !          94240:                 }
1.1       misho    94241:             }
1.1.1.2 ! misho    94242:             if (!isset($components['path'])) {
        !          94243:                 return PEAR::raiseError('parsePackageName(): array $param ' .
        !          94244:                     'must contain a valid package name in "' . $param . '"',
        !          94245:                     'package', null, null, $param);
1.1       misho    94246:             }
1.1.1.2 ! misho    94247:             if (isset($components['host'])) {
        !          94248:                 // remove the leading "/"
        !          94249:                 $components['path'] = substr($components['path'], 1);
1.1       misho    94250:             }
1.1.1.2 ! misho    94251:             if (!isset($components['scheme'])) {
        !          94252:                 if (strpos($components['path'], '/') !== false) {
        !          94253:                     if ($components['path']{0} == '/') {
        !          94254:                         return PEAR::raiseError('parsePackageName(): this is not ' .
        !          94255:                             'a package name, it begins with "/" in "' . $param . '"',
        !          94256:                             'invalid', null, null, $param);
        !          94257:                     }
        !          94258:                     $parts = explode('/', $components['path']);
        !          94259:                     $components['host'] = array_shift($parts);
        !          94260:                     if (count($parts) > 1) {
        !          94261:                         $components['path'] = array_pop($parts);
        !          94262:                         $components['host'] .= '/' . implode('/', $parts);
        !          94263:                     } else {
        !          94264:                         $components['path'] = implode('/', $parts);
        !          94265:                     }
        !          94266:                 } else {
        !          94267:                     $components['host'] = $defaultchannel;
        !          94268:                 }
        !          94269:             } else {
        !          94270:                 if (strpos($components['path'], '/')) {
        !          94271:                     $parts = explode('/', $components['path']);
        !          94272:                     $components['path'] = array_pop($parts);
        !          94273:                     $components['host'] .= '/' . implode('/', $parts);
        !          94274:                 }
1.1       misho    94275:             }
                   94276: 
1.1.1.2 ! misho    94277:             if (is_array($param)) {
        !          94278:                 $param['package'] = $components['path'];
        !          94279:             } else {
        !          94280:                 $param = array(
        !          94281:                     'package' => $components['path']
        !          94282:                     );
        !          94283:                 if (isset($components['host'])) {
        !          94284:                     $param['channel'] = $components['host'];
        !          94285:                 }
        !          94286:             }
        !          94287:             if (isset($components['fragment'])) {
        !          94288:                 $param['group'] = $components['fragment'];
        !          94289:             }
        !          94290:             if (isset($components['user'])) {
        !          94291:                 $param['user'] = $components['user'];
        !          94292:             }
        !          94293:             if (isset($components['pass'])) {
        !          94294:                 $param['pass'] = $components['pass'];
        !          94295:             }
        !          94296:             if (isset($components['query'])) {
        !          94297:                 parse_str($components['query'], $param['opts']);
        !          94298:             }
        !          94299:             // check for extension
        !          94300:             $pathinfo = pathinfo($param['package']);
        !          94301:             if (isset($pathinfo['extension']) &&
        !          94302:                   in_array(strtolower($pathinfo['extension']), array('tgz', 'tar'))) {
        !          94303:                 $param['extension'] = $pathinfo['extension'];
        !          94304:                 $param['package'] = substr($pathinfo['basename'], 0,
        !          94305:                     strlen($pathinfo['basename']) - 4);
        !          94306:             }
        !          94307:             // check for version
        !          94308:             if (strpos($param['package'], '-')) {
        !          94309:                 $test = explode('-', $param['package']);
        !          94310:                 if (count($test) != 2) {
        !          94311:                     return PEAR::raiseError('parsePackageName(): only one version/state ' .
        !          94312:                         'delimiter "-" is allowed in "' . $saveparam . '"',
        !          94313:                         'version', null, null, $param);
        !          94314:                 }
        !          94315:                 list($param['package'], $param['version']) = $test;
        !          94316:             }
1.1       misho    94317:         }
1.1.1.2 ! misho    94318:         // validation
        !          94319:         $info = $this->channelExists($param['channel']);
        !          94320:         if (PEAR::isError($info)) {
        !          94321:             return $info;
1.1       misho    94322:         }
1.1.1.2 ! misho    94323:         if (!$info) {
        !          94324:             return PEAR::raiseError('unknown channel "' . $param['channel'] .
        !          94325:                 '" in "' . $saveparam . '"', 'channel', null, null, $param);
1.1       misho    94326:         }
1.1.1.2 ! misho    94327:         $chan = $this->getChannel($param['channel']);
        !          94328:         if (PEAR::isError($chan)) {
        !          94329:             return $chan;
1.1       misho    94330:         }
1.1.1.2 ! misho    94331:         if (!$chan) {
        !          94332:             return PEAR::raiseError("Exception: corrupt registry, could not " .
        !          94333:                 "retrieve channel " . $param['channel'] . " information",
        !          94334:                 'registry', null, null, $param);
        !          94335:         }
        !          94336:         $param['channel'] = $chan->getName();
        !          94337:         $validate = $chan->getValidationObject();
        !          94338:         $vpackage = $chan->getValidationPackage();
        !          94339:         // validate package name
        !          94340:         if (!$validate->validPackageName($param['package'], $vpackage['_content'])) {
        !          94341:             return PEAR::raiseError('parsePackageName(): invalid package name "' .
        !          94342:                 $param['package'] . '" in "' . $saveparam . '"',
        !          94343:                 'package', null, null, $param);
        !          94344:         }
        !          94345:         if (isset($param['group'])) {
        !          94346:             if (!PEAR_Validate::validGroupName($param['group'])) {
        !          94347:                 return PEAR::raiseError('parsePackageName(): dependency group "' . $param['group'] .
        !          94348:                     '" is not a valid group name in "' . $saveparam . '"', 'group', null, null,
        !          94349:                     $param);
1.1       misho    94350:             }
1.1.1.2 ! misho    94351:         }
        !          94352:         if (isset($param['state'])) {
        !          94353:             if (!in_array(strtolower($param['state']), $validate->getValidStates())) {
        !          94354:                 return PEAR::raiseError('parsePackageName(): state "' . $param['state']
        !          94355:                     . '" is not a valid state in "' . $saveparam . '"',
        !          94356:                     'state', null, null, $param);
1.1       misho    94357:             }
                   94358:         }
1.1.1.2 ! misho    94359:         if (isset($param['version'])) {
        !          94360:             if (isset($param['state'])) {
        !          94361:                 return PEAR::raiseError('parsePackageName(): cannot contain both ' .
        !          94362:                     'a version and a stability (state) in "' . $saveparam . '"',
        !          94363:                     'version/state', null, null, $param);
        !          94364:             }
        !          94365:             // check whether version is actually a state
        !          94366:             if (in_array(strtolower($param['version']), $validate->getValidStates())) {
        !          94367:                 $param['state'] = strtolower($param['version']);
        !          94368:                 unset($param['version']);
        !          94369:             } else {
        !          94370:                 if (!$validate->validVersion($param['version'])) {
        !          94371:                     return PEAR::raiseError('parsePackageName(): "' . $param['version'] .
        !          94372:                         '" is neither a valid version nor a valid state in "' .
        !          94373:                         $saveparam . '"', 'version/state', null, null, $param);
        !          94374:                 }
        !          94375:             }
1.1       misho    94376:         }
1.1.1.2 ! misho    94377:         return $param;
        !          94378:     }
1.1       misho    94379: 
1.1.1.2 ! misho    94380:     /**
        !          94381:      * @param array
        !          94382:      * @return string
        !          94383:      */
        !          94384:     function parsedPackageNameToString($parsed, $brief = false)
        !          94385:     {
        !          94386:         if (is_string($parsed)) {
        !          94387:             return $parsed;
1.1       misho    94388:         }
1.1.1.2 ! misho    94389:         if (is_object($parsed)) {
        !          94390:             $p = $parsed;
        !          94391:             $parsed = array(
        !          94392:                 'package' => $p->getPackage(),
        !          94393:                 'channel' => $p->getChannel(),
        !          94394:                 'version' => $p->getVersion(),
        !          94395:             );
1.1       misho    94396:         }
1.1.1.2 ! misho    94397:         if (isset($parsed['uri'])) {
        !          94398:             return $parsed['uri'];
1.1       misho    94399:         }
1.1.1.2 ! misho    94400:         if ($brief) {
        !          94401:             if ($channel = $this->channelAlias($parsed['channel'])) {
        !          94402:                 return $channel . '/' . $parsed['package'];
        !          94403:             }
1.1       misho    94404:         }
1.1.1.2 ! misho    94405:         $upass = '';
        !          94406:         if (isset($parsed['user'])) {
        !          94407:             $upass = $parsed['user'];
        !          94408:             if (isset($parsed['pass'])) {
        !          94409:                 $upass .= ':' . $parsed['pass'];
        !          94410:             }
        !          94411:             $upass = "$upass@";
1.1       misho    94412:         }
1.1.1.2 ! misho    94413:         $ret = 'channel://' . $upass . $parsed['channel'] . '/' . $parsed['package'];
        !          94414:         if (isset($parsed['version']) || isset($parsed['state'])) {
        !          94415:             $ver = isset($parsed['version']) ? $parsed['version'] : '';
        !          94416:             $ver .= isset($parsed['state']) ? $parsed['state'] : '';
        !          94417:             $ret .= '-' . $ver;
1.1       misho    94418:         }
1.1.1.2 ! misho    94419:         if (isset($parsed['extension'])) {
        !          94420:             $ret .= '.' . $parsed['extension'];
1.1       misho    94421:         }
1.1.1.2 ! misho    94422:         if (isset($parsed['opts'])) {
        !          94423:             $ret .= '?';
        !          94424:             foreach ($parsed['opts'] as $name => $value) {
        !          94425:                 $parsed['opts'][$name] = "$name=$value";
1.1       misho    94426:             }
1.1.1.2 ! misho    94427:             $ret .= implode('&', $parsed['opts']);
1.1       misho    94428:         }
1.1.1.2 ! misho    94429:         if (isset($parsed['group'])) {
        !          94430:             $ret .= '#' . $parsed['group'];
1.1       misho    94431:         }
                   94432:         return $ret;
                   94433:     }
1.1.1.2 ! misho    94434: }<?php
        !          94435: /**
        !          94436:  * PEAR_REST
        !          94437:  *
        !          94438:  * PHP versions 4 and 5
        !          94439:  *
        !          94440:  * @category   pear
        !          94441:  * @package    PEAR
        !          94442:  * @author     Greg Beaver <cellog@php.net>
        !          94443:  * @copyright  1997-2009 The Authors
        !          94444:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          94445:  * @version    CVS: $Id: REST.php 313023 2011-07-06 19:17:11Z dufuz $
        !          94446:  * @link       http://pear.php.net/package/PEAR
        !          94447:  * @since      File available since Release 1.4.0a1
        !          94448:  */
1.1       misho    94449: 
1.1.1.2 ! misho    94450: /**
        !          94451:  * For downloading xml files
        !          94452:  */
        !          94453: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
        !          94454: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/XMLParser.php';
        !          94455: 
        !          94456: /**
        !          94457:  * Intelligently retrieve data, following hyperlinks if necessary, and re-directing
        !          94458:  * as well
        !          94459:  * @category   pear
        !          94460:  * @package    PEAR
        !          94461:  * @author     Greg Beaver <cellog@php.net>
        !          94462:  * @copyright  1997-2009 The Authors
        !          94463:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          94464:  * @version    Release: 1.9.4
        !          94465:  * @link       http://pear.php.net/package/PEAR
        !          94466:  * @since      Class available since Release 1.4.0a1
        !          94467:  */
        !          94468: class PEAR_REST
        !          94469: {
        !          94470:     var $config;
        !          94471:     var $_options;
        !          94472: 
        !          94473:     function PEAR_REST(&$config, $options = array())
1.1       misho    94474:     {
1.1.1.2 ! misho    94475:         $this->config   = &$config;
        !          94476:         $this->_options = $options;
1.1       misho    94477:     }
                   94478: 
                   94479:     /**
1.1.1.2 ! misho    94480:      * Retrieve REST data, but always retrieve the local cache if it is available.
        !          94481:      *
        !          94482:      * This is useful for elements that should never change, such as information on a particular
        !          94483:      * release
        !          94484:      * @param string full URL to this resource
        !          94485:      * @param array|false contents of the accept-encoding header
        !          94486:      * @param boolean     if true, xml will be returned as a string, otherwise, xml will be
        !          94487:      *                    parsed using PEAR_XMLParser
        !          94488:      * @return string|array
1.1       misho    94489:      */
1.1.1.2 ! misho    94490:     function retrieveCacheFirst($url, $accept = false, $forcestring = false, $channel = false)
1.1       misho    94491:     {
1.1.1.2 ! misho    94492:         $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
        !          94493:             md5($url) . 'rest.cachefile';
1.1       misho    94494: 
1.1.1.2 ! misho    94495:         if (file_exists($cachefile)) {
        !          94496:             return unserialize(implode('', file($cachefile)));
1.1       misho    94497:         }
                   94498: 
1.1.1.2 ! misho    94499:         return $this->retrieveData($url, $accept, $forcestring, $channel);
1.1       misho    94500:     }
                   94501: 
                   94502:     /**
1.1.1.2 ! misho    94503:      * Retrieve a remote REST resource
        !          94504:      * @param string full URL to this resource
        !          94505:      * @param array|false contents of the accept-encoding header
        !          94506:      * @param boolean     if true, xml will be returned as a string, otherwise, xml will be
        !          94507:      *                    parsed using PEAR_XMLParser
        !          94508:      * @return string|array
1.1       misho    94509:      */
1.1.1.2 ! misho    94510:     function retrieveData($url, $accept = false, $forcestring = false, $channel = false)
1.1       misho    94511:     {
1.1.1.2 ! misho    94512:         $cacheId = $this->getCacheId($url);
        !          94513:         if ($ret = $this->useLocalCache($url, $cacheId)) {
        !          94514:             return $ret;
1.1       misho    94515:         }
                   94516: 
1.1.1.2 ! misho    94517:         $file = $trieddownload = false;
        !          94518:         if (!isset($this->_options['offline'])) {
        !          94519:             $trieddownload = true;
        !          94520:             $file = $this->downloadHttp($url, $cacheId ? $cacheId['lastChange'] : false, $accept, $channel);
1.1       misho    94521:         }
                   94522: 
1.1.1.2 ! misho    94523:         if (PEAR::isError($file)) {
        !          94524:             if ($file->getCode() !== -9276) {
        !          94525:                 return $file;
1.1       misho    94526:             }
                   94527: 
1.1.1.2 ! misho    94528:             $trieddownload = false;
        !          94529:             $file = false; // use local copy if available on socket connect error
1.1       misho    94530:         }
                   94531: 
1.1.1.2 ! misho    94532:         if (!$file) {
        !          94533:             $ret = $this->getCache($url);
        !          94534:             if (!PEAR::isError($ret) && $trieddownload) {
        !          94535:                 // reset the age of the cache if the server says it was unmodified
        !          94536:                 $result = $this->saveCache($url, $ret, null, true, $cacheId);
        !          94537:                 if (PEAR::isError($result)) {
        !          94538:                     return PEAR::raiseError($result->getMessage());
        !          94539:                 }
        !          94540:             }
1.1       misho    94541: 
1.1.1.2 ! misho    94542:             return $ret;
1.1       misho    94543:         }
                   94544: 
1.1.1.2 ! misho    94545:         if (is_array($file)) {
        !          94546:             $headers      = $file[2];
        !          94547:             $lastmodified = $file[1];
        !          94548:             $content      = $file[0];
        !          94549:         } else {
        !          94550:             $headers      = array();
        !          94551:             $lastmodified = false;
        !          94552:             $content      = $file;
1.1       misho    94553:         }
                   94554: 
1.1.1.2 ! misho    94555:         if ($forcestring) {
        !          94556:             $result = $this->saveCache($url, $content, $lastmodified, false, $cacheId);
        !          94557:             if (PEAR::isError($result)) {
        !          94558:                 return PEAR::raiseError($result->getMessage());
        !          94559:             }
1.1       misho    94560: 
1.1.1.2 ! misho    94561:             return $content;
1.1       misho    94562:         }
                   94563: 
1.1.1.2 ! misho    94564:         if (isset($headers['content-type'])) {
        !          94565:             switch ($headers['content-type']) {
        !          94566:                 case 'text/xml' :
        !          94567:                 case 'application/xml' :
        !          94568:                 case 'text/plain' :
        !          94569:                     if ($headers['content-type'] === 'text/plain') {
        !          94570:                         $check = substr($content, 0, 5);
        !          94571:                         if ($check !== '<?xml') {
        !          94572:                             break;
        !          94573:                         }
        !          94574:                     }
        !          94575: 
        !          94576:                     $parser = new PEAR_XMLParser;
        !          94577:                     PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          94578:                     $err = $parser->parse($content);
        !          94579:                     PEAR::popErrorHandling();
        !          94580:                     if (PEAR::isError($err)) {
        !          94581:                         return PEAR::raiseError('Invalid xml downloaded from "' . $url . '": ' .
        !          94582:                             $err->getMessage());
        !          94583:                     }
        !          94584:                     $content = $parser->getData();
        !          94585:                 case 'text/html' :
        !          94586:                 default :
        !          94587:                     // use it as a string
1.1       misho    94588:             }
1.1.1.2 ! misho    94589:         } else {
        !          94590:             // assume XML
        !          94591:             $parser = new PEAR_XMLParser;
        !          94592:             $parser->parse($content);
        !          94593:             $content = $parser->getData();
        !          94594:         }
1.1       misho    94595: 
1.1.1.2 ! misho    94596:         $result = $this->saveCache($url, $content, $lastmodified, false, $cacheId);
        !          94597:         if (PEAR::isError($result)) {
        !          94598:             return PEAR::raiseError($result->getMessage());
1.1       misho    94599:         }
1.1.1.2 ! misho    94600: 
        !          94601:         return $content;
1.1       misho    94602:     }
                   94603: 
1.1.1.2 ! misho    94604:     function useLocalCache($url, $cacheid = null)
1.1       misho    94605:     {
1.1.1.2 ! misho    94606:         if ($cacheid === null) {
        !          94607:             $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
        !          94608:                 md5($url) . 'rest.cacheid';
        !          94609:             if (!file_exists($cacheidfile)) {
        !          94610:                 return false;
        !          94611:             }
1.1       misho    94612: 
1.1.1.2 ! misho    94613:             $cacheid = unserialize(implode('', file($cacheidfile)));
1.1       misho    94614:         }
                   94615: 
1.1.1.2 ! misho    94616:         $cachettl = $this->config->get('cache_ttl');
        !          94617:         // If cache is newer than $cachettl seconds, we use the cache!
        !          94618:         if (time() - $cacheid['age'] < $cachettl) {
        !          94619:             return $this->getCache($url);
1.1       misho    94620:         }
                   94621: 
1.1.1.2 ! misho    94622:         return false;
1.1       misho    94623:     }
                   94624: 
1.1.1.2 ! misho    94625:     function getCacheId($url)
1.1       misho    94626:     {
1.1.1.2 ! misho    94627:         $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
        !          94628:             md5($url) . 'rest.cacheid';
        !          94629: 
        !          94630:         if (!file_exists($cacheidfile)) {
        !          94631:             return false;
1.1       misho    94632:         }
                   94633: 
1.1.1.2 ! misho    94634:         $ret = unserialize(implode('', file($cacheidfile)));
1.1       misho    94635:         return $ret;
                   94636:     }
                   94637: 
1.1.1.2 ! misho    94638:     function getCache($url)
1.1       misho    94639:     {
1.1.1.2 ! misho    94640:         $cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
        !          94641:             md5($url) . 'rest.cachefile';
1.1       misho    94642: 
1.1.1.2 ! misho    94643:         if (!file_exists($cachefile)) {
        !          94644:             return PEAR::raiseError('No cached content available for "' . $url . '"');
1.1       misho    94645:         }
                   94646: 
1.1.1.2 ! misho    94647:         return unserialize(implode('', file($cachefile)));
1.1       misho    94648:     }
                   94649: 
                   94650:     /**
1.1.1.2 ! misho    94651:      * @param string full URL to REST resource
        !          94652:      * @param string original contents of the REST resource
        !          94653:      * @param array  HTTP Last-Modified and ETag headers
        !          94654:      * @param bool   if true, then the cache id file should be regenerated to
        !          94655:      *               trigger a new time-to-live value
1.1       misho    94656:      */
1.1.1.2 ! misho    94657:     function saveCache($url, $contents, $lastmodified, $nochange = false, $cacheid = null)
1.1       misho    94658:     {
1.1.1.2 ! misho    94659:         $cache_dir   = $this->config->get('cache_dir');
        !          94660:         $d           = $cache_dir . DIRECTORY_SEPARATOR . md5($url);
        !          94661:         $cacheidfile = $d . 'rest.cacheid';
        !          94662:         $cachefile   = $d . 'rest.cachefile';
1.1       misho    94663: 
1.1.1.2 ! misho    94664:         if (!is_dir($cache_dir)) {
        !          94665:             if (System::mkdir(array('-p', $cache_dir)) === false) {
        !          94666:               return PEAR::raiseError("The value of config option cache_dir ($cache_dir) is not a directory and attempts to create the directory failed.");
1.1       misho    94667:             }
                   94668:         }
                   94669: 
1.1.1.2 ! misho    94670:         if ($cacheid === null && $nochange) {
        !          94671:             $cacheid = unserialize(implode('', file($cacheidfile)));
1.1       misho    94672:         }
                   94673: 
1.1.1.2 ! misho    94674:         $idData = serialize(array(
        !          94675:             'age'        => time(),
        !          94676:             'lastChange' => ($nochange ? $cacheid['lastChange'] : $lastmodified),
        !          94677:         ));
1.1       misho    94678: 
1.1.1.2 ! misho    94679:         $result = $this->saveCacheFile($cacheidfile, $idData);
        !          94680:         if (PEAR::isError($result)) {
        !          94681:             return $result;
        !          94682:         } elseif ($nochange) {
        !          94683:             return true;
1.1       misho    94684:         }
                   94685: 
1.1.1.2 ! misho    94686:         $result = $this->saveCacheFile($cachefile, serialize($contents));
        !          94687:         if (PEAR::isError($result)) {
        !          94688:             if (file_exists($cacheidfile)) {
        !          94689:               @unlink($cacheidfile);
        !          94690:             }
        !          94691: 
        !          94692:             return $result;
1.1       misho    94693:         }
                   94694: 
                   94695:         return true;
                   94696:     }
                   94697: 
1.1.1.2 ! misho    94698:     function saveCacheFile($file, $contents)
1.1       misho    94699:     {
1.1.1.2 ! misho    94700:         $len = strlen($contents);
1.1       misho    94701: 
1.1.1.2 ! misho    94702:         $cachefile_fp = @fopen($file, 'xb'); // x is the O_CREAT|O_EXCL mode
        !          94703:         if ($cachefile_fp !== false) { // create file
        !          94704:             if (fwrite($cachefile_fp, $contents, $len) < $len) {
        !          94705:                 fclose($cachefile_fp);
        !          94706:                 return PEAR::raiseError("Could not write $file.");
        !          94707:             }
        !          94708:         } else { // update file
        !          94709:             $cachefile_lstat = lstat($file);
        !          94710:             $cachefile_fp = @fopen($file, 'wb');
        !          94711:             if (!$cachefile_fp) {
        !          94712:                 return PEAR::raiseError("Could not open $file for writing.");
        !          94713:             }
1.1       misho    94714: 
1.1.1.2 ! misho    94715:             $cachefile_fstat = fstat($cachefile_fp);
        !          94716:             if (
        !          94717:               $cachefile_lstat['mode'] == $cachefile_fstat['mode'] &&
        !          94718:               $cachefile_lstat['ino']  == $cachefile_fstat['ino'] &&
        !          94719:               $cachefile_lstat['dev']  == $cachefile_fstat['dev'] &&
        !          94720:               $cachefile_fstat['nlink'] === 1
        !          94721:             ) {
        !          94722:                 if (fwrite($cachefile_fp, $contents, $len) < $len) {
        !          94723:                     fclose($cachefile_fp);
        !          94724:                     return PEAR::raiseError("Could not write $file.");
        !          94725:                 }
        !          94726:             } else {
        !          94727:                 fclose($cachefile_fp);
        !          94728:                 $link = function_exists('readlink') ? readlink($file) : $file;
        !          94729:                 return PEAR::raiseError('SECURITY ERROR: Will not write to ' . $file . ' as it is symlinked to ' . $link . ' - Possible symlink attack');
        !          94730:             }
1.1       misho    94731:         }
                   94732: 
1.1.1.2 ! misho    94733:         fclose($cachefile_fp);
1.1       misho    94734:         return true;
                   94735:     }
                   94736: 
                   94737:     /**
1.1.1.2 ! misho    94738:      * Efficiently Download a file through HTTP.  Returns downloaded file as a string in-memory
        !          94739:      * This is best used for small files
        !          94740:      *
        !          94741:      * If an HTTP proxy has been configured (http_proxy PEAR_Config
        !          94742:      * setting), the proxy will be used.
        !          94743:      *
        !          94744:      * @param string  $url       the URL to download
        !          94745:      * @param string  $save_dir  directory to save file in
        !          94746:      * @param false|string|array $lastmodified header values to check against for caching
        !          94747:      *                           use false to return the header values from this download
        !          94748:      * @param false|array $accept Accept headers to send
        !          94749:      * @return string|array  Returns the contents of the downloaded file or a PEAR
        !          94750:      *                       error on failure.  If the error is caused by
        !          94751:      *                       socket-related errors, the error object will
        !          94752:      *                       have the fsockopen error code available through
        !          94753:      *                       getCode().  If caching is requested, then return the header
        !          94754:      *                       values.
        !          94755:      *
        !          94756:      * @access public
1.1       misho    94757:      */
1.1.1.2 ! misho    94758:     function downloadHttp($url, $lastmodified = null, $accept = false, $channel = false)
1.1       misho    94759:     {
1.1.1.2 ! misho    94760:         static $redirect = 0;
        !          94761:         // always reset , so we are clean case of error
        !          94762:         $wasredirect = $redirect;
        !          94763:         $redirect = 0;
        !          94764: 
        !          94765:         $info = parse_url($url);
        !          94766:         if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) {
        !          94767:             return PEAR::raiseError('Cannot download non-http URL "' . $url . '"');
1.1       misho    94768:         }
                   94769: 
1.1.1.2 ! misho    94770:         if (!isset($info['host'])) {
        !          94771:             return PEAR::raiseError('Cannot download from non-URL "' . $url . '"');
1.1       misho    94772:         }
                   94773: 
1.1.1.2 ! misho    94774:         $host   = isset($info['host']) ? $info['host'] : null;
        !          94775:         $port   = isset($info['port']) ? $info['port'] : null;
        !          94776:         $path   = isset($info['path']) ? $info['path'] : null;
        !          94777:         $schema = (isset($info['scheme']) && $info['scheme'] == 'https') ? 'https' : 'http';
1.1       misho    94778: 
1.1.1.2 ! misho    94779:         $proxy_host = $proxy_port = $proxy_user = $proxy_pass = '';
        !          94780:         if ($this->config->get('http_proxy')&&
        !          94781:               $proxy = parse_url($this->config->get('http_proxy'))
        !          94782:         ) {
        !          94783:             $proxy_host = isset($proxy['host']) ? $proxy['host'] : null;
        !          94784:             if ($schema === 'https') {
        !          94785:                 $proxy_host = 'ssl://' . $proxy_host;
        !          94786:             }
1.1       misho    94787: 
1.1.1.2 ! misho    94788:             $proxy_port   = isset($proxy['port']) ? $proxy['port'] : 8080;
        !          94789:             $proxy_user   = isset($proxy['user']) ? urldecode($proxy['user']) : null;
        !          94790:             $proxy_pass   = isset($proxy['pass']) ? urldecode($proxy['pass']) : null;
        !          94791:             $proxy_schema = (isset($proxy['scheme']) && $proxy['scheme'] == 'https') ? 'https' : 'http';
1.1       misho    94792:         }
                   94793: 
1.1.1.2 ! misho    94794:         if (empty($port)) {
        !          94795:             $port = (isset($info['scheme']) && $info['scheme'] == 'https')  ? 443 : 80;
1.1       misho    94796:         }
                   94797: 
1.1.1.2 ! misho    94798:         if (isset($proxy['host'])) {
        !          94799:             $request = "GET $url HTTP/1.1\r\n";
        !          94800:         } else {
        !          94801:             $request = "GET $path HTTP/1.1\r\n";
1.1       misho    94802:         }
                   94803: 
1.1.1.2 ! misho    94804:         $request .= "Host: $host\r\n";
        !          94805:         $ifmodifiedsince = '';
        !          94806:         if (is_array($lastmodified)) {
        !          94807:             if (isset($lastmodified['Last-Modified'])) {
        !          94808:                 $ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n";
1.1       misho    94809:             }
                   94810: 
1.1.1.2 ! misho    94811:             if (isset($lastmodified['ETag'])) {
        !          94812:                 $ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n";
1.1       misho    94813:             }
1.1.1.2 ! misho    94814:         } else {
        !          94815:             $ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : '');
1.1       misho    94816:         }
                   94817: 
1.1.1.2 ! misho    94818:         $request .= $ifmodifiedsince .
        !          94819:             "User-Agent: PEAR/1.9.4/PHP/" . PHP_VERSION . "\r\n";
1.1       misho    94820: 
1.1.1.2 ! misho    94821:         $username = $this->config->get('username', null, $channel);
        !          94822:         $password = $this->config->get('password', null, $channel);
1.1       misho    94823: 
1.1.1.2 ! misho    94824:         if ($username && $password) {
        !          94825:             $tmp = base64_encode("$username:$password");
        !          94826:             $request .= "Authorization: Basic $tmp\r\n";
1.1       misho    94827:         }
                   94828: 
1.1.1.2 ! misho    94829:         if ($proxy_host != '' && $proxy_user != '') {
        !          94830:             $request .= 'Proxy-Authorization: Basic ' .
        !          94831:                 base64_encode($proxy_user . ':' . $proxy_pass) . "\r\n";
        !          94832:         }
1.1       misho    94833: 
1.1.1.2 ! misho    94834:         if ($accept) {
        !          94835:             $request .= 'Accept: ' . implode(', ', $accept) . "\r\n";
1.1       misho    94836:         }
                   94837: 
1.1.1.2 ! misho    94838:         $request .= "Accept-Encoding:\r\n";
        !          94839:         $request .= "Connection: close\r\n";
        !          94840:         $request .= "\r\n";
1.1       misho    94841: 
1.1.1.2 ! misho    94842:         if ($proxy_host != '') {
        !          94843:             $fp = @fsockopen($proxy_host, $proxy_port, $errno, $errstr, 15);
        !          94844:             if (!$fp) {
        !          94845:                 return PEAR::raiseError("Connection to `$proxy_host:$proxy_port' failed: $errstr", -9276);
        !          94846:             }
        !          94847:         } else {
        !          94848:             if ($schema === 'https') {
        !          94849:                 $host = 'ssl://' . $host;
1.1       misho    94850:             }
                   94851: 
1.1.1.2 ! misho    94852:             $fp = @fsockopen($host, $port, $errno, $errstr);
        !          94853:             if (!$fp) {
        !          94854:                 return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno);
        !          94855:             }
1.1       misho    94856:         }
                   94857: 
1.1.1.2 ! misho    94858:         fwrite($fp, $request);
1.1       misho    94859: 
1.1.1.2 ! misho    94860:         $headers = array();
        !          94861:         $reply   = 0;
        !          94862:         while ($line = trim(fgets($fp, 1024))) {
        !          94863:             if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) {
        !          94864:                 $headers[strtolower($matches[1])] = trim($matches[2]);
        !          94865:             } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) {
        !          94866:                 $reply = (int)$matches[1];
        !          94867:                 if ($reply == 304 && ($lastmodified || ($lastmodified === false))) {
        !          94868:                     return false;
        !          94869:                 }
        !          94870: 
        !          94871:                 if (!in_array($reply, array(200, 301, 302, 303, 305, 307))) {
        !          94872:                     return PEAR::raiseError("File $schema://$host:$port$path not valid (received: $line)");
        !          94873:                 }
        !          94874:             }
1.1       misho    94875:         }
                   94876: 
1.1.1.2 ! misho    94877:         if ($reply != 200) {
        !          94878:             if (!isset($headers['location'])) {
        !          94879:                 return PEAR::raiseError("File $schema://$host:$port$path not valid (redirected but no location)");
        !          94880:             }
1.1       misho    94881: 
1.1.1.2 ! misho    94882:             if ($wasredirect > 4) {
        !          94883:                 return PEAR::raiseError("File $schema://$host:$port$path not valid (redirection looped more than 5 times)");
        !          94884:             }
1.1       misho    94885: 
1.1.1.2 ! misho    94886:             $redirect = $wasredirect + 1;
        !          94887:             return $this->downloadHttp($headers['location'], $lastmodified, $accept, $channel);
1.1       misho    94888:         }
                   94889: 
1.1.1.2 ! misho    94890:         $length = isset($headers['content-length']) ? $headers['content-length'] : -1;
1.1       misho    94891: 
1.1.1.2 ! misho    94892:         $data = '';
        !          94893:         while ($chunk = @fread($fp, 8192)) {
        !          94894:             $data .= $chunk;
1.1       misho    94895:         }
1.1.1.2 ! misho    94896:         fclose($fp);
1.1       misho    94897: 
1.1.1.2 ! misho    94898:         if ($lastmodified === false || $lastmodified) {
        !          94899:             if (isset($headers['etag'])) {
        !          94900:                 $lastmodified = array('ETag' => $headers['etag']);
        !          94901:             }
1.1       misho    94902: 
1.1.1.2 ! misho    94903:             if (isset($headers['last-modified'])) {
        !          94904:                 if (is_array($lastmodified)) {
        !          94905:                     $lastmodified['Last-Modified'] = $headers['last-modified'];
        !          94906:                 } else {
        !          94907:                     $lastmodified = $headers['last-modified'];
        !          94908:                 }
        !          94909:             }
1.1       misho    94910: 
1.1.1.2 ! misho    94911:             return array($data, $lastmodified, $headers);
1.1       misho    94912:         }
1.1.1.2 ! misho    94913: 
        !          94914:         return $data;
1.1       misho    94915:     }
1.1.1.2 ! misho    94916: }<?php
        !          94917: /**
        !          94918:  * PEAR_REST_10
        !          94919:  *
        !          94920:  * PHP versions 4 and 5
        !          94921:  *
        !          94922:  * @category   pear
        !          94923:  * @package    PEAR
        !          94924:  * @author     Greg Beaver <cellog@php.net>
        !          94925:  * @copyright  1997-2009 The Authors
        !          94926:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          94927:  * @version    CVS: $Id: 10.php 313023 2011-07-06 19:17:11Z dufuz $
        !          94928:  * @link       http://pear.php.net/package/PEAR
        !          94929:  * @since      File available since Release 1.4.0a12
        !          94930:  */
1.1       misho    94931: 
1.1.1.2 ! misho    94932: /**
        !          94933:  * For downloading REST xml/txt files
        !          94934:  */
        !          94935: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/REST.php';
1.1       misho    94936: 
1.1.1.2 ! misho    94937: /**
        !          94938:  * Implement REST 1.0
        !          94939:  *
        !          94940:  * @category   pear
        !          94941:  * @package    PEAR
        !          94942:  * @author     Greg Beaver <cellog@php.net>
        !          94943:  * @copyright  1997-2009 The Authors
        !          94944:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          94945:  * @version    Release: 1.9.4
        !          94946:  * @link       http://pear.php.net/package/PEAR
        !          94947:  * @since      Class available since Release 1.4.0a12
        !          94948:  */
        !          94949: class PEAR_REST_10
        !          94950: {
1.1       misho    94951:     /**
1.1.1.2 ! misho    94952:      * @var PEAR_REST
1.1       misho    94953:      */
1.1.1.2 ! misho    94954:     var $_rest;
        !          94955:     function PEAR_REST_10($config, $options = array())
1.1       misho    94956:     {
1.1.1.2 ! misho    94957:         $this->_rest = &new PEAR_REST($config, $options);
1.1       misho    94958:     }
                   94959: 
                   94960:     /**
1.1.1.2 ! misho    94961:      * Retrieve information about a remote package to be downloaded from a REST server
1.1       misho    94962:      *
1.1.1.2 ! misho    94963:      * @param string $base The uri to prepend to all REST calls
        !          94964:      * @param array $packageinfo an array of format:
        !          94965:      * <pre>
        !          94966:      *  array(
        !          94967:      *   'package' => 'packagename',
        !          94968:      *   'channel' => 'channelname',
        !          94969:      *  ['state' => 'alpha' (or valid state),]
        !          94970:      *  -or-
        !          94971:      *  ['version' => '1.whatever']
        !          94972:      * </pre>
        !          94973:      * @param string $prefstate Current preferred_state config variable value
        !          94974:      * @param bool $installed the installed version of this package to compare against
        !          94975:      * @return array|false|PEAR_Error see {@link _returnDownloadURL()}
1.1       misho    94976:      */
1.1.1.2 ! misho    94977:     function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false)
1.1       misho    94978:     {
1.1.1.2 ! misho    94979:         $states = $this->betterStates($prefstate, true);
        !          94980:         if (!$states) {
        !          94981:             return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
1.1       misho    94982:         }
                   94983: 
1.1.1.2 ! misho    94984:         $channel  = $packageinfo['channel'];
        !          94985:         $package  = $packageinfo['package'];
        !          94986:         $state    = isset($packageinfo['state'])   ? $packageinfo['state']   : null;
        !          94987:         $version  = isset($packageinfo['version']) ? $packageinfo['version'] : null;
        !          94988:         $restFile = $base . 'r/' . strtolower($package) . '/allreleases.xml';
1.1       misho    94989: 
1.1.1.2 ! misho    94990:         $info = $this->_rest->retrieveData($restFile, false, false, $channel);
        !          94991:         if (PEAR::isError($info)) {
        !          94992:             return PEAR::raiseError('No releases available for package "' .
        !          94993:                 $channel . '/' . $package . '"');
1.1       misho    94994:         }
                   94995: 
1.1.1.2 ! misho    94996:         if (!isset($info['r'])) {
        !          94997:             return false;
1.1       misho    94998:         }
                   94999: 
1.1.1.2 ! misho    95000:         $release = $found = false;
        !          95001:         if (!is_array($info['r']) || !isset($info['r'][0])) {
        !          95002:             $info['r'] = array($info['r']);
1.1       misho    95003:         }
                   95004: 
1.1.1.2 ! misho    95005:         foreach ($info['r'] as $release) {
        !          95006:             if (!isset($this->_rest->_options['force']) && ($installed &&
        !          95007:                   version_compare($release['v'], $installed, '<'))) {
        !          95008:                 continue;
        !          95009:             }
1.1       misho    95010: 
1.1.1.2 ! misho    95011:             if (isset($state)) {
        !          95012:                 // try our preferred state first
        !          95013:                 if ($release['s'] == $state) {
        !          95014:                     $found = true;
        !          95015:                     break;
        !          95016:                 }
        !          95017:                 // see if there is something newer and more stable
        !          95018:                 // bug #7221
        !          95019:                 if (in_array($release['s'], $this->betterStates($state), true)) {
        !          95020:                     $found = true;
        !          95021:                     break;
        !          95022:                 }
        !          95023:             } elseif (isset($version)) {
        !          95024:                 if ($release['v'] == $version) {
        !          95025:                     $found = true;
        !          95026:                     break;
        !          95027:                 }
        !          95028:             } else {
        !          95029:                 if (in_array($release['s'], $states)) {
        !          95030:                     $found = true;
        !          95031:                     break;
        !          95032:                 }
        !          95033:             }
1.1       misho    95034:         }
                   95035: 
1.1.1.2 ! misho    95036:         return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel);
        !          95037:     }
1.1       misho    95038: 
1.1.1.2 ! misho    95039:     function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage,
        !          95040:                                $prefstate = 'stable', $installed = false, $channel = false)
1.1       misho    95041:     {
1.1.1.2 ! misho    95042:         $states = $this->betterStates($prefstate, true);
        !          95043:         if (!$states) {
        !          95044:             return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
1.1       misho    95045:         }
                   95046: 
1.1.1.2 ! misho    95047:         $channel  = $dependency['channel'];
        !          95048:         $package  = $dependency['name'];
        !          95049:         $state    = isset($dependency['state'])   ? $dependency['state']   : null;
        !          95050:         $version  = isset($dependency['version']) ? $dependency['version'] : null;
        !          95051:         $restFile = $base . 'r/' . strtolower($package) . '/allreleases.xml';
1.1       misho    95052: 
1.1.1.2 ! misho    95053:         $info = $this->_rest->retrieveData($restFile, false, false, $channel);
        !          95054:         if (PEAR::isError($info)) {
        !          95055:             return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package']
        !          95056:                 . '" dependency "' . $channel . '/' . $package . '" has no releases');
1.1       misho    95057:         }
                   95058: 
1.1.1.2 ! misho    95059:         if (!is_array($info) || !isset($info['r'])) {
        !          95060:             return false;
        !          95061:         }
1.1       misho    95062: 
1.1.1.2 ! misho    95063:         $exclude = array();
        !          95064:         $min = $max = $recommended = false;
        !          95065:         if ($xsdversion == '1.0') {
        !          95066:             switch ($dependency['rel']) {
        !          95067:                 case 'ge' :
        !          95068:                     $min = $dependency['version'];
        !          95069:                 break;
        !          95070:                 case 'gt' :
        !          95071:                     $min = $dependency['version'];
        !          95072:                     $exclude = array($dependency['version']);
        !          95073:                 break;
        !          95074:                 case 'eq' :
        !          95075:                     $recommended = $dependency['version'];
        !          95076:                 break;
        !          95077:                 case 'lt' :
        !          95078:                     $max = $dependency['version'];
        !          95079:                     $exclude = array($dependency['version']);
        !          95080:                 break;
        !          95081:                 case 'le' :
        !          95082:                     $max = $dependency['version'];
        !          95083:                 break;
        !          95084:                 case 'ne' :
        !          95085:                     $exclude = array($dependency['version']);
        !          95086:                 break;
        !          95087:             }
        !          95088:         } else {
        !          95089:             $min = isset($dependency['min']) ? $dependency['min'] : false;
        !          95090:             $max = isset($dependency['max']) ? $dependency['max'] : false;
        !          95091:             $recommended = isset($dependency['recommended']) ?
        !          95092:                 $dependency['recommended'] : false;
        !          95093:             if (isset($dependency['exclude'])) {
        !          95094:                 if (!isset($dependency['exclude'][0])) {
        !          95095:                     $exclude = array($dependency['exclude']);
        !          95096:                 }
        !          95097:             }
1.1       misho    95098:         }
1.1.1.2 ! misho    95099:         $release = $found = false;
        !          95100:         if (!is_array($info['r']) || !isset($info['r'][0])) {
        !          95101:             $info['r'] = array($info['r']);
1.1       misho    95102:         }
1.1.1.2 ! misho    95103:         foreach ($info['r'] as $release) {
        !          95104:             if (!isset($this->_rest->_options['force']) && ($installed &&
        !          95105:                   version_compare($release['v'], $installed, '<'))) {
        !          95106:                 continue;
        !          95107:             }
        !          95108:             if (in_array($release['v'], $exclude)) { // skip excluded versions
        !          95109:                 continue;
        !          95110:             }
        !          95111:             // allow newer releases to say "I'm OK with the dependent package"
        !          95112:             if ($xsdversion == '2.0' && isset($release['co'])) {
        !          95113:                 if (!is_array($release['co']) || !isset($release['co'][0])) {
        !          95114:                     $release['co'] = array($release['co']);
        !          95115:                 }
        !          95116:                 foreach ($release['co'] as $entry) {
        !          95117:                     if (isset($entry['x']) && !is_array($entry['x'])) {
        !          95118:                         $entry['x'] = array($entry['x']);
        !          95119:                     } elseif (!isset($entry['x'])) {
        !          95120:                         $entry['x'] = array();
        !          95121:                     }
        !          95122:                     if ($entry['c'] == $deppackage['channel'] &&
        !          95123:                           strtolower($entry['p']) == strtolower($deppackage['package']) &&
        !          95124:                           version_compare($deppackage['version'], $entry['min'], '>=') &&
        !          95125:                           version_compare($deppackage['version'], $entry['max'], '<=') &&
        !          95126:                           !in_array($release['v'], $entry['x'])) {
        !          95127:                         $recommended = $release['v'];
        !          95128:                         break;
        !          95129:                     }
        !          95130:                 }
        !          95131:             }
        !          95132:             if ($recommended) {
        !          95133:                 if ($release['v'] != $recommended) { // if we want a specific
        !          95134:                     // version, then skip all others
        !          95135:                     continue;
        !          95136:                 } else {
        !          95137:                     if (!in_array($release['s'], $states)) {
        !          95138:                         // the stability is too low, but we must return the
        !          95139:                         // recommended version if possible
        !          95140:                         return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel);
        !          95141:                     }
        !          95142:                 }
        !          95143:             }
        !          95144:             if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions
        !          95145:                 continue;
        !          95146:             }
        !          95147:             if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions
        !          95148:                 continue;
        !          95149:             }
        !          95150:             if ($installed && version_compare($release['v'], $installed, '<')) {
        !          95151:                 continue;
        !          95152:             }
        !          95153:             if (in_array($release['s'], $states)) { // if in the preferred state...
        !          95154:                 $found = true; // ... then use it
        !          95155:                 break;
        !          95156:             }
1.1       misho    95157:         }
1.1.1.2 ! misho    95158:         return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel);
1.1       misho    95159:     }
                   95160: 
                   95161:     /**
1.1.1.2 ! misho    95162:      * Take raw data and return the array needed for processing a download URL
        !          95163:      *
        !          95164:      * @param string $base REST base uri
        !          95165:      * @param string $package Package name
        !          95166:      * @param array $release an array of format array('v' => version, 's' => state)
        !          95167:      *                       describing the release to download
        !          95168:      * @param array $info list of all releases as defined by allreleases.xml
        !          95169:      * @param bool|null $found determines whether the release was found or this is the next
        !          95170:      *                    best alternative.  If null, then versions were skipped because
        !          95171:      *                    of PHP dependency
        !          95172:      * @return array|PEAR_Error
        !          95173:      * @access private
1.1       misho    95174:      */
1.1.1.2 ! misho    95175:     function _returnDownloadURL($base, $package, $release, $info, $found, $phpversion = false, $channel = false)
1.1       misho    95176:     {
1.1.1.2 ! misho    95177:         if (!$found) {
        !          95178:             $release = $info['r'][0];
1.1       misho    95179:         }
                   95180: 
1.1.1.2 ! misho    95181:         $packageLower = strtolower($package);
        !          95182:         $pinfo = $this->_rest->retrieveCacheFirst($base . 'p/' . $packageLower . '/' .
        !          95183:             'info.xml', false, false, $channel);
        !          95184:         if (PEAR::isError($pinfo)) {
        !          95185:             return PEAR::raiseError('Package "' . $package .
        !          95186:                 '" does not have REST info xml available');
1.1       misho    95187:         }
                   95188: 
1.1.1.2 ! misho    95189:         $releaseinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . $packageLower . '/' .
        !          95190:             $release['v'] . '.xml', false, false, $channel);
        !          95191:         if (PEAR::isError($releaseinfo)) {
        !          95192:             return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] .
        !          95193:                 '" does not have REST xml available');
1.1       misho    95194:         }
                   95195: 
1.1.1.2 ! misho    95196:         $packagexml = $this->_rest->retrieveCacheFirst($base . 'r/' . $packageLower . '/' .
        !          95197:             'deps.' . $release['v'] . '.txt', false, true, $channel);
        !          95198:         if (PEAR::isError($packagexml)) {
        !          95199:             return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] .
        !          95200:                 '" does not have REST dependency information available');
        !          95201:         }
1.1       misho    95202: 
1.1.1.2 ! misho    95203:         $packagexml = unserialize($packagexml);
        !          95204:         if (!$packagexml) {
        !          95205:             $packagexml = array();
1.1       misho    95206:         }
                   95207: 
1.1.1.2 ! misho    95208:         $allinfo = $this->_rest->retrieveData($base . 'r/' . $packageLower .
        !          95209:             '/allreleases.xml', false, false, $channel);
        !          95210:         if (PEAR::isError($allinfo)) {
        !          95211:             return $allinfo;
1.1       misho    95212:         }
                   95213: 
1.1.1.2 ! misho    95214:         if (!is_array($allinfo['r']) || !isset($allinfo['r'][0])) {
        !          95215:             $allinfo['r'] = array($allinfo['r']);
1.1       misho    95216:         }
                   95217: 
1.1.1.2 ! misho    95218:         $compatible = false;
        !          95219:         foreach ($allinfo['r'] as $release) {
        !          95220:             if ($release['v'] != $releaseinfo['v']) {
        !          95221:                 continue;
        !          95222:             }
1.1       misho    95223: 
1.1.1.2 ! misho    95224:             if (!isset($release['co'])) {
        !          95225:                 break;
        !          95226:             }
1.1       misho    95227: 
1.1.1.2 ! misho    95228:             $compatible = array();
        !          95229:             if (!is_array($release['co']) || !isset($release['co'][0])) {
        !          95230:                 $release['co'] = array($release['co']);
        !          95231:             }
        !          95232: 
        !          95233:             foreach ($release['co'] as $entry) {
        !          95234:                 $comp = array();
        !          95235:                 $comp['name']    = $entry['p'];
        !          95236:                 $comp['channel'] = $entry['c'];
        !          95237:                 $comp['min']     = $entry['min'];
        !          95238:                 $comp['max']     = $entry['max'];
        !          95239:                 if (isset($entry['x']) && !is_array($entry['x'])) {
        !          95240:                     $comp['exclude'] = $entry['x'];
        !          95241:                 }
        !          95242: 
        !          95243:                 $compatible[] = $comp;
        !          95244:             }
        !          95245: 
        !          95246:             if (count($compatible) == 1) {
        !          95247:                 $compatible = $compatible[0];
        !          95248:             }
        !          95249: 
        !          95250:             break;
        !          95251:         }
        !          95252: 
        !          95253:         $deprecated = false;
        !          95254:         if (isset($pinfo['dc']) && isset($pinfo['dp'])) {
        !          95255:             if (is_array($pinfo['dp'])) {
        !          95256:                 $deprecated = array('channel' => (string) $pinfo['dc'],
        !          95257:                                     'package' => trim($pinfo['dp']['_content']));
        !          95258:             } else {
        !          95259:                 $deprecated = array('channel' => (string) $pinfo['dc'],
        !          95260:                                     'package' => trim($pinfo['dp']));
        !          95261:             }
        !          95262:         }
        !          95263: 
        !          95264:         $return = array(
        !          95265:             'version'    => $releaseinfo['v'],
        !          95266:             'info'       => $packagexml,
        !          95267:             'package'    => $releaseinfo['p']['_content'],
        !          95268:             'stability'  => $releaseinfo['st'],
        !          95269:             'compatible' => $compatible,
        !          95270:             'deprecated' => $deprecated,
        !          95271:         );
        !          95272: 
        !          95273:         if ($found) {
        !          95274:             $return['url'] = $releaseinfo['g'];
        !          95275:             return $return;
1.1       misho    95276:         }
                   95277: 
1.1.1.2 ! misho    95278:         $return['php'] = $phpversion;
        !          95279:         return $return;
1.1       misho    95280:     }
                   95281: 
1.1.1.2 ! misho    95282:     function listPackages($base, $channel = false)
1.1       misho    95283:     {
1.1.1.2 ! misho    95284:         $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
        !          95285:         if (PEAR::isError($packagelist)) {
        !          95286:             return $packagelist;
1.1       misho    95287:         }
1.1.1.2 ! misho    95288: 
        !          95289:         if (!is_array($packagelist) || !isset($packagelist['p'])) {
        !          95290:             return array();
1.1       misho    95291:         }
1.1.1.2 ! misho    95292: 
        !          95293:         if (!is_array($packagelist['p'])) {
        !          95294:             $packagelist['p'] = array($packagelist['p']);
1.1       misho    95295:         }
                   95296: 
1.1.1.2 ! misho    95297:         return $packagelist['p'];
        !          95298:     }
1.1       misho    95299: 
1.1.1.2 ! misho    95300:     /**
        !          95301:      * List all categories of a REST server
        !          95302:      *
        !          95303:      * @param string $base base URL of the server
        !          95304:      * @return array of categorynames
        !          95305:      */
        !          95306:     function listCategories($base, $channel = false)
1.1       misho    95307:     {
1.1.1.2 ! misho    95308:         $categories = array();
1.1       misho    95309: 
1.1.1.2 ! misho    95310:         // c/categories.xml does not exist;
        !          95311:         // check for every package its category manually
        !          95312:         // This is SLOOOWWWW : ///
        !          95313:         $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
        !          95314:         if (PEAR::isError($packagelist)) {
        !          95315:             return $packagelist;
1.1       misho    95316:         }
                   95317: 
1.1.1.2 ! misho    95318:         if (!is_array($packagelist) || !isset($packagelist['p'])) {
        !          95319:             $ret = array();
        !          95320:             return $ret;
1.1       misho    95321:         }
                   95322: 
1.1.1.2 ! misho    95323:         if (!is_array($packagelist['p'])) {
        !          95324:             $packagelist['p'] = array($packagelist['p']);
1.1       misho    95325:         }
                   95326: 
1.1.1.2 ! misho    95327:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          95328:         foreach ($packagelist['p'] as $package) {
        !          95329:                 $inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
        !          95330:                 if (PEAR::isError($inf)) {
        !          95331:                     PEAR::popErrorHandling();
        !          95332:                     return $inf;
        !          95333:                 }
        !          95334:                 $cat = $inf['ca']['_content'];
        !          95335:                 if (!isset($categories[$cat])) {
        !          95336:                     $categories[$cat] = $inf['ca'];
        !          95337:                 }
1.1       misho    95338:         }
                   95339: 
1.1.1.2 ! misho    95340:         return array_values($categories);
1.1       misho    95341:     }
                   95342: 
                   95343:     /**
1.1.1.2 ! misho    95344:      * List a category of a REST server
        !          95345:      *
        !          95346:      * @param string $base base URL of the server
        !          95347:      * @param string $category name of the category
        !          95348:      * @param boolean $info also download full package info
        !          95349:      * @return array of packagenames
1.1       misho    95350:      */
1.1.1.2 ! misho    95351:     function listCategory($base, $category, $info = false, $channel = false)
1.1       misho    95352:     {
1.1.1.2 ! misho    95353:         // gives '404 Not Found' error when category doesn't exist
        !          95354:         $packagelist = $this->_rest->retrieveData($base.'c/'.urlencode($category).'/packages.xml', false, false, $channel);
        !          95355:         if (PEAR::isError($packagelist)) {
        !          95356:             return $packagelist;
1.1       misho    95357:         }
                   95358: 
1.1.1.2 ! misho    95359:         if (!is_array($packagelist) || !isset($packagelist['p'])) {
        !          95360:             return array();
1.1       misho    95361:         }
                   95362: 
1.1.1.2 ! misho    95363:         if (!is_array($packagelist['p']) ||
        !          95364:             !isset($packagelist['p'][0])) { // only 1 pkg
        !          95365:             $packagelist = array($packagelist['p']);
        !          95366:         } else {
        !          95367:             $packagelist = $packagelist['p'];
        !          95368:         }
1.1       misho    95369: 
1.1.1.2 ! misho    95370:         if ($info == true) {
        !          95371:             // get individual package info
        !          95372:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          95373:             foreach ($packagelist as $i => $packageitem) {
        !          95374:                 $url = sprintf('%s'.'r/%s/latest.txt',
        !          95375:                         $base,
        !          95376:                         strtolower($packageitem['_content']));
        !          95377:                 $version = $this->_rest->retrieveData($url, false, false, $channel);
        !          95378:                 if (PEAR::isError($version)) {
        !          95379:                     break; // skipit
1.1       misho    95380:                 }
1.1.1.2 ! misho    95381:                 $url = sprintf('%s'.'r/%s/%s.xml',
        !          95382:                         $base,
        !          95383:                         strtolower($packageitem['_content']),
        !          95384:                         $version);
        !          95385:                 $info = $this->_rest->retrieveData($url, false, false, $channel);
        !          95386:                 if (PEAR::isError($info)) {
        !          95387:                     break; // skipit
1.1       misho    95388:                 }
1.1.1.2 ! misho    95389:                 $packagelist[$i]['info'] = $info;
1.1       misho    95390:             }
1.1.1.2 ! misho    95391:             PEAR::popErrorHandling();
1.1       misho    95392:         }
1.1.1.2 ! misho    95393: 
        !          95394:         return $packagelist;
1.1       misho    95395:     }
                   95396: 
1.1.1.2 ! misho    95397: 
        !          95398:     function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false)
1.1       misho    95399:     {
1.1.1.2 ! misho    95400:         $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
        !          95401:         if (PEAR::isError($packagelist)) {
        !          95402:             return $packagelist;
        !          95403:         }
        !          95404:         if ($this->_rest->config->get('verbose') > 0) {
        !          95405:             $ui = &PEAR_Frontend::singleton();
        !          95406:             $ui->log('Retrieving data...0%', true);
1.1       misho    95407:         }
                   95408:         $ret = array();
1.1.1.2 ! misho    95409:         if (!is_array($packagelist) || !isset($packagelist['p'])) {
        !          95410:             return $ret;
1.1       misho    95411:         }
1.1.1.2 ! misho    95412:         if (!is_array($packagelist['p'])) {
        !          95413:             $packagelist['p'] = array($packagelist['p']);
1.1       misho    95414:         }
                   95415: 
1.1.1.2 ! misho    95416:         // only search-packagename = quicksearch !
        !          95417:         if ($searchpackage && (!$searchsummary || empty($searchpackage))) {
        !          95418:             $newpackagelist = array();
        !          95419:             foreach ($packagelist['p'] as $package) {
        !          95420:                 if (!empty($searchpackage) && stristr($package, $searchpackage) !== false) {
        !          95421:                     $newpackagelist[] = $package;
1.1       misho    95422:                 }
                   95423:             }
1.1.1.2 ! misho    95424:             $packagelist['p'] = $newpackagelist;
        !          95425:         }
        !          95426:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          95427:         $next = .1;
        !          95428:         foreach ($packagelist['p'] as $progress => $package) {
        !          95429:             if ($this->_rest->config->get('verbose') > 0) {
        !          95430:                 if ($progress / count($packagelist['p']) >= $next) {
        !          95431:                     if ($next == .5) {
        !          95432:                         $ui->log('50%', false);
        !          95433:                     } else {
        !          95434:                         $ui->log('.', false);
1.1       misho    95435:                     }
1.1.1.2 ! misho    95436:                     $next += .1;
        !          95437:                 }
        !          95438:             }
        !          95439: 
        !          95440:             if ($basic) { // remote-list command
        !          95441:                 if ($dostable) {
        !          95442:                     $latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
        !          95443:                         '/stable.txt', false, false, $channel);
        !          95444:                 } else {
        !          95445:                     $latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
        !          95446:                         '/latest.txt', false, false, $channel);
        !          95447:                 }
        !          95448:                 if (PEAR::isError($latest)) {
        !          95449:                     $latest = false;
        !          95450:                 }
        !          95451:                 $info = array('stable' => $latest);
        !          95452:             } else { // list-all command
        !          95453:                 $inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
        !          95454:                 if (PEAR::isError($inf)) {
        !          95455:                     PEAR::popErrorHandling();
        !          95456:                     return $inf;
        !          95457:                 }
        !          95458:                 if ($searchpackage) {
        !          95459:                     $found = (!empty($searchpackage) && stristr($package, $searchpackage) !== false);
        !          95460:                     if (!$found && !(isset($searchsummary) && !empty($searchsummary)
        !          95461:                         && (stristr($inf['s'], $searchsummary) !== false
        !          95462:                             || stristr($inf['d'], $searchsummary) !== false)))
        !          95463:                     {
1.1       misho    95464:                         continue;
1.1.1.2 ! misho    95465:                     };
        !          95466:                 }
        !          95467:                 $releases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
        !          95468:                     '/allreleases.xml', false, false, $channel);
        !          95469:                 if (PEAR::isError($releases)) {
        !          95470:                     continue;
        !          95471:                 }
        !          95472:                 if (!isset($releases['r'][0])) {
        !          95473:                     $releases['r'] = array($releases['r']);
        !          95474:                 }
        !          95475:                 unset($latest);
        !          95476:                 unset($unstable);
        !          95477:                 unset($stable);
        !          95478:                 unset($state);
        !          95479:                 foreach ($releases['r'] as $release) {
        !          95480:                     if (!isset($latest)) {
        !          95481:                         if ($dostable && $release['s'] == 'stable') {
        !          95482:                             $latest = $release['v'];
        !          95483:                             $state = 'stable';
        !          95484:                         }
        !          95485:                         if (!$dostable) {
        !          95486:                             $latest = $release['v'];
        !          95487:                             $state = $release['s'];
        !          95488:                         }
1.1       misho    95489:                     }
1.1.1.2 ! misho    95490:                     if (!isset($stable) && $release['s'] == 'stable') {
        !          95491:                         $stable = $release['v'];
        !          95492:                         if (!isset($unstable)) {
        !          95493:                             $unstable = $stable;
        !          95494:                         }
1.1       misho    95495:                     }
1.1.1.2 ! misho    95496:                     if (!isset($unstable) && $release['s'] != 'stable') {
        !          95497:                         $latest = $unstable = $release['v'];
        !          95498:                         $state = $release['s'];
        !          95499:                     }
        !          95500:                     if (isset($latest) && !isset($state)) {
        !          95501:                         $state = $release['s'];
        !          95502:                     }
        !          95503:                     if (isset($latest) && isset($stable) && isset($unstable)) {
        !          95504:                         break;
1.1       misho    95505:                     }
                   95506:                 }
1.1.1.2 ! misho    95507:                 $deps = array();
        !          95508:                 if (!isset($unstable)) {
        !          95509:                     $unstable = false;
        !          95510:                     $state = 'stable';
        !          95511:                     if (isset($stable)) {
        !          95512:                         $latest = $unstable = $stable;
        !          95513:                     }
        !          95514:                 } else {
        !          95515:                     $latest = $unstable;
1.1       misho    95516:                 }
1.1.1.2 ! misho    95517:                 if (!isset($latest)) {
        !          95518:                     $latest = false;
1.1       misho    95519:                 }
1.1.1.2 ! misho    95520:                 if ($latest) {
        !          95521:                     $d = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' .
        !          95522:                         $latest . '.txt', false, false, $channel);
        !          95523:                     if (!PEAR::isError($d)) {
        !          95524:                         $d = unserialize($d);
        !          95525:                         if ($d) {
        !          95526:                             if (isset($d['required'])) {
        !          95527:                                 if (!class_exists('PEAR_PackageFile_v2')) {
        !          95528:                                     require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2.php';
        !          95529:                                 }
        !          95530:                                 if (!isset($pf)) {
        !          95531:                                     $pf = new PEAR_PackageFile_v2;
        !          95532:                                 }
        !          95533:                                 $pf->setDeps($d);
        !          95534:                                 $tdeps = $pf->getDeps();
        !          95535:                             } else {
        !          95536:                                 $tdeps = $d;
        !          95537:                             }
        !          95538:                             foreach ($tdeps as $dep) {
        !          95539:                                 if ($dep['type'] !== 'pkg') {
        !          95540:                                     continue;
        !          95541:                                 }
        !          95542:                                 $deps[] = $dep;
        !          95543:                             }
        !          95544:                         }
1.1       misho    95545:                     }
                   95546:                 }
1.1.1.2 ! misho    95547:                 if (!isset($stable)) {
        !          95548:                     $stable = '-n/a-';
        !          95549:                 }
        !          95550:                 if (!$searchpackage) {
        !          95551:                     $info = array('stable' => $latest, 'summary' => $inf['s'], 'description' =>
        !          95552:                         $inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'],
        !          95553:                         'unstable' => $unstable, 'state' => $state);
        !          95554:                 } else {
        !          95555:                     $info = array('stable' => $stable, 'summary' => $inf['s'], 'description' =>
        !          95556:                         $inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'],
        !          95557:                         'unstable' => $unstable, 'state' => $state);
1.1       misho    95558:                 }
                   95559:             }
1.1.1.2 ! misho    95560:             $ret[$package] = $info;
        !          95561:         }
        !          95562:         PEAR::popErrorHandling();
        !          95563:         return $ret;
        !          95564:     }
1.1       misho    95565: 
1.1.1.2 ! misho    95566:     function listLatestUpgrades($base, $pref_state, $installed, $channel, &$reg)
        !          95567:     {
        !          95568:         $packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
        !          95569:         if (PEAR::isError($packagelist)) {
        !          95570:             return $packagelist;
        !          95571:         }
        !          95572: 
        !          95573:         $ret = array();
        !          95574:         if (!is_array($packagelist) || !isset($packagelist['p'])) {
        !          95575:             return $ret;
        !          95576:         }
        !          95577: 
        !          95578:         if (!is_array($packagelist['p'])) {
        !          95579:             $packagelist['p'] = array($packagelist['p']);
        !          95580:         }
        !          95581: 
        !          95582:         foreach ($packagelist['p'] as $package) {
        !          95583:             if (!isset($installed[strtolower($package)])) {
        !          95584:                 continue;
1.1       misho    95585:             }
1.1.1.2 ! misho    95586: 
        !          95587:             $inst_version = $reg->packageInfo($package, 'version', $channel);
        !          95588:             $inst_state   = $reg->packageInfo($package, 'release_state', $channel);
        !          95589:             PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          95590:             $info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
        !          95591:                 '/allreleases.xml', false, false, $channel);
        !          95592:             PEAR::popErrorHandling();
        !          95593:             if (PEAR::isError($info)) {
        !          95594:                 continue; // no remote releases
1.1       misho    95595:             }
1.1.1.2 ! misho    95596: 
        !          95597:             if (!isset($info['r'])) {
        !          95598:                 continue;
1.1       misho    95599:             }
1.1.1.2 ! misho    95600: 
        !          95601:             $release = $found = false;
        !          95602:             if (!is_array($info['r']) || !isset($info['r'][0])) {
        !          95603:                 $info['r'] = array($info['r']);
1.1       misho    95604:             }
1.1.1.2 ! misho    95605: 
        !          95606:             // $info['r'] is sorted by version number
        !          95607:             usort($info['r'], array($this, '_sortReleasesByVersionNumber'));
        !          95608:             foreach ($info['r'] as $release) {
        !          95609:                 if ($inst_version && version_compare($release['v'], $inst_version, '<=')) {
        !          95610:                     // not newer than the one installed
        !          95611:                     break;
        !          95612:                 }
        !          95613: 
        !          95614:                 // new version > installed version
        !          95615:                 if (!$pref_state) {
        !          95616:                     // every state is a good state
        !          95617:                     $found = true;
        !          95618:                     break;
        !          95619:                 } else {
        !          95620:                     $new_state = $release['s'];
        !          95621:                     // if new state >= installed state: go
        !          95622:                     if (in_array($new_state, $this->betterStates($inst_state, true))) {
        !          95623:                         $found = true;
        !          95624:                         break;
        !          95625:                     } else {
        !          95626:                         // only allow to lower the state of package,
        !          95627:                         // if new state >= preferred state: go
        !          95628:                         if (in_array($new_state, $this->betterStates($pref_state, true))) {
        !          95629:                             $found = true;
        !          95630:                             break;
        !          95631:                         }
        !          95632:                     }
        !          95633:                 }
1.1       misho    95634:             }
1.1.1.2 ! misho    95635: 
        !          95636:             if (!$found) {
        !          95637:                 continue;
1.1       misho    95638:             }
1.1.1.2 ! misho    95639: 
        !          95640:             $relinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' .
        !          95641:                 $release['v'] . '.xml', false, false, $channel);
        !          95642:             if (PEAR::isError($relinfo)) {
        !          95643:                 return $relinfo;
1.1       misho    95644:             }
1.1.1.2 ! misho    95645: 
        !          95646:             $ret[$package] = array(
        !          95647:                 'version'  => $release['v'],
        !          95648:                 'state'    => $release['s'],
        !          95649:                 'filesize' => $relinfo['f'],
        !          95650:             );
1.1       misho    95651:         }
1.1.1.2 ! misho    95652: 
        !          95653:         return $ret;
        !          95654:     }
        !          95655: 
        !          95656:     function packageInfo($base, $package, $channel = false)
        !          95657:     {
        !          95658:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
        !          95659:         $pinfo = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
        !          95660:         if (PEAR::isError($pinfo)) {
        !          95661:             PEAR::popErrorHandling();
        !          95662:             return PEAR::raiseError('Unknown package: "' . $package . '" in channel "' . $channel . '"' . "\n". 'Debug: ' .
        !          95663:                 $pinfo->getMessage());
1.1       misho    95664:         }
1.1.1.2 ! misho    95665: 
        !          95666:         $releases = array();
        !          95667:         $allreleases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
        !          95668:             '/allreleases.xml', false, false, $channel);
        !          95669:         if (!PEAR::isError($allreleases)) {
        !          95670:             if (!class_exists('PEAR_PackageFile_v2')) {
        !          95671:                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2.php';
1.1       misho    95672:             }
1.1.1.2 ! misho    95673: 
        !          95674:             if (!is_array($allreleases['r']) || !isset($allreleases['r'][0])) {
        !          95675:                 $allreleases['r'] = array($allreleases['r']);
1.1       misho    95676:             }
1.1.1.2 ! misho    95677: 
        !          95678:             $pf = new PEAR_PackageFile_v2;
        !          95679:             foreach ($allreleases['r'] as $release) {
        !          95680:                 $ds = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' .
        !          95681:                     $release['v'] . '.txt', false, false, $channel);
        !          95682:                 if (PEAR::isError($ds)) {
        !          95683:                     continue;
        !          95684:                 }
        !          95685: 
        !          95686:                 if (!isset($latest)) {
        !          95687:                     $latest = $release['v'];
        !          95688:                 }
        !          95689: 
        !          95690:                 $pf->setDeps(unserialize($ds));
        !          95691:                 $ds = $pf->getDeps();
        !          95692:                 $info = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package)
        !          95693:                     . '/' . $release['v'] . '.xml', false, false, $channel);
        !          95694: 
        !          95695:                 if (PEAR::isError($info)) {
        !          95696:                     continue;
        !          95697:                 }
        !          95698: 
        !          95699:                 $releases[$release['v']] = array(
        !          95700:                     'doneby' => $info['m'],
        !          95701:                     'license' => $info['l'],
        !          95702:                     'summary' => $info['s'],
        !          95703:                     'description' => $info['d'],
        !          95704:                     'releasedate' => $info['da'],
        !          95705:                     'releasenotes' => $info['n'],
        !          95706:                     'state' => $release['s'],
        !          95707:                     'deps' => $ds ? $ds : array(),
        !          95708:                 );
1.1       misho    95709:             }
1.1.1.2 ! misho    95710:         } else {
        !          95711:             $latest = '';
        !          95712:         }
        !          95713: 
        !          95714:         PEAR::popErrorHandling();
        !          95715:         if (isset($pinfo['dc']) && isset($pinfo['dp'])) {
        !          95716:             if (is_array($pinfo['dp'])) {
        !          95717:                 $deprecated = array('channel' => (string) $pinfo['dc'],
        !          95718:                                     'package' => trim($pinfo['dp']['_content']));
1.1       misho    95719:             } else {
1.1.1.2 ! misho    95720:                 $deprecated = array('channel' => (string) $pinfo['dc'],
        !          95721:                                     'package' => trim($pinfo['dp']));
1.1       misho    95722:             }
1.1.1.2 ! misho    95723:         } else {
        !          95724:             $deprecated = false;
1.1       misho    95725:         }
1.1.1.2 ! misho    95726: 
        !          95727:         if (!isset($latest)) {
        !          95728:             $latest = '';
        !          95729:         }
        !          95730: 
        !          95731:         return array(
        !          95732:             'name' => $pinfo['n'],
        !          95733:             'channel' => $pinfo['c'],
        !          95734:             'category' => $pinfo['ca']['_content'],
        !          95735:             'stable' => $latest,
        !          95736:             'license' => $pinfo['l'],
        !          95737:             'summary' => $pinfo['s'],
        !          95738:             'description' => $pinfo['d'],
        !          95739:             'releases' => $releases,
        !          95740:             'deprecated' => $deprecated,
        !          95741:             );
1.1       misho    95742:     }
                   95743: 
                   95744:     /**
1.1.1.2 ! misho    95745:      * Return an array containing all of the states that are more stable than
        !          95746:      * or equal to the passed in state
        !          95747:      *
        !          95748:      * @param string Release state
        !          95749:      * @param boolean Determines whether to include $state in the list
        !          95750:      * @return false|array False if $state is not a valid release state
1.1       misho    95751:      */
1.1.1.2 ! misho    95752:     function betterStates($state, $include = false)
1.1       misho    95753:     {
1.1.1.2 ! misho    95754:         static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
        !          95755:         $i = array_search($state, $states);
        !          95756:         if ($i === false) {
        !          95757:             return false;
1.1       misho    95758:         }
1.1.1.2 ! misho    95759: 
        !          95760:         if ($include) {
        !          95761:             $i--;
1.1       misho    95762:         }
1.1.1.2 ! misho    95763: 
        !          95764:         return array_slice($states, $i + 1);
        !          95765:     }
        !          95766: 
        !          95767:     /**
        !          95768:      * Sort releases by version number
        !          95769:      *
        !          95770:      * @access private
        !          95771:      */
        !          95772:     function _sortReleasesByVersionNumber($a, $b)
        !          95773:     {
        !          95774:         if (version_compare($a['v'], $b['v'], '=')) {
        !          95775:             return 0;
1.1       misho    95776:         }
1.1.1.2 ! misho    95777: 
        !          95778:         if (version_compare($a['v'], $b['v'], '>')) {
        !          95779:             return -1;
1.1       misho    95780:         }
1.1.1.2 ! misho    95781: 
        !          95782:         if (version_compare($a['v'], $b['v'], '<')) {
        !          95783:             return 1;
1.1       misho    95784:         }
                   95785:     }
                   95786: }<?php
                   95787: /**
1.1.1.2 ! misho    95788:  * PEAR_REST_11 - implement faster list-all/remote-list command
1.1       misho    95789:  *
                   95790:  * PHP versions 4 and 5
                   95791:  *
                   95792:  * @category   pear
                   95793:  * @package    PEAR
                   95794:  * @author     Greg Beaver <cellog@php.net>
                   95795:  * @copyright  1997-2009 The Authors
                   95796:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    95797:  * @version    CVS: $Id: 11.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    95798:  * @link       http://pear.php.net/package/PEAR
1.1.1.2 ! misho    95799:  * @since      File available since Release 1.4.3
1.1       misho    95800:  */
                   95801: 
                   95802: /**
1.1.1.2 ! misho    95803:  * For downloading REST xml/txt files
1.1       misho    95804:  */
1.1.1.2 ! misho    95805: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/REST.php';
1.1       misho    95806: 
                   95807: /**
1.1.1.2 ! misho    95808:  * Implement REST 1.1
        !          95809:  *
1.1       misho    95810:  * @category   pear
                   95811:  * @package    PEAR
                   95812:  * @author     Greg Beaver <cellog@php.net>
                   95813:  * @copyright  1997-2009 The Authors
                   95814:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    95815:  * @version    Release: 1.9.4
1.1       misho    95816:  * @link       http://pear.php.net/package/PEAR
1.1.1.2 ! misho    95817:  * @since      Class available since Release 1.4.3
1.1       misho    95818:  */
1.1.1.2 ! misho    95819: class PEAR_REST_11
1.1       misho    95820: {
                   95821:     /**
1.1.1.2 ! misho    95822:      * @var PEAR_REST
1.1       misho    95823:      */
1.1.1.2 ! misho    95824:     var $_rest;
1.1       misho    95825: 
1.1.1.2 ! misho    95826:     function PEAR_REST_11($config, $options = array())
        !          95827:     {
        !          95828:         $this->_rest = &new PEAR_REST($config, $options);
        !          95829:     }
        !          95830: 
        !          95831:     function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false)
        !          95832:     {
        !          95833:         $categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel);
        !          95834:         if (PEAR::isError($categorylist)) {
        !          95835:             return $categorylist;
1.1       misho    95836:         }
                   95837: 
1.1.1.2 ! misho    95838:         $ret = array();
        !          95839:         if (!is_array($categorylist['c']) || !isset($categorylist['c'][0])) {
        !          95840:             $categorylist['c'] = array($categorylist['c']);
1.1       misho    95841:         }
                   95842: 
1.1.1.2 ! misho    95843:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
1.1       misho    95844: 
1.1.1.2 ! misho    95845:         foreach ($categorylist['c'] as $progress => $category) {
        !          95846:             $category = $category['_content'];
        !          95847:             $packagesinfo = $this->_rest->retrieveData($base .
        !          95848:                 'c/' . urlencode($category) . '/packagesinfo.xml', false, false, $channel);
        !          95849: 
        !          95850:             if (PEAR::isError($packagesinfo)) {
        !          95851:                 continue;
1.1       misho    95852:             }
                   95853: 
1.1.1.2 ! misho    95854:             if (!is_array($packagesinfo) || !isset($packagesinfo['pi'])) {
        !          95855:                 continue;
        !          95856:             }
1.1       misho    95857: 
1.1.1.2 ! misho    95858:             if (!is_array($packagesinfo['pi']) || !isset($packagesinfo['pi'][0])) {
        !          95859:                 $packagesinfo['pi'] = array($packagesinfo['pi']);
        !          95860:             }
1.1       misho    95861: 
1.1.1.2 ! misho    95862:             foreach ($packagesinfo['pi'] as $packageinfo) {
        !          95863:                 if (empty($packageinfo)) {
        !          95864:                     continue;
        !          95865:                 }
1.1       misho    95866: 
1.1.1.2 ! misho    95867:                 $info     = $packageinfo['p'];
        !          95868:                 $package  = $info['n'];
        !          95869:                 $releases = isset($packageinfo['a']) ? $packageinfo['a'] : false;
        !          95870:                 unset($latest);
        !          95871:                 unset($unstable);
        !          95872:                 unset($stable);
        !          95873:                 unset($state);
1.1       misho    95874: 
1.1.1.2 ! misho    95875:                 if ($releases) {
        !          95876:                     if (!isset($releases['r'][0])) {
        !          95877:                         $releases['r'] = array($releases['r']);
        !          95878:                     }
1.1       misho    95879: 
1.1.1.2 ! misho    95880:                     foreach ($releases['r'] as $release) {
        !          95881:                         if (!isset($latest)) {
        !          95882:                             if ($dostable && $release['s'] == 'stable') {
        !          95883:                                 $latest = $release['v'];
        !          95884:                                 $state = 'stable';
        !          95885:                             }
        !          95886:                             if (!$dostable) {
        !          95887:                                 $latest = $release['v'];
        !          95888:                                 $state = $release['s'];
        !          95889:                             }
        !          95890:                         }
1.1       misho    95891: 
1.1.1.2 ! misho    95892:                         if (!isset($stable) && $release['s'] == 'stable') {
        !          95893:                             $stable = $release['v'];
        !          95894:                             if (!isset($unstable)) {
        !          95895:                                 $unstable = $stable;
        !          95896:                             }
        !          95897:                         }
1.1       misho    95898: 
1.1.1.2 ! misho    95899:                         if (!isset($unstable) && $release['s'] != 'stable') {
        !          95900:                             $unstable = $release['v'];
        !          95901:                             $state = $release['s'];
        !          95902:                         }
1.1       misho    95903: 
1.1.1.2 ! misho    95904:                         if (isset($latest) && !isset($state)) {
        !          95905:                             $state = $release['s'];
        !          95906:                         }
1.1       misho    95907: 
1.1.1.2 ! misho    95908:                         if (isset($latest) && isset($stable) && isset($unstable)) {
        !          95909:                             break;
        !          95910:                         }
        !          95911:                     }
        !          95912:                 }
1.1       misho    95913: 
1.1.1.2 ! misho    95914:                 if ($basic) { // remote-list command
        !          95915:                     if (!isset($latest)) {
        !          95916:                         $latest = false;
        !          95917:                     }
1.1       misho    95918: 
1.1.1.2 ! misho    95919:                     if ($dostable) {
        !          95920:                         // $state is not set if there are no releases
        !          95921:                         if (isset($state) && $state == 'stable') {
        !          95922:                             $ret[$package] = array('stable' => $latest);
        !          95923:                         } else {
        !          95924:                             $ret[$package] = array('stable' => '-n/a-');
        !          95925:                         }
        !          95926:                     } else {
        !          95927:                         $ret[$package] = array('stable' => $latest);
        !          95928:                     }
1.1       misho    95929: 
1.1.1.2 ! misho    95930:                     continue;
        !          95931:                 }
1.1       misho    95932: 
1.1.1.2 ! misho    95933:                 // list-all command
        !          95934:                 if (!isset($unstable)) {
        !          95935:                     $unstable = false;
        !          95936:                     $state = 'stable';
        !          95937:                     if (isset($stable)) {
        !          95938:                         $latest = $unstable = $stable;
        !          95939:                     }
        !          95940:                 } else {
        !          95941:                     $latest = $unstable;
        !          95942:                 }
1.1       misho    95943: 
1.1.1.2 ! misho    95944:                 if (!isset($latest)) {
        !          95945:                     $latest = false;
        !          95946:                 }
1.1       misho    95947: 
1.1.1.2 ! misho    95948:                 $deps = array();
        !          95949:                 if ($latest && isset($packageinfo['deps'])) {
        !          95950:                     if (!is_array($packageinfo['deps']) ||
        !          95951:                           !isset($packageinfo['deps'][0])
        !          95952:                     ) {
        !          95953:                         $packageinfo['deps'] = array($packageinfo['deps']);
        !          95954:                     }
1.1       misho    95955: 
1.1.1.2 ! misho    95956:                     $d = false;
        !          95957:                     foreach ($packageinfo['deps'] as $dep) {
        !          95958:                         if ($dep['v'] == $latest) {
        !          95959:                             $d = unserialize($dep['d']);
        !          95960:                         }
        !          95961:                     }
1.1       misho    95962: 
1.1.1.2 ! misho    95963:                     if ($d) {
        !          95964:                         if (isset($d['required'])) {
        !          95965:                             if (!class_exists('PEAR_PackageFile_v2')) {
        !          95966:                                 require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/PackageFile/v2.php';
        !          95967:                             }
1.1       misho    95968: 
1.1.1.2 ! misho    95969:                             if (!isset($pf)) {
        !          95970:                                 $pf = new PEAR_PackageFile_v2;
        !          95971:                             }
1.1       misho    95972: 
1.1.1.2 ! misho    95973:                             $pf->setDeps($d);
        !          95974:                             $tdeps = $pf->getDeps();
        !          95975:                         } else {
        !          95976:                             $tdeps = $d;
        !          95977:                         }
        !          95978: 
        !          95979:                         foreach ($tdeps as $dep) {
        !          95980:                             if ($dep['type'] !== 'pkg') {
        !          95981:                                 continue;
        !          95982:                             }
        !          95983: 
        !          95984:                             $deps[] = $dep;
        !          95985:                         }
        !          95986:                     }
1.1       misho    95987:                 }
1.1.1.2 ! misho    95988: 
        !          95989:                 $info = array(
        !          95990:                     'stable'      => $latest,
        !          95991:                     'summary'     => $info['s'],
        !          95992:                     'description' => $info['d'],
        !          95993:                     'deps'        => $deps,
        !          95994:                     'category'    => $info['ca']['_content'],
        !          95995:                     'unstable'    => $unstable,
        !          95996:                     'state'       => $state
        !          95997:                 );
        !          95998:                 $ret[$package] = $info;
1.1       misho    95999:             }
                   96000:         }
                   96001: 
1.1.1.2 ! misho    96002:         PEAR::popErrorHandling();
        !          96003:         return $ret;
1.1       misho    96004:     }
                   96005: 
                   96006:     /**
1.1.1.2 ! misho    96007:      * List all categories of a REST server
1.1       misho    96008:      *
1.1.1.2 ! misho    96009:      * @param string $base base URL of the server
        !          96010:      * @return array of categorynames
1.1       misho    96011:      */
1.1.1.2 ! misho    96012:     function listCategories($base, $channel = false)
1.1       misho    96013:     {
1.1.1.2 ! misho    96014:         $categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel);
        !          96015:         if (PEAR::isError($categorylist)) {
        !          96016:             return $categorylist;
1.1       misho    96017:         }
                   96018: 
1.1.1.2 ! misho    96019:         if (!is_array($categorylist) || !isset($categorylist['c'])) {
        !          96020:             return array();
1.1       misho    96021:         }
                   96022: 
1.1.1.2 ! misho    96023:         if (isset($categorylist['c']['_content'])) {
        !          96024:             // only 1 category
        !          96025:             $categorylist['c'] = array($categorylist['c']);
1.1       misho    96026:         }
                   96027: 
1.1.1.2 ! misho    96028:         return $categorylist['c'];
        !          96029:     }
1.1       misho    96030: 
1.1.1.2 ! misho    96031:     /**
        !          96032:      * List packages in a category of a REST server
        !          96033:      *
        !          96034:      * @param string $base base URL of the server
        !          96035:      * @param string $category name of the category
        !          96036:      * @param boolean $info also download full package info
        !          96037:      * @return array of packagenames
        !          96038:      */
        !          96039:     function listCategory($base, $category, $info = false, $channel = false)
        !          96040:     {
        !          96041:         if ($info == false) {
        !          96042:             $url = '%s'.'c/%s/packages.xml';
1.1       misho    96043:         } else {
1.1.1.2 ! misho    96044:             $url = '%s'.'c/%s/packagesinfo.xml';
1.1       misho    96045:         }
1.1.1.2 ! misho    96046:         $url = sprintf($url,
        !          96047:                     $base,
        !          96048:                     urlencode($category));
1.1       misho    96049: 
1.1.1.2 ! misho    96050:         // gives '404 Not Found' error when category doesn't exist
        !          96051:         $packagelist = $this->_rest->retrieveData($url, false, false, $channel);
        !          96052:         if (PEAR::isError($packagelist)) {
        !          96053:             return $packagelist;
1.1       misho    96054:         }
1.1.1.2 ! misho    96055:         if (!is_array($packagelist)) {
        !          96056:             return array();
1.1       misho    96057:         }
                   96058: 
1.1.1.2 ! misho    96059:         if ($info == false) {
        !          96060:             if (!isset($packagelist['p'])) {
        !          96061:                 return array();
1.1       misho    96062:             }
1.1.1.2 ! misho    96063:             if (!is_array($packagelist['p']) ||
        !          96064:                 !isset($packagelist['p'][0])) { // only 1 pkg
        !          96065:                 $packagelist = array($packagelist['p']);
        !          96066:             } else {
        !          96067:                 $packagelist = $packagelist['p'];
1.1       misho    96068:             }
1.1.1.2 ! misho    96069:             return $packagelist;
1.1       misho    96070:         }
                   96071: 
1.1.1.2 ! misho    96072:         // info == true
        !          96073:         if (!isset($packagelist['pi'])) {
        !          96074:             return array();
1.1       misho    96075:         }
                   96076: 
1.1.1.2 ! misho    96077:         if (!is_array($packagelist['pi']) ||
        !          96078:             !isset($packagelist['pi'][0])) { // only 1 pkg
        !          96079:             $packagelist_pre = array($packagelist['pi']);
        !          96080:         } else {
        !          96081:             $packagelist_pre = $packagelist['pi'];
        !          96082:         }
1.1       misho    96083: 
1.1.1.2 ! misho    96084:         $packagelist = array();
        !          96085:         foreach ($packagelist_pre as $i => $item) {
        !          96086:             // compatibility with r/<latest.txt>.xml
        !          96087:             if (isset($item['a']['r'][0])) {
        !          96088:                 // multiple releases
        !          96089:                 $item['p']['v'] = $item['a']['r'][0]['v'];
        !          96090:                 $item['p']['st'] = $item['a']['r'][0]['s'];
        !          96091:             } elseif (isset($item['a'])) {
        !          96092:                 // first and only release
        !          96093:                 $item['p']['v'] = $item['a']['r']['v'];
        !          96094:                 $item['p']['st'] = $item['a']['r']['s'];
1.1       misho    96095:             }
                   96096: 
1.1.1.2 ! misho    96097:             $packagelist[$i] = array('attribs' => $item['p']['r'],
        !          96098:                                      '_content' => $item['p']['n'],
        !          96099:                                      'info' => $item['p']);
1.1       misho    96100:         }
                   96101: 
1.1.1.2 ! misho    96102:         return $packagelist;
        !          96103:     }
1.1       misho    96104: 
1.1.1.2 ! misho    96105:     /**
        !          96106:      * Return an array containing all of the states that are more stable than
        !          96107:      * or equal to the passed in state
        !          96108:      *
        !          96109:      * @param string Release state
        !          96110:      * @param boolean Determines whether to include $state in the list
        !          96111:      * @return false|array False if $state is not a valid release state
        !          96112:      */
        !          96113:     function betterStates($state, $include = false)
        !          96114:     {
        !          96115:         static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
        !          96116:         $i = array_search($state, $states);
        !          96117:         if ($i === false) {
        !          96118:             return false;
1.1       misho    96119:         }
1.1.1.2 ! misho    96120:         if ($include) {
        !          96121:             $i--;
1.1       misho    96122:         }
1.1.1.2 ! misho    96123:         return array_slice($states, $i + 1);
1.1       misho    96124:     }
                   96125: }
1.1.1.2 ! misho    96126: ?><?php
1.1       misho    96127: /**
1.1.1.2 ! misho    96128:  * PEAR_REST_13
1.1       misho    96129:  *
                   96130:  * PHP versions 4 and 5
                   96131:  *
                   96132:  * @category   pear
                   96133:  * @package    PEAR
                   96134:  * @author     Greg Beaver <cellog@php.net>
                   96135:  * @copyright  1997-2009 The Authors
                   96136:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    96137:  * @version    CVS: $Id: 13.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    96138:  * @link       http://pear.php.net/package/PEAR
                   96139:  * @since      File available since Release 1.4.0a12
                   96140:  */
                   96141: 
                   96142: /**
                   96143:  * For downloading REST xml/txt files
                   96144:  */
                   96145: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/REST.php';
1.1.1.2 ! misho    96146: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/REST/10.php';
1.1       misho    96147: 
                   96148: /**
1.1.1.2 ! misho    96149:  * Implement REST 1.3
1.1       misho    96150:  *
                   96151:  * @category   pear
                   96152:  * @package    PEAR
                   96153:  * @author     Greg Beaver <cellog@php.net>
                   96154:  * @copyright  1997-2009 The Authors
                   96155:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    96156:  * @version    Release: 1.9.4
1.1       misho    96157:  * @link       http://pear.php.net/package/PEAR
1.1.1.2 ! misho    96158:  * @since      Class available since Release 1.4.0a12
        !          96159:  */
        !          96160: class PEAR_REST_13 extends PEAR_REST_10
        !          96161: {
1.1       misho    96162:     /**
                   96163:      * Retrieve information about a remote package to be downloaded from a REST server
                   96164:      *
1.1.1.2 ! misho    96165:      * This is smart enough to resolve the minimum PHP version dependency prior to download
1.1       misho    96166:      * @param string $base The uri to prepend to all REST calls
                   96167:      * @param array $packageinfo an array of format:
                   96168:      * <pre>
                   96169:      *  array(
                   96170:      *   'package' => 'packagename',
                   96171:      *   'channel' => 'channelname',
                   96172:      *  ['state' => 'alpha' (or valid state),]
                   96173:      *  -or-
                   96174:      *  ['version' => '1.whatever']
                   96175:      * </pre>
                   96176:      * @param string $prefstate Current preferred_state config variable value
                   96177:      * @param bool $installed the installed version of this package to compare against
                   96178:      * @return array|false|PEAR_Error see {@link _returnDownloadURL()}
                   96179:      */
                   96180:     function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false)
                   96181:     {
                   96182:         $states = $this->betterStates($prefstate, true);
                   96183:         if (!$states) {
                   96184:             return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
                   96185:         }
                   96186: 
                   96187:         $channel  = $packageinfo['channel'];
                   96188:         $package  = $packageinfo['package'];
                   96189:         $state    = isset($packageinfo['state'])   ? $packageinfo['state']   : null;
                   96190:         $version  = isset($packageinfo['version']) ? $packageinfo['version'] : null;
1.1.1.2 ! misho    96191:         $restFile = $base . 'r/' . strtolower($package) . '/allreleases2.xml';
1.1       misho    96192: 
                   96193:         $info = $this->_rest->retrieveData($restFile, false, false, $channel);
                   96194:         if (PEAR::isError($info)) {
                   96195:             return PEAR::raiseError('No releases available for package "' .
                   96196:                 $channel . '/' . $package . '"');
                   96197:         }
                   96198: 
                   96199:         if (!isset($info['r'])) {
                   96200:             return false;
                   96201:         }
                   96202: 
                   96203:         $release = $found = false;
                   96204:         if (!is_array($info['r']) || !isset($info['r'][0])) {
                   96205:             $info['r'] = array($info['r']);
                   96206:         }
                   96207: 
1.1.1.2 ! misho    96208:         $skippedphp = false;
1.1       misho    96209:         foreach ($info['r'] as $release) {
                   96210:             if (!isset($this->_rest->_options['force']) && ($installed &&
                   96211:                   version_compare($release['v'], $installed, '<'))) {
                   96212:                 continue;
                   96213:             }
                   96214: 
                   96215:             if (isset($state)) {
                   96216:                 // try our preferred state first
                   96217:                 if ($release['s'] == $state) {
1.1.1.2 ! misho    96218:                     if (!isset($version) && version_compare($release['m'], phpversion(), '>')) {
        !          96219:                         // skip releases that require a PHP version newer than our PHP version
        !          96220:                         $skippedphp = $release;
        !          96221:                         continue;
        !          96222:                     }
1.1       misho    96223:                     $found = true;
                   96224:                     break;
                   96225:                 }
1.1.1.2 ! misho    96226: 
1.1       misho    96227:                 // see if there is something newer and more stable
                   96228:                 // bug #7221
                   96229:                 if (in_array($release['s'], $this->betterStates($state), true)) {
1.1.1.2 ! misho    96230:                     if (!isset($version) && version_compare($release['m'], phpversion(), '>')) {
        !          96231:                         // skip releases that require a PHP version newer than our PHP version
        !          96232:                         $skippedphp = $release;
        !          96233:                         continue;
        !          96234:                     }
1.1       misho    96235:                     $found = true;
                   96236:                     break;
                   96237:                 }
                   96238:             } elseif (isset($version)) {
                   96239:                 if ($release['v'] == $version) {
1.1.1.2 ! misho    96240:                     if (!isset($this->_rest->_options['force']) &&
        !          96241:                           !isset($version) &&
        !          96242:                           version_compare($release['m'], phpversion(), '>')) {
        !          96243:                         // skip releases that require a PHP version newer than our PHP version
        !          96244:                         $skippedphp = $release;
        !          96245:                         continue;
        !          96246:                     }
1.1       misho    96247:                     $found = true;
                   96248:                     break;
                   96249:                 }
                   96250:             } else {
                   96251:                 if (in_array($release['s'], $states)) {
1.1.1.2 ! misho    96252:                     if (version_compare($release['m'], phpversion(), '>')) {
        !          96253:                         // skip releases that require a PHP version newer than our PHP version
        !          96254:                         $skippedphp = $release;
        !          96255:                         continue;
        !          96256:                     }
1.1       misho    96257:                     $found = true;
                   96258:                     break;
                   96259:                 }
                   96260:             }
                   96261:         }
                   96262: 
1.1.1.2 ! misho    96263:         if (!$found && $skippedphp) {
        !          96264:             $found = null;
        !          96265:         }
        !          96266: 
        !          96267:         return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel);
1.1       misho    96268:     }
                   96269: 
                   96270:     function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage,
                   96271:                                $prefstate = 'stable', $installed = false, $channel = false)
                   96272:     {
                   96273:         $states = $this->betterStates($prefstate, true);
                   96274:         if (!$states) {
                   96275:             return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
                   96276:         }
                   96277: 
                   96278:         $channel  = $dependency['channel'];
                   96279:         $package  = $dependency['name'];
                   96280:         $state    = isset($dependency['state'])   ? $dependency['state']   : null;
                   96281:         $version  = isset($dependency['version']) ? $dependency['version'] : null;
1.1.1.2 ! misho    96282:         $restFile = $base . 'r/' . strtolower($package) .'/allreleases2.xml';
1.1       misho    96283: 
                   96284:         $info = $this->_rest->retrieveData($restFile, false, false, $channel);
                   96285:         if (PEAR::isError($info)) {
                   96286:             return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package']
                   96287:                 . '" dependency "' . $channel . '/' . $package . '" has no releases');
                   96288:         }
                   96289: 
                   96290:         if (!is_array($info) || !isset($info['r'])) {
                   96291:             return false;
                   96292:         }
                   96293: 
                   96294:         $exclude = array();
                   96295:         $min = $max = $recommended = false;
                   96296:         if ($xsdversion == '1.0') {
1.1.1.2 ! misho    96297:             $pinfo['package'] = $dependency['name'];
        !          96298:             $pinfo['channel'] = 'pear.php.net'; // this is always true - don't change this
1.1       misho    96299:             switch ($dependency['rel']) {
                   96300:                 case 'ge' :
                   96301:                     $min = $dependency['version'];
                   96302:                 break;
                   96303:                 case 'gt' :
                   96304:                     $min = $dependency['version'];
                   96305:                     $exclude = array($dependency['version']);
                   96306:                 break;
                   96307:                 case 'eq' :
                   96308:                     $recommended = $dependency['version'];
                   96309:                 break;
                   96310:                 case 'lt' :
                   96311:                     $max = $dependency['version'];
                   96312:                     $exclude = array($dependency['version']);
                   96313:                 break;
                   96314:                 case 'le' :
                   96315:                     $max = $dependency['version'];
                   96316:                 break;
                   96317:                 case 'ne' :
                   96318:                     $exclude = array($dependency['version']);
                   96319:                 break;
                   96320:             }
                   96321:         } else {
1.1.1.2 ! misho    96322:             $pinfo['package'] = $dependency['name'];
1.1       misho    96323:             $min = isset($dependency['min']) ? $dependency['min'] : false;
                   96324:             $max = isset($dependency['max']) ? $dependency['max'] : false;
                   96325:             $recommended = isset($dependency['recommended']) ?
                   96326:                 $dependency['recommended'] : false;
                   96327:             if (isset($dependency['exclude'])) {
                   96328:                 if (!isset($dependency['exclude'][0])) {
                   96329:                     $exclude = array($dependency['exclude']);
                   96330:                 }
                   96331:             }
                   96332:         }
1.1.1.2 ! misho    96333: 
        !          96334:         $skippedphp = $found = $release = false;
1.1       misho    96335:         if (!is_array($info['r']) || !isset($info['r'][0])) {
                   96336:             $info['r'] = array($info['r']);
                   96337:         }
1.1.1.2 ! misho    96338: 
1.1       misho    96339:         foreach ($info['r'] as $release) {
                   96340:             if (!isset($this->_rest->_options['force']) && ($installed &&
                   96341:                   version_compare($release['v'], $installed, '<'))) {
                   96342:                 continue;
                   96343:             }
1.1.1.2 ! misho    96344: 
1.1       misho    96345:             if (in_array($release['v'], $exclude)) { // skip excluded versions
                   96346:                 continue;
                   96347:             }
1.1.1.2 ! misho    96348: 
1.1       misho    96349:             // allow newer releases to say "I'm OK with the dependent package"
                   96350:             if ($xsdversion == '2.0' && isset($release['co'])) {
                   96351:                 if (!is_array($release['co']) || !isset($release['co'][0])) {
                   96352:                     $release['co'] = array($release['co']);
                   96353:                 }
1.1.1.2 ! misho    96354: 
1.1       misho    96355:                 foreach ($release['co'] as $entry) {
                   96356:                     if (isset($entry['x']) && !is_array($entry['x'])) {
                   96357:                         $entry['x'] = array($entry['x']);
                   96358:                     } elseif (!isset($entry['x'])) {
                   96359:                         $entry['x'] = array();
                   96360:                     }
1.1.1.2 ! misho    96361: 
1.1       misho    96362:                     if ($entry['c'] == $deppackage['channel'] &&
                   96363:                           strtolower($entry['p']) == strtolower($deppackage['package']) &&
                   96364:                           version_compare($deppackage['version'], $entry['min'], '>=') &&
                   96365:                           version_compare($deppackage['version'], $entry['max'], '<=') &&
                   96366:                           !in_array($release['v'], $entry['x'])) {
1.1.1.2 ! misho    96367:                         if (version_compare($release['m'], phpversion(), '>')) {
        !          96368:                             // skip dependency releases that require a PHP version
        !          96369:                             // newer than our PHP version
        !          96370:                             $skippedphp = $release;
        !          96371:                             continue;
        !          96372:                         }
        !          96373: 
1.1       misho    96374:                         $recommended = $release['v'];
                   96375:                         break;
                   96376:                     }
                   96377:                 }
                   96378:             }
1.1.1.2 ! misho    96379: 
1.1       misho    96380:             if ($recommended) {
                   96381:                 if ($release['v'] != $recommended) { // if we want a specific
                   96382:                     // version, then skip all others
                   96383:                     continue;
1.1.1.2 ! misho    96384:                 }
        !          96385: 
        !          96386:                 if (!in_array($release['s'], $states)) {
        !          96387:                     // the stability is too low, but we must return the
        !          96388:                     // recommended version if possible
        !          96389:                     return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel);
1.1       misho    96390:                 }
                   96391:             }
1.1.1.2 ! misho    96392: 
1.1       misho    96393:             if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions
                   96394:                 continue;
                   96395:             }
1.1.1.2 ! misho    96396: 
1.1       misho    96397:             if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions
                   96398:                 continue;
                   96399:             }
1.1.1.2 ! misho    96400: 
1.1       misho    96401:             if ($installed && version_compare($release['v'], $installed, '<')) {
                   96402:                 continue;
                   96403:             }
1.1.1.2 ! misho    96404: 
1.1       misho    96405:             if (in_array($release['s'], $states)) { // if in the preferred state...
1.1.1.2 ! misho    96406:                 if (version_compare($release['m'], phpversion(), '>')) {
        !          96407:                     // skip dependency releases that require a PHP version
        !          96408:                     // newer than our PHP version
        !          96409:                     $skippedphp = $release;
        !          96410:                     continue;
        !          96411:                 }
        !          96412: 
1.1       misho    96413:                 $found = true; // ... then use it
                   96414:                 break;
                   96415:             }
                   96416:         }
1.1.1.2 ! misho    96417: 
        !          96418:         if (!$found && $skippedphp) {
        !          96419:             $found = null;
        !          96420:         }
        !          96421: 
        !          96422:         return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel);
1.1       misho    96423:     }
1.1.1.2 ! misho    96424: }<?php
        !          96425: /**
        !          96426:  * PEAR_RunTest
        !          96427:  *
        !          96428:  * PHP versions 4 and 5
        !          96429:  *
        !          96430:  * @category   pear
        !          96431:  * @package    PEAR
        !          96432:  * @author     Tomas V.V.Cox <cox@idecnet.com>
        !          96433:  * @author     Greg Beaver <cellog@php.net>
        !          96434:  * @copyright  1997-2009 The Authors
        !          96435:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          96436:  * @version    CVS: $Id: RunTest.php 313024 2011-07-06 19:51:24Z dufuz $
        !          96437:  * @link       http://pear.php.net/package/PEAR
        !          96438:  * @since      File available since Release 1.3.3
        !          96439:  */
        !          96440: 
        !          96441: /**
        !          96442:  * for error handling
        !          96443:  */
        !          96444: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
        !          96445: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Config.php';
        !          96446: 
        !          96447: define('DETAILED', 1);
        !          96448: putenv("PHP_PEAR_RUNTESTS=1");
1.1       misho    96449: 
1.1.1.2 ! misho    96450: /**
        !          96451:  * Simplified version of PHP's test suite
        !          96452:  *
        !          96453:  * Try it with:
        !          96454:  *
        !          96455:  * $ php -r 'include "../PEAR/RunTest.php"; $t=new PEAR_RunTest; $o=$t->run("./pear_system.phpt");print_r($o);'
        !          96456:  *
        !          96457:  *
        !          96458:  * @category   pear
        !          96459:  * @package    PEAR
        !          96460:  * @author     Tomas V.V.Cox <cox@idecnet.com>
        !          96461:  * @author     Greg Beaver <cellog@php.net>
        !          96462:  * @copyright  1997-2009 The Authors
        !          96463:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
        !          96464:  * @version    Release: 1.9.4
        !          96465:  * @link       http://pear.php.net/package/PEAR
        !          96466:  * @since      Class available since Release 1.3.3
        !          96467:  */
        !          96468: class PEAR_RunTest
        !          96469: {
        !          96470:     var $_headers = array();
        !          96471:     var $_logger;
        !          96472:     var $_options;
        !          96473:     var $_php;
        !          96474:     var $tests_count;
        !          96475:     var $xdebug_loaded;
1.1       misho    96476:     /**
1.1.1.2 ! misho    96477:      * Saved value of php executable, used to reset $_php when we
        !          96478:      * have a test that uses cgi
1.1       misho    96479:      *
1.1.1.2 ! misho    96480:      * @var unknown_type
1.1       misho    96481:      */
1.1.1.2 ! misho    96482:     var $_savephp;
        !          96483:     var $ini_overwrites = array(
        !          96484:         'output_handler=',
        !          96485:         'open_basedir=',
        !          96486:         'safe_mode=0',
        !          96487:         'disable_functions=',
        !          96488:         'output_buffering=Off',
        !          96489:         'display_errors=1',
        !          96490:         'log_errors=0',
        !          96491:         'html_errors=0',
        !          96492:         'track_errors=1',
        !          96493:         'report_memleaks=0',
        !          96494:         'report_zend_debug=0',
        !          96495:         'docref_root=',
        !          96496:         'docref_ext=.html',
        !          96497:         'error_prepend_string=',
        !          96498:         'error_append_string=',
        !          96499:         'auto_prepend_file=',
        !          96500:         'auto_append_file=',
        !          96501:         'magic_quotes_runtime=0',
        !          96502:         'xdebug.default_enable=0',
        !          96503:         'allow_url_fopen=1',
        !          96504:     );
        !          96505: 
        !          96506:     /**
        !          96507:      * An object that supports the PEAR_Common->log() signature, or null
        !          96508:      * @param PEAR_Common|null
        !          96509:      */
        !          96510:     function PEAR_RunTest($logger = null, $options = array())
1.1       misho    96511:     {
1.1.1.2 ! misho    96512:         if (!defined('E_DEPRECATED')) {
        !          96513:             define('E_DEPRECATED', 0);
1.1       misho    96514:         }
1.1.1.2 ! misho    96515:         if (!defined('E_STRICT')) {
        !          96516:             define('E_STRICT', 0);
        !          96517:         }
        !          96518:         $this->ini_overwrites[] = 'error_reporting=' . (E_ALL & ~(E_DEPRECATED | E_STRICT));
        !          96519:         if (is_null($logger)) {
        !          96520:             require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
        !          96521:             $logger = new PEAR_Common;
1.1       misho    96522:         }
1.1.1.2 ! misho    96523:         $this->_logger  = $logger;
        !          96524:         $this->_options = $options;
1.1       misho    96525: 
1.1.1.2 ! misho    96526:         $conf = &PEAR_Config::singleton();
        !          96527:         $this->_php = $conf->get('php_bin');
        !          96528:     }
        !          96529: 
        !          96530:     /**
        !          96531:      * Taken from php-src/run-tests.php
        !          96532:      *
        !          96533:      * @param string $commandline command name
        !          96534:      * @param array $env
        !          96535:      * @param string $stdin standard input to pass to the command
        !          96536:      * @return unknown
        !          96537:      */
        !          96538:     function system_with_timeout($commandline, $env = null, $stdin = null)
        !          96539:     {
        !          96540:         $data = '';
        !          96541:         if (version_compare(phpversion(), '5.0.0', '<')) {
        !          96542:             $proc = proc_open($commandline, array(
        !          96543:                 0 => array('pipe', 'r'),
        !          96544:                 1 => array('pipe', 'w'),
        !          96545:                 2 => array('pipe', 'w')
        !          96546:                 ), $pipes);
        !          96547:         } else {
        !          96548:             $proc = proc_open($commandline, array(
        !          96549:                 0 => array('pipe', 'r'),
        !          96550:                 1 => array('pipe', 'w'),
        !          96551:                 2 => array('pipe', 'w')
        !          96552:                 ), $pipes, null, $env, array('suppress_errors' => true));
1.1       misho    96553:         }
                   96554: 
1.1.1.2 ! misho    96555:         if (!$proc) {
        !          96556:             return false;
1.1       misho    96557:         }
                   96558: 
1.1.1.2 ! misho    96559:         if (is_string($stdin)) {
        !          96560:             fwrite($pipes[0], $stdin);
1.1       misho    96561:         }
1.1.1.2 ! misho    96562:         fclose($pipes[0]);
1.1       misho    96563: 
1.1.1.2 ! misho    96564:         while (true) {
        !          96565:             /* hide errors from interrupted syscalls */
        !          96566:             $r = $pipes;
        !          96567:             $e = $w = null;
        !          96568:             $n = @stream_select($r, $w, $e, 60);
        !          96569: 
        !          96570:             if ($n === 0) {
        !          96571:                 /* timed out */
        !          96572:                 $data .= "\n ** ERROR: process timed out **\n";
        !          96573:                 proc_terminate($proc);
        !          96574:                 return array(1234567890, $data);
        !          96575:             } else if ($n > 0) {
        !          96576:                 $line = fread($pipes[1], 8192);
        !          96577:                 if (strlen($line) == 0) {
        !          96578:                     /* EOF */
        !          96579:                     break;
        !          96580:                 }
        !          96581:                 $data .= $line;
        !          96582:             }
        !          96583:         }
        !          96584:         if (function_exists('proc_get_status')) {
        !          96585:             $stat = proc_get_status($proc);
        !          96586:             if ($stat['signaled']) {
        !          96587:                 $data .= "\nTermsig=".$stat['stopsig'];
        !          96588:             }
        !          96589:         }
        !          96590:         $code = proc_close($proc);
        !          96591:         if (function_exists('proc_get_status')) {
        !          96592:             $code = $stat['exitcode'];
1.1       misho    96593:         }
1.1.1.2 ! misho    96594:         return array($code, $data);
        !          96595:     }
1.1       misho    96596: 
1.1.1.2 ! misho    96597:     /**
        !          96598:      * Turns a PHP INI string into an array
        !          96599:      *
        !          96600:      * Turns -d "include_path=/foo/bar" into this:
        !          96601:      * array(
        !          96602:      *   'include_path' => array(
        !          96603:      *          'operator' => '-d',
        !          96604:      *          'value'    => '/foo/bar',
        !          96605:      *   )
        !          96606:      * )
        !          96607:      * Works both with quotes and without
        !          96608:      *
        !          96609:      * @param string an PHP INI string, -d "include_path=/foo/bar"
        !          96610:      * @return array
        !          96611:      */
        !          96612:     function iniString2array($ini_string)
        !          96613:     {
        !          96614:         if (!$ini_string) {
        !          96615:             return array();
1.1       misho    96616:         }
1.1.1.2 ! misho    96617:         $split = preg_split('/[\s]|=/', $ini_string, -1, PREG_SPLIT_NO_EMPTY);
        !          96618:         $key   = $split[1][0] == '"'                     ? substr($split[1], 1)     : $split[1];
        !          96619:         $value = $split[2][strlen($split[2]) - 1] == '"' ? substr($split[2], 0, -1) : $split[2];
        !          96620:         // FIXME review if this is really the struct to go with
        !          96621:         $array = array($key => array('operator' => $split[0], 'value' => $value));
        !          96622:         return $array;
        !          96623:     }
1.1       misho    96624: 
1.1.1.2 ! misho    96625:     function settings2array($settings, $ini_settings)
        !          96626:     {
        !          96627:         foreach ($settings as $setting) {
        !          96628:             if (strpos($setting, '=') !== false) {
        !          96629:                 $setting = explode('=', $setting, 2);
        !          96630:                 $name  = trim(strtolower($setting[0]));
        !          96631:                 $value = trim($setting[1]);
        !          96632:                 $ini_settings[$name] = $value;
1.1       misho    96633:             }
1.1.1.2 ! misho    96634:         }
        !          96635:         return $ini_settings;
        !          96636:     }
1.1       misho    96637: 
1.1.1.2 ! misho    96638:     function settings2params($ini_settings)
        !          96639:     {
        !          96640:         $settings = '';
        !          96641:         foreach ($ini_settings as $name => $value) {
        !          96642:             if (is_array($value)) {
        !          96643:                 $operator = $value['operator'];
        !          96644:                 $value    = $value['value'];
        !          96645:             } else {
        !          96646:                 $operator = '-d';
1.1       misho    96647:             }
1.1.1.2 ! misho    96648:             $value = addslashes($value);
        !          96649:             $settings .= " $operator \"$name=$value\"";
        !          96650:         }
        !          96651:         return $settings;
        !          96652:     }
1.1       misho    96653: 
1.1.1.2 ! misho    96654:     function _preparePhpBin($php, $file, $ini_settings)
        !          96655:     {
        !          96656:         $file = escapeshellarg($file);
        !          96657:         // This was fixed in php 5.3 and is not needed after that
        !          96658:         if (OS_WINDOWS && version_compare(PHP_VERSION, '5.3', '<')) {
        !          96659:             $cmd = '"'.escapeshellarg($php).' '.$ini_settings.' -f ' . $file .'"';
        !          96660:         } else {
        !          96661:             $cmd = $php . $ini_settings . ' -f ' . $file;
        !          96662:         }
        !          96663: 
        !          96664:         return $cmd;
        !          96665:     }
        !          96666: 
        !          96667:     function runPHPUnit($file, $ini_settings = '')
        !          96668:     {
        !          96669:         if (!file_exists($file) && file_exists(getcwd() . DIRECTORY_SEPARATOR . $file)) {
        !          96670:             $file = realpath(getcwd() . DIRECTORY_SEPARATOR . $file);
        !          96671:         } elseif (file_exists($file)) {
        !          96672:             $file = realpath($file);
        !          96673:         }
        !          96674: 
        !          96675:         $cmd = $this->_preparePhpBin($this->_php, $file, $ini_settings);
        !          96676:         if (isset($this->_logger)) {
        !          96677:             $this->_logger->log(2, 'Running command "' . $cmd . '"');
        !          96678:         }
        !          96679: 
        !          96680:         $savedir = getcwd(); // in case the test moves us around
        !          96681:         chdir(dirname($file));
        !          96682:         echo `$cmd`;
        !          96683:         chdir($savedir);
        !          96684:         return 'PASSED'; // we have no way of knowing this information so assume passing
        !          96685:     }
        !          96686: 
        !          96687:     /**
        !          96688:      * Runs an individual test case.
        !          96689:      *
        !          96690:      * @param string       The filename of the test
        !          96691:      * @param array|string INI settings to be applied to the test run
        !          96692:      * @param integer      Number what the current running test is of the
        !          96693:      *                     whole test suite being runned.
        !          96694:      *
        !          96695:      * @return string|object Returns PASSED, WARNED, FAILED depending on how the
        !          96696:      *                       test came out.
        !          96697:      *                       PEAR Error when the tester it self fails
        !          96698:      */
        !          96699:     function run($file, $ini_settings = array(), $test_number = 1)
        !          96700:     {
        !          96701:         if (isset($this->_savephp)) {
        !          96702:             $this->_php = $this->_savephp;
        !          96703:             unset($this->_savephp);
        !          96704:         }
        !          96705:         if (empty($this->_options['cgi'])) {
        !          96706:             // try to see if php-cgi is in the path
        !          96707:             $res = $this->system_with_timeout('php-cgi -v');
        !          96708:             if (false !== $res && !(is_array($res) && in_array($res[0], array(-1, 127)))) {
        !          96709:                 $this->_options['cgi'] = 'php-cgi';
1.1       misho    96710:             }
1.1.1.2 ! misho    96711:         }
        !          96712:         if (1 < $len = strlen($this->tests_count)) {
        !          96713:             $test_number = str_pad($test_number, $len, ' ', STR_PAD_LEFT);
        !          96714:             $test_nr = "[$test_number/$this->tests_count] ";
        !          96715:         } else {
        !          96716:             $test_nr = '';
        !          96717:         }
1.1       misho    96718: 
1.1.1.2 ! misho    96719:         $file = realpath($file);
        !          96720:         $section_text = $this->_readFile($file);
        !          96721:         if (PEAR::isError($section_text)) {
        !          96722:             return $section_text;
        !          96723:         }
1.1       misho    96724: 
1.1.1.2 ! misho    96725:         if (isset($section_text['POST_RAW']) && isset($section_text['UPLOAD'])) {
        !          96726:             return PEAR::raiseError("Cannot contain both POST_RAW and UPLOAD in test file: $file");
        !          96727:         }
        !          96728: 
        !          96729:         $cwd = getcwd();
        !          96730: 
        !          96731:         $pass_options = '';
        !          96732:         if (!empty($this->_options['ini'])) {
        !          96733:             $pass_options = $this->_options['ini'];
        !          96734:         }
        !          96735: 
        !          96736:         if (is_string($ini_settings)) {
        !          96737:             $ini_settings = $this->iniString2array($ini_settings);
        !          96738:         }
        !          96739: 
        !          96740:         $ini_settings = $this->settings2array($this->ini_overwrites, $ini_settings);
        !          96741:         if ($section_text['INI']) {
        !          96742:             if (strpos($section_text['INI'], '{PWD}') !== false) {
        !          96743:                 $section_text['INI'] = str_replace('{PWD}', dirname($file), $section_text['INI']);
1.1       misho    96744:             }
1.1.1.2 ! misho    96745:             $ini = preg_split( "/[\n\r]+/", $section_text['INI']);
        !          96746:             $ini_settings = $this->settings2array($ini, $ini_settings);
        !          96747:         }
        !          96748:         $ini_settings = $this->settings2params($ini_settings);
        !          96749:         $shortname = str_replace($cwd . DIRECTORY_SEPARATOR, '', $file);
1.1       misho    96750: 
1.1.1.2 ! misho    96751:         $tested = trim($section_text['TEST']);
        !          96752:         $tested.= !isset($this->_options['simple']) ? "[$shortname]" : ' ';
        !          96753: 
        !          96754:         if (!empty($section_text['POST']) || !empty($section_text['POST_RAW']) ||
        !          96755:               !empty($section_text['UPLOAD']) || !empty($section_text['GET']) ||
        !          96756:               !empty($section_text['COOKIE']) || !empty($section_text['EXPECTHEADERS'])) {
        !          96757:             if (empty($this->_options['cgi'])) {
        !          96758:                 if (!isset($this->_options['quiet'])) {
        !          96759:                     $this->_logger->log(0, "SKIP $test_nr$tested (reason: --cgi option needed for this test, type 'pear help run-tests')");
        !          96760:                 }
        !          96761:                 if (isset($this->_options['tapoutput'])) {
        !          96762:                     return array('ok', ' # skip --cgi option needed for this test, "pear help run-tests" for info');
        !          96763:                 }
        !          96764:                 return 'SKIPPED';
1.1       misho    96765:             }
1.1.1.2 ! misho    96766:             $this->_savephp = $this->_php;
        !          96767:             $this->_php = $this->_options['cgi'];
        !          96768:         }
1.1       misho    96769: 
1.1.1.2 ! misho    96770:         $temp_dir = realpath(dirname($file));
        !          96771:         $main_file_name = basename($file, 'phpt');
        !          96772:         $diff_filename     = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'diff';
        !          96773:         $log_filename      = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'log';
        !          96774:         $exp_filename      = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'exp';
        !          96775:         $output_filename   = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'out';
        !          96776:         $memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'mem';
        !          96777:         $temp_file         = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'php';
        !          96778:         $temp_skipif       = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'skip.php';
        !          96779:         $temp_clean        = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'clean.php';
        !          96780:         $tmp_post          = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.');
        !          96781: 
        !          96782:         // unlink old test results
        !          96783:         $this->_cleanupOldFiles($file);
        !          96784: 
        !          96785:         // Check if test should be skipped.
        !          96786:         $res  = $this->_runSkipIf($section_text, $temp_skipif, $tested, $ini_settings);
        !          96787:         if (count($res) != 2) {
        !          96788:             return $res;
1.1       misho    96789:         }
1.1.1.2 ! misho    96790:         $info = $res['info'];
        !          96791:         $warn = $res['warn'];
1.1       misho    96792: 
1.1.1.2 ! misho    96793:         // We've satisfied the preconditions - run the test!
        !          96794:         if (isset($this->_options['coverage']) && $this->xdebug_loaded) {
        !          96795:             $xdebug_file = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'xdebug';
        !          96796:             $text = "\n" . 'function coverage_shutdown() {' .
        !          96797:                     "\n" . '    $xdebug = var_export(xdebug_get_code_coverage(), true);';
        !          96798:             if (!function_exists('file_put_contents')) {
        !          96799:                 $text .= "\n" . '    $fh = fopen(\'' . $xdebug_file . '\', "wb");' .
        !          96800:                         "\n" . '    if ($fh !== false) {' .
        !          96801:                         "\n" . '        fwrite($fh, $xdebug);' .
        !          96802:                         "\n" . '        fclose($fh);' .
        !          96803:                         "\n" . '    }';
1.1       misho    96804:             } else {
1.1.1.2 ! misho    96805:                 $text .= "\n" . '    file_put_contents(\'' . $xdebug_file . '\', $xdebug);';
        !          96806:             }
        !          96807: 
        !          96808:             // Workaround for http://pear.php.net/bugs/bug.php?id=17292
        !          96809:             $lines             = explode("\n", $section_text['FILE']);
        !          96810:             $numLines          = count($lines);
        !          96811:             $namespace         = '';
        !          96812:             $coverage_shutdown = 'coverage_shutdown';
        !          96813: 
        !          96814:             if (
        !          96815:                 substr($lines[0], 0, 2) == '<?' ||
        !          96816:                 substr($lines[0], 0, 5) == '<?php'
        !          96817:             ) {
        !          96818:                 unset($lines[0]);
1.1       misho    96819:             }
                   96820: 
                   96821: 
1.1.1.2 ! misho    96822:             for ($i = 0; $i < $numLines; $i++) {
        !          96823:                 if (isset($lines[$i]) && substr($lines[$i], 0, 9) == 'namespace') {
        !          96824:                     $namespace         = substr($lines[$i], 10, -1);
        !          96825:                     $coverage_shutdown = $namespace . '\\coverage_shutdown';
        !          96826:                     $namespace         = "namespace " . $namespace . ";\n";
1.1       misho    96827: 
1.1.1.2 ! misho    96828:                     unset($lines[$i]);
        !          96829:                     break;
        !          96830:                 }
        !          96831:             }
1.1       misho    96832: 
1.1.1.2 ! misho    96833:             $text .= "\n    xdebug_stop_code_coverage();" .
        !          96834:                 "\n" . '} // end coverage_shutdown()' .
        !          96835:                 "\n\n" . 'register_shutdown_function("' . $coverage_shutdown . '");';
        !          96836:             $text .= "\n" . 'xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);' . "\n";
1.1       misho    96837: 
1.1.1.2 ! misho    96838:             $this->save_text($temp_file, "<?php\n" . $namespace . $text  . "\n" . implode("\n", $lines));
        !          96839:         } else {
        !          96840:             $this->save_text($temp_file, $section_text['FILE']);
1.1       misho    96841:         }
                   96842: 
1.1.1.2 ! misho    96843:         $args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : '';
        !          96844:         $cmd = $this->_preparePhpBin($this->_php, $temp_file, $ini_settings);
        !          96845:         $cmd.= "$args 2>&1";
        !          96846:         if (isset($this->_logger)) {
        !          96847:             $this->_logger->log(2, 'Running command "' . $cmd . '"');
1.1       misho    96848:         }
                   96849: 
1.1.1.2 ! misho    96850:         // Reset environment from any previous test.
        !          96851:         $env = $this->_resetEnv($section_text, $temp_file);
1.1       misho    96852: 
1.1.1.2 ! misho    96853:         $section_text = $this->_processUpload($section_text, $file);
        !          96854:         if (PEAR::isError($section_text)) {
        !          96855:             return $section_text;
1.1       misho    96856:         }
                   96857: 
1.1.1.2 ! misho    96858:         if (array_key_exists('POST_RAW', $section_text) && !empty($section_text['POST_RAW'])) {
        !          96859:             $post = trim($section_text['POST_RAW']);
        !          96860:             $raw_lines = explode("\n", $post);
1.1       misho    96861: 
1.1.1.2 ! misho    96862:             $request = '';
        !          96863:             $started = false;
        !          96864:             foreach ($raw_lines as $i => $line) {
        !          96865:                 if (empty($env['CONTENT_TYPE']) &&
        !          96866:                     preg_match('/^Content-Type:(.*)/i', $line, $res)) {
        !          96867:                     $env['CONTENT_TYPE'] = trim(str_replace("\r", '', $res[1]));
        !          96868:                     continue;
1.1       misho    96869:                 }
1.1.1.2 ! misho    96870:                 if ($started) {
        !          96871:                     $request .= "\n";
1.1       misho    96872:                 }
1.1.1.2 ! misho    96873:                 $started = true;
        !          96874:                 $request .= $line;
        !          96875:             }
1.1       misho    96876: 
1.1.1.2 ! misho    96877:             $env['CONTENT_LENGTH'] = strlen($request);
        !          96878:             $env['REQUEST_METHOD'] = 'POST';
1.1       misho    96879: 
1.1.1.2 ! misho    96880:             $this->save_text($tmp_post, $request);
        !          96881:             $cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post";
        !          96882:         } elseif (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
        !          96883:             $post = trim($section_text['POST']);
        !          96884:             $this->save_text($tmp_post, $post);
        !          96885:             $content_length = strlen($post);
1.1       misho    96886: 
1.1.1.2 ! misho    96887:             $env['REQUEST_METHOD'] = 'POST';
        !          96888:             $env['CONTENT_TYPE']   = 'application/x-www-form-urlencoded';
        !          96889:             $env['CONTENT_LENGTH'] = $content_length;
1.1       misho    96890: 
1.1.1.2 ! misho    96891:             $cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post";
1.1       misho    96892:         } else {
1.1.1.2 ! misho    96893:             $env['REQUEST_METHOD'] = 'GET';
        !          96894:             $env['CONTENT_TYPE']   = '';
        !          96895:             $env['CONTENT_LENGTH'] = '';
1.1       misho    96896:         }
                   96897: 
1.1.1.2 ! misho    96898:         if (OS_WINDOWS && isset($section_text['RETURNS'])) {
        !          96899:             ob_start();
        !          96900:             system($cmd, $return_value);
        !          96901:             $out = ob_get_contents();
        !          96902:             ob_end_clean();
        !          96903:             $section_text['RETURNS'] = (int) trim($section_text['RETURNS']);
        !          96904:             $returnfail = ($return_value != $section_text['RETURNS']);
        !          96905:         } else {
        !          96906:             $returnfail = false;
        !          96907:             $stdin = isset($section_text['STDIN']) ? $section_text['STDIN'] : null;
        !          96908:             $out = $this->system_with_timeout($cmd, $env, $stdin);
        !          96909:             $return_value = $out[0];
        !          96910:             $out = $out[1];
1.1       misho    96911:         }
                   96912: 
1.1.1.2 ! misho    96913:         $output = preg_replace('/\r\n/', "\n", trim($out));
1.1       misho    96914: 
1.1.1.2 ! misho    96915:         if (isset($tmp_post) && realpath($tmp_post) && file_exists($tmp_post)) {
        !          96916:             @unlink(realpath($tmp_post));
1.1       misho    96917:         }
1.1.1.2 ! misho    96918:         chdir($cwd); // in case the test moves us around
1.1       misho    96919: 
1.1.1.2 ! misho    96920:         $this->_testCleanup($section_text, $temp_clean);
        !          96921: 
        !          96922:         /* when using CGI, strip the headers from the output */
        !          96923:         $output = $this->_stripHeadersCGI($output);
        !          96924: 
        !          96925:         if (isset($section_text['EXPECTHEADERS'])) {
        !          96926:             $testheaders = $this->_processHeaders($section_text['EXPECTHEADERS']);
        !          96927:             $missing = array_diff_assoc($testheaders, $this->_headers);
        !          96928:             $changed = '';
        !          96929:             foreach ($missing as $header => $value) {
        !          96930:                 if (isset($this->_headers[$header])) {
        !          96931:                     $changed .= "-$header: $value\n+$header: ";
        !          96932:                     $changed .= $this->_headers[$header];
        !          96933:                 } else {
        !          96934:                     $changed .= "-$header: $value\n";
1.1       misho    96935:                 }
                   96936:             }
1.1.1.2 ! misho    96937:             if ($missing) {
        !          96938:                 // tack on failed headers to output:
        !          96939:                 $output .= "\n====EXPECTHEADERS FAILURE====:\n$changed";
1.1       misho    96940:             }
1.1.1.2 ! misho    96941:         }
        !          96942:         // Does the output match what is expected?
        !          96943:         do {
        !          96944:             if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) {
        !          96945:                 if (isset($section_text['EXPECTF'])) {
        !          96946:                     $wanted = trim($section_text['EXPECTF']);
1.1       misho    96947:                 } else {
1.1.1.2 ! misho    96948:                     $wanted = trim($section_text['EXPECTREGEX']);
1.1       misho    96949:                 }
1.1.1.2 ! misho    96950:                 $wanted_re = preg_replace('/\r\n/', "\n", $wanted);
        !          96951:                 if (isset($section_text['EXPECTF'])) {
        !          96952:                     $wanted_re = preg_quote($wanted_re, '/');
        !          96953:                     // Stick to basics
        !          96954:                     $wanted_re = str_replace("%s", ".+?", $wanted_re); //not greedy
        !          96955:                     $wanted_re = str_replace("%i", "[+\-]?[0-9]+", $wanted_re);
        !          96956:                     $wanted_re = str_replace("%d", "[0-9]+", $wanted_re);
        !          96957:                     $wanted_re = str_replace("%x", "[0-9a-fA-F]+", $wanted_re);
        !          96958:                     $wanted_re = str_replace("%f", "[+\-]?\.?[0-9]+\.?[0-9]*(E-?[0-9]+)?", $wanted_re);
        !          96959:                     $wanted_re = str_replace("%c", ".", $wanted_re);
        !          96960:                     // %f allows two points "-.0.0" but that is the best *simple* expression
1.1       misho    96961:                 }
1.1.1.2 ! misho    96962: 
        !          96963:     /* DEBUG YOUR REGEX HERE
        !          96964:             var_dump($wanted_re);
        !          96965:             print(str_repeat('=', 80) . "\n");
        !          96966:             var_dump($output);
        !          96967:     */
        !          96968:                 if (!$returnfail && preg_match("/^$wanted_re\$/s", $output)) {
        !          96969:                     if (file_exists($temp_file)) {
        !          96970:                         unlink($temp_file);
1.1       misho    96971:                     }
1.1.1.2 ! misho    96972:                     if (array_key_exists('FAIL', $section_text)) {
        !          96973:                         break;
1.1       misho    96974:                     }
1.1.1.2 ! misho    96975:                     if (!isset($this->_options['quiet'])) {
        !          96976:                         $this->_logger->log(0, "PASS $test_nr$tested$info");
1.1       misho    96977:                     }
1.1.1.2 ! misho    96978:                     if (isset($this->_options['tapoutput'])) {
        !          96979:                         return array('ok', ' - ' . $tested);
1.1       misho    96980:                     }
1.1.1.2 ! misho    96981:                     return 'PASSED';
1.1       misho    96982:                 }
1.1.1.2 ! misho    96983:             } else {
        !          96984:                 if (isset($section_text['EXPECTFILE'])) {
        !          96985:                     $f = $temp_dir . '/' . trim($section_text['EXPECTFILE']);
        !          96986:                     if (!($fp = @fopen($f, 'rb'))) {
        !          96987:                         return PEAR::raiseError('--EXPECTFILE-- section file ' .
        !          96988:                             $f . ' not found');
1.1       misho    96989:                     }
1.1.1.2 ! misho    96990:                     fclose($fp);
        !          96991:                     $section_text['EXPECT'] = file_get_contents($f);
1.1       misho    96992:                 }
1.1.1.2 ! misho    96993: 
        !          96994:                 if (isset($section_text['EXPECT'])) {
        !          96995:                     $wanted = preg_replace('/\r\n/', "\n", trim($section_text['EXPECT']));
        !          96996:                 } else {
        !          96997:                     $wanted = '';
1.1       misho    96998:                 }
1.1.1.2 ! misho    96999: 
        !          97000:                 // compare and leave on success
        !          97001:                 if (!$returnfail && 0 == strcmp($output, $wanted)) {
        !          97002:                     if (file_exists($temp_file)) {
        !          97003:                         unlink($temp_file);
        !          97004:                     }
        !          97005:                     if (array_key_exists('FAIL', $section_text)) {
        !          97006:                         break;
        !          97007:                     }
        !          97008:                     if (!isset($this->_options['quiet'])) {
        !          97009:                         $this->_logger->log(0, "PASS $test_nr$tested$info");
        !          97010:                     }
        !          97011:                     if (isset($this->_options['tapoutput'])) {
        !          97012:                         return array('ok', ' - ' . $tested);
1.1       misho    97013:                     }
1.1.1.2 ! misho    97014:                     return 'PASSED';
1.1       misho    97015:                 }
1.1.1.2 ! misho    97016:             }
        !          97017:         } while (false);
        !          97018: 
        !          97019:         if (array_key_exists('FAIL', $section_text)) {
        !          97020:             // we expect a particular failure
        !          97021:             // this is only used for testing PEAR_RunTest
        !          97022:             $expectf  = isset($section_text['EXPECTF']) ? $wanted_re : null;
        !          97023:             $faildiff = $this->generate_diff($wanted, $output, null, $expectf);
        !          97024:             $faildiff = preg_replace('/\r/', '', $faildiff);
        !          97025:             $wanted   = preg_replace('/\r/', '', trim($section_text['FAIL']));
        !          97026:             if ($faildiff == $wanted) {
        !          97027:                 if (!isset($this->_options['quiet'])) {
        !          97028:                     $this->_logger->log(0, "PASS $test_nr$tested$info");
1.1       misho    97029:                 }
1.1.1.2 ! misho    97030:                 if (isset($this->_options['tapoutput'])) {
        !          97031:                     return array('ok', ' - ' . $tested);
1.1       misho    97032:                 }
1.1.1.2 ! misho    97033:                 return 'PASSED';
        !          97034:             }
        !          97035:             unset($section_text['EXPECTF']);
        !          97036:             $output = $faildiff;
        !          97037:             if (isset($section_text['RETURNS'])) {
        !          97038:                 return PEAR::raiseError('Cannot have both RETURNS and FAIL in the same test: ' .
        !          97039:                     $file);
        !          97040:             }
        !          97041:         }
        !          97042: 
        !          97043:         // Test failed so we need to report details.
        !          97044:         $txt = $warn ? 'WARN ' : 'FAIL ';
        !          97045:         $this->_logger->log(0, $txt . $test_nr . $tested . $info);
        !          97046: 
        !          97047:         // write .exp
        !          97048:         $res = $this->_writeLog($exp_filename, $wanted);
        !          97049:         if (PEAR::isError($res)) {
        !          97050:             return $res;
        !          97051:         }
        !          97052: 
        !          97053:         // write .out
        !          97054:         $res = $this->_writeLog($output_filename, $output);
        !          97055:         if (PEAR::isError($res)) {
        !          97056:             return $res;
        !          97057:         }
        !          97058: 
        !          97059:         // write .diff
        !          97060:         $returns = isset($section_text['RETURNS']) ?
        !          97061:                         array(trim($section_text['RETURNS']), $return_value) : null;
        !          97062:         $expectf = isset($section_text['EXPECTF']) ? $wanted_re : null;
        !          97063:         $data = $this->generate_diff($wanted, $output, $returns, $expectf);
        !          97064:         $res  = $this->_writeLog($diff_filename, $data);
        !          97065:         if (PEAR::isError($res)) {
        !          97066:             return $res;
        !          97067:         }
        !          97068: 
        !          97069:         // write .log
        !          97070:         $data = "
        !          97071: ---- EXPECTED OUTPUT
        !          97072: $wanted
        !          97073: ---- ACTUAL OUTPUT
        !          97074: $output
        !          97075: ---- FAILED
        !          97076: ";
        !          97077: 
        !          97078:         if ($returnfail) {
        !          97079:             $data .= "
        !          97080: ---- EXPECTED RETURN
        !          97081: $section_text[RETURNS]
        !          97082: ---- ACTUAL RETURN
        !          97083: $return_value
        !          97084: ";
        !          97085:         }
        !          97086: 
        !          97087:         $res = $this->_writeLog($log_filename, $data);
        !          97088:         if (PEAR::isError($res)) {
        !          97089:             return $res;
        !          97090:         }
        !          97091: 
        !          97092:         if (isset($this->_options['tapoutput'])) {
        !          97093:             $wanted = explode("\n", $wanted);
        !          97094:             $wanted = "# Expected output:\n#\n#" . implode("\n#", $wanted);
        !          97095:             $output = explode("\n", $output);
        !          97096:             $output = "#\n#\n# Actual output:\n#\n#" . implode("\n#", $output);
        !          97097:             return array($wanted . $output . 'not ok', ' - ' . $tested);
        !          97098:         }
        !          97099:         return $warn ? 'WARNED' : 'FAILED';
        !          97100:     }
        !          97101: 
        !          97102:     function generate_diff($wanted, $output, $rvalue, $wanted_re)
        !          97103:     {
        !          97104:         $w  = explode("\n", $wanted);
        !          97105:         $o  = explode("\n", $output);
        !          97106:         $wr = explode("\n", $wanted_re);
        !          97107:         $w1 = array_diff_assoc($w, $o);
        !          97108:         $o1 = array_diff_assoc($o, $w);
        !          97109:         $o2 = $w2 = array();
        !          97110:         foreach ($w1 as $idx => $val) {
        !          97111:             if (!$wanted_re || !isset($wr[$idx]) || !isset($o1[$idx]) ||
        !          97112:                   !preg_match('/^' . $wr[$idx] . '\\z/', $o1[$idx])) {
        !          97113:                 $w2[sprintf("%03d<", $idx)] = sprintf("%03d- ", $idx + 1) . $val;
        !          97114:             }
        !          97115:         }
        !          97116:         foreach ($o1 as $idx => $val) {
        !          97117:             if (!$wanted_re || !isset($wr[$idx]) ||
        !          97118:                   !preg_match('/^' . $wr[$idx] . '\\z/', $val)) {
        !          97119:                 $o2[sprintf("%03d>", $idx)] = sprintf("%03d+ ", $idx + 1) . $val;
1.1       misho    97120:             }
                   97121:         }
1.1.1.2 ! misho    97122:         $diff = array_merge($w2, $o2);
        !          97123:         ksort($diff);
        !          97124:         $extra = $rvalue ? "##EXPECTED: $rvalue[0]\r\n##RETURNED: $rvalue[1]" : '';
        !          97125:         return implode("\r\n", $diff) . $extra;
1.1       misho    97126:     }
                   97127: 
1.1.1.2 ! misho    97128:     //  Write the given text to a temporary file, and return the filename.
        !          97129:     function save_text($filename, $text)
1.1       misho    97130:     {
1.1.1.2 ! misho    97131:         if (!$fp = fopen($filename, 'w')) {
        !          97132:             return PEAR::raiseError("Cannot open file '" . $filename . "' (save_text)");
1.1       misho    97133:         }
1.1.1.2 ! misho    97134:         fwrite($fp, $text);
        !          97135:         fclose($fp);
        !          97136:     if (1 < DETAILED) echo "
        !          97137: FILE $filename {{{
        !          97138: $text
        !          97139: }}}
        !          97140: ";
        !          97141:     }
1.1       misho    97142: 
1.1.1.2 ! misho    97143:     function _cleanupOldFiles($file)
        !          97144:     {
        !          97145:         $temp_dir = realpath(dirname($file));
        !          97146:         $mainFileName = basename($file, 'phpt');
        !          97147:         $diff_filename     = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'diff';
        !          97148:         $log_filename      = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'log';
        !          97149:         $exp_filename      = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'exp';
        !          97150:         $output_filename   = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'out';
        !          97151:         $memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'mem';
        !          97152:         $temp_file         = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'php';
        !          97153:         $temp_skipif       = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'skip.php';
        !          97154:         $temp_clean        = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'clean.php';
        !          97155:         $tmp_post          = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.');
1.1       misho    97156: 
1.1.1.2 ! misho    97157:         // unlink old test results
        !          97158:         @unlink($diff_filename);
        !          97159:         @unlink($log_filename);
        !          97160:         @unlink($exp_filename);
        !          97161:         @unlink($output_filename);
        !          97162:         @unlink($memcheck_filename);
        !          97163:         @unlink($temp_file);
        !          97164:         @unlink($temp_skipif);
        !          97165:         @unlink($tmp_post);
        !          97166:         @unlink($temp_clean);
        !          97167:     }
1.1       misho    97168: 
1.1.1.2 ! misho    97169:     function _runSkipIf($section_text, $temp_skipif, $tested, $ini_settings)
        !          97170:     {
        !          97171:         $info = '';
        !          97172:         $warn = false;
        !          97173:         if (array_key_exists('SKIPIF', $section_text) && trim($section_text['SKIPIF'])) {
        !          97174:             $this->save_text($temp_skipif, $section_text['SKIPIF']);
        !          97175:             $output = $this->system_with_timeout("$this->_php$ini_settings -f \"$temp_skipif\"");
        !          97176:             $output = $output[1];
        !          97177:             $loutput = ltrim($output);
        !          97178:             unlink($temp_skipif);
        !          97179:             if (!strncasecmp('skip', $loutput, 4)) {
        !          97180:                 $skipreason = "SKIP $tested";
        !          97181:                 if (preg_match('/^\s*skip\s*(.+)\s*/i', $output, $m)) {
        !          97182:                     $skipreason .= '(reason: ' . $m[1] . ')';
        !          97183:                 }
        !          97184:                 if (!isset($this->_options['quiet'])) {
        !          97185:                     $this->_logger->log(0, $skipreason);
        !          97186:                 }
        !          97187:                 if (isset($this->_options['tapoutput'])) {
        !          97188:                     return array('ok', ' # skip ' . $reason);
        !          97189:                 }
        !          97190:                 return 'SKIPPED';
1.1       misho    97191:             }
                   97192: 
1.1.1.2 ! misho    97193:             if (!strncasecmp('info', $loutput, 4)
        !          97194:                 && preg_match('/^\s*info\s*(.+)\s*/i', $output, $m)) {
        !          97195:                 $info = " (info: $m[1])";
1.1       misho    97196:             }
                   97197: 
1.1.1.2 ! misho    97198:             if (!strncasecmp('warn', $loutput, 4)
        !          97199:                 && preg_match('/^\s*warn\s*(.+)\s*/i', $output, $m)) {
        !          97200:                 $warn = true; /* only if there is a reason */
        !          97201:                 $info = " (warn: $m[1])";
1.1       misho    97202:             }
1.1.1.2 ! misho    97203:         }
1.1       misho    97204: 
1.1.1.2 ! misho    97205:         return array('warn' => $warn, 'info' => $info);
        !          97206:     }
1.1       misho    97207: 
1.1.1.2 ! misho    97208:     function _stripHeadersCGI($output)
        !          97209:     {
        !          97210:         $this->headers = array();
        !          97211:         if (!empty($this->_options['cgi']) &&
        !          97212:               $this->_php == $this->_options['cgi'] &&
        !          97213:               preg_match("/^(.*?)(?:\n\n(.*)|\\z)/s", $output, $match)) {
        !          97214:             $output = isset($match[2]) ? trim($match[2]) : '';
        !          97215:             $this->_headers = $this->_processHeaders($match[1]);
        !          97216:         }
1.1       misho    97217: 
1.1.1.2 ! misho    97218:         return $output;
        !          97219:     }
1.1       misho    97220: 
1.1.1.2 ! misho    97221:     /**
        !          97222:      * Return an array that can be used with array_diff() to compare headers
        !          97223:      *
        !          97224:      * @param string $text
        !          97225:      */
        !          97226:     function _processHeaders($text)
        !          97227:     {
        !          97228:         $headers = array();
        !          97229:         $rh = preg_split("/[\n\r]+/", $text);
        !          97230:         foreach ($rh as $line) {
        !          97231:             if (strpos($line, ':')!== false) {
        !          97232:                 $line = explode(':', $line, 2);
        !          97233:                 $headers[trim($line[0])] = trim($line[1]);
1.1       misho    97234:             }
                   97235:         }
1.1.1.2 ! misho    97236:         return $headers;
1.1       misho    97237:     }
                   97238: 
1.1.1.2 ! misho    97239:     function _readFile($file)
1.1       misho    97240:     {
1.1.1.2 ! misho    97241:         // Load the sections of the test file.
        !          97242:         $section_text = array(
        !          97243:             'TEST'   => '(unnamed test)',
        !          97244:             'SKIPIF' => '',
        !          97245:             'GET'    => '',
        !          97246:             'COOKIE' => '',
        !          97247:             'POST'   => '',
        !          97248:             'ARGS'   => '',
        !          97249:             'INI'    => '',
        !          97250:             'CLEAN'  => '',
        !          97251:         );
        !          97252: 
        !          97253:         if (!is_file($file) || !$fp = fopen($file, "r")) {
        !          97254:             return PEAR::raiseError("Cannot open test file: $file");
1.1       misho    97255:         }
                   97256: 
1.1.1.2 ! misho    97257:         $section = '';
        !          97258:         while (!feof($fp)) {
        !          97259:             $line = fgets($fp);
1.1       misho    97260: 
1.1.1.2 ! misho    97261:             // Match the beginning of a section.
        !          97262:             if (preg_match('/^--([_A-Z]+)--/', $line, $r)) {
        !          97263:                 $section = $r[1];
        !          97264:                 $section_text[$section] = '';
        !          97265:                 continue;
        !          97266:             } elseif (empty($section)) {
        !          97267:                 fclose($fp);
        !          97268:                 return PEAR::raiseError("Invalid sections formats in test file: $file");
1.1       misho    97269:             }
                   97270: 
1.1.1.2 ! misho    97271:             // Add to the section text.
        !          97272:             $section_text[$section] .= $line;
        !          97273:         }
        !          97274:         fclose($fp);
1.1       misho    97275: 
1.1.1.2 ! misho    97276:         return $section_text;
        !          97277:     }
1.1       misho    97278: 
1.1.1.2 ! misho    97279:     function _writeLog($logname, $data)
        !          97280:     {
        !          97281:         if (!$log = fopen($logname, 'w')) {
        !          97282:             return PEAR::raiseError("Cannot create test log - $logname");
        !          97283:         }
        !          97284:         fwrite($log, $data);
        !          97285:         fclose($log);
        !          97286:     }
1.1       misho    97287: 
1.1.1.2 ! misho    97288:     function _resetEnv($section_text, $temp_file)
        !          97289:     {
        !          97290:         $env = $_ENV;
        !          97291:         $env['REDIRECT_STATUS'] = '';
        !          97292:         $env['QUERY_STRING']    = '';
        !          97293:         $env['PATH_TRANSLATED'] = '';
        !          97294:         $env['SCRIPT_FILENAME'] = '';
        !          97295:         $env['REQUEST_METHOD']  = '';
        !          97296:         $env['CONTENT_TYPE']    = '';
        !          97297:         $env['CONTENT_LENGTH']  = '';
        !          97298:         if (!empty($section_text['ENV'])) {
        !          97299:             if (strpos($section_text['ENV'], '{PWD}') !== false) {
        !          97300:                 $section_text['ENV'] = str_replace('{PWD}', dirname($temp_file), $section_text['ENV']);
        !          97301:             }
        !          97302:             foreach (explode("\n", trim($section_text['ENV'])) as $e) {
        !          97303:                 $e = explode('=', trim($e), 2);
        !          97304:                 if (!empty($e[0]) && isset($e[1])) {
        !          97305:                     $env[$e[0]] = $e[1];
1.1       misho    97306:                 }
                   97307:             }
                   97308:         }
1.1.1.2 ! misho    97309:         if (array_key_exists('GET', $section_text)) {
        !          97310:             $env['QUERY_STRING'] = trim($section_text['GET']);
1.1       misho    97311:         } else {
1.1.1.2 ! misho    97312:             $env['QUERY_STRING'] = '';
1.1       misho    97313:         }
1.1.1.2 ! misho    97314:         if (array_key_exists('COOKIE', $section_text)) {
        !          97315:             $env['HTTP_COOKIE'] = trim($section_text['COOKIE']);
        !          97316:         } else {
        !          97317:             $env['HTTP_COOKIE'] = '';
1.1       misho    97318:         }
1.1.1.2 ! misho    97319:         $env['REDIRECT_STATUS'] = '1';
        !          97320:         $env['PATH_TRANSLATED'] = $temp_file;
        !          97321:         $env['SCRIPT_FILENAME'] = $temp_file;
1.1       misho    97322: 
1.1.1.2 ! misho    97323:         return $env;
1.1       misho    97324:     }
                   97325: 
1.1.1.2 ! misho    97326:     function _processUpload($section_text, $file)
1.1       misho    97327:     {
1.1.1.2 ! misho    97328:         if (array_key_exists('UPLOAD', $section_text) && !empty($section_text['UPLOAD'])) {
        !          97329:             $upload_files = trim($section_text['UPLOAD']);
        !          97330:             $upload_files = explode("\n", $upload_files);
1.1       misho    97331: 
1.1.1.2 ! misho    97332:             $request = "Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737\n" .
        !          97333:                        "-----------------------------20896060251896012921717172737\n";
        !          97334:             foreach ($upload_files as $fileinfo) {
        !          97335:                 $fileinfo = explode('=', $fileinfo);
        !          97336:                 if (count($fileinfo) != 2) {
        !          97337:                     return PEAR::raiseError("Invalid UPLOAD section in test file: $file");
        !          97338:                 }
        !          97339:                 if (!realpath(dirname($file) . '/' . $fileinfo[1])) {
        !          97340:                     return PEAR::raiseError("File for upload does not exist: $fileinfo[1] " .
        !          97341:                         "in test file: $file");
        !          97342:                 }
        !          97343:                 $file_contents = file_get_contents(dirname($file) . '/' . $fileinfo[1]);
        !          97344:                 $fileinfo[1] = basename($fileinfo[1]);
        !          97345:                 $request .= "Content-Disposition: form-data; name=\"$fileinfo[0]\"; filename=\"$fileinfo[1]\"\n";
        !          97346:                 $request .= "Content-Type: text/plain\n\n";
        !          97347:                 $request .= $file_contents . "\n" .
        !          97348:                     "-----------------------------20896060251896012921717172737\n";
        !          97349:             }
        !          97350: 
        !          97351:             if (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
        !          97352:                 // encode POST raw
        !          97353:                 $post = trim($section_text['POST']);
        !          97354:                 $post = explode('&', $post);
        !          97355:                 foreach ($post as $i => $post_info) {
        !          97356:                     $post_info = explode('=', $post_info);
        !          97357:                     if (count($post_info) != 2) {
        !          97358:                         return PEAR::raiseError("Invalid POST data in test file: $file");
        !          97359:                     }
        !          97360:                     $post_info[0] = rawurldecode($post_info[0]);
        !          97361:                     $post_info[1] = rawurldecode($post_info[1]);
        !          97362:                     $post[$i] = $post_info;
        !          97363:                 }
        !          97364:                 foreach ($post as $post_info) {
        !          97365:                     $request .= "Content-Disposition: form-data; name=\"$post_info[0]\"\n\n";
        !          97366:                     $request .= $post_info[1] . "\n" .
        !          97367:                         "-----------------------------20896060251896012921717172737\n";
        !          97368:                 }
        !          97369:                 unset($section_text['POST']);
        !          97370:             }
        !          97371:             $section_text['POST_RAW'] = $request;
1.1       misho    97372:         }
                   97373: 
1.1.1.2 ! misho    97374:         return $section_text;
1.1       misho    97375:     }
                   97376: 
1.1.1.2 ! misho    97377:     function _testCleanup($section_text, $temp_clean)
1.1       misho    97378:     {
1.1.1.2 ! misho    97379:         if ($section_text['CLEAN']) {
        !          97380:             // perform test cleanup
        !          97381:             $this->save_text($temp_clean, $section_text['CLEAN']);
        !          97382:             $output = $this->system_with_timeout("$this->_php $temp_clean  2>&1");
        !          97383:             if (strlen($output[1])) {
        !          97384:                 echo "BORKED --CLEAN-- section! output:\n", $output[1];
        !          97385:             }
        !          97386:             if (file_exists($temp_clean)) {
        !          97387:                 unlink($temp_clean);
        !          97388:             }
1.1       misho    97389:         }
                   97390:     }
1.1.1.2 ! misho    97391: }
        !          97392: <?php
1.1       misho    97393: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   97394: require_once 'phar://install-pear-nozlib.phar/' . 'System.php';
                   97395: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Config.php';
                   97396: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Command.php';
                   97397: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
                   97398: class PEAR_Start extends PEAR
                   97399: {
                   97400:     var $bin_dir;
                   97401:     var $data_dir;
                   97402:     var $cfg_dir;
                   97403:     var $www_dir;
                   97404:     var $install_pfc;
                   97405:     var $corePackages =
                   97406:         array(
                   97407:             'Archive_Tar',
                   97408:             'Console_Getopt',
                   97409:             'PEAR',
                   97410:             'Structures_Graph',
                   97411:             'XML_Util',
                   97412:         );
                   97413:     var $local_dir = array();
                   97414:     var $origpwd;
                   97415:     var $pfc_packages = array(
                   97416:             'DB',
                   97417:             'Net_Socket',
                   97418:             'Net_SMTP',
                   97419:             'Mail',
                   97420:             'XML_Parser',
                   97421:             'XML_RPC',
                   97422:             'PHPUnit'
                   97423:         );
                   97424:     var $php_dir;
                   97425:     var $php_bin;
                   97426:     var $pear_conf;
                   97427:     var $validPHPBin = false;
                   97428:     var $test_dir;
                   97429:     var $download_dir;
                   97430:     var $temp_dir;
                   97431:     var $config =
                   97432:         array(
                   97433:             'prefix',
                   97434:             'bin_dir',
                   97435:             'php_dir',
                   97436:             'doc_dir',
                   97437:             'data_dir',
                   97438:             'cfg_dir',
                   97439:             'www_dir',
                   97440:             'test_dir',
                   97441:             'temp_dir',
                   97442:             'download_dir',
                   97443:             'pear_conf',
                   97444:         );
                   97445:     var $prefix;
                   97446:     var $progress = 0;
                   97447:     var $configPrompt =
                   97448:         array(
                   97449:             'prefix' => 'Installation base ($prefix)',
                   97450:             'temp_dir' => 'Temporary directory for processing',
                   97451:             'download_dir' => 'Temporary directory for downloads',
                   97452:             'bin_dir' => 'Binaries directory',
                   97453:             'php_dir' => 'PHP code directory ($php_dir)',
                   97454:             'doc_dir' => 'Documentation directory',
                   97455:             'data_dir' => 'Data directory',
                   97456:             'cfg_dir' => 'User-modifiable configuration files directory',
                   97457:             'www_dir' => 'Public Web Files directory',
                   97458:             'test_dir' => 'Tests directory',
                   97459:             'pear_conf' => 'Name of configuration file',
                   97460:         );
                   97461: 
                   97462:     var $localInstall;
                   97463:     var $PEARConfig;
                   97464:     var $tarball = array();
                   97465: 
                   97466:     function PEAR_Start()
                   97467:     {
                   97468:         parent::PEAR();
                   97469:         if (OS_WINDOWS) {
                   97470:             $this->configPrompt['php_bin'] = 'Path to CLI php.exe';
                   97471:             $this->config[] = 'php_bin';
                   97472:             $this->prefix = getcwd();
                   97473: 
                   97474:             if (!@is_dir($this->prefix)) {
                   97475:                 if (@is_dir('c:\php5')) {
                   97476:                     $this->prefix = 'c:\php5';
                   97477:                 } elseif (@is_dir('c:\php4')) {
                   97478:                     $this->prefix = 'c:\php4';
                   97479:                 } elseif (@is_dir('c:\php')) {
                   97480:                     $this->prefix = 'c:\php';
                   97481:                 }
                   97482:             }
                   97483: 
                   97484:             $slash = "\\";
                   97485:             if (strrpos($this->prefix, '\\') === (strlen($this->prefix) - 1)) {
                   97486:                 $slash = '';
                   97487:             }
                   97488: 
                   97489:             $this->localInstall = false;
                   97490:             $this->bin_dir   = '$prefix';
                   97491:             $this->temp_dir   = '$prefix' . $slash . 'tmp';
                   97492:             $this->download_dir   = '$prefix' . $slash . 'tmp';
                   97493:             $this->php_dir   = '$prefix' . $slash . 'pear';
                   97494:             $this->doc_dir   = '$prefix' . $slash . 'docs';
                   97495:             $this->data_dir  = '$prefix' . $slash . 'data';
                   97496:             $this->test_dir  = '$prefix' . $slash . 'tests';
                   97497:             $this->www_dir  = '$prefix' . $slash . 'www';
                   97498:             $this->cfg_dir  = '$prefix' . $slash . 'cfg';
                   97499:             $this->pear_conf = PEAR_CONFIG_SYSCONFDIR . '\\pear.ini';
                   97500:             /*
                   97501:              * Detects php.exe
                   97502:              */
                   97503:             $this->validPHPBin = true;
                   97504:             if ($t = $this->safeGetenv('PHP_PEAR_PHP_BIN')) {
                   97505:                 $this->php_bin   = dirname($t);
                   97506:             } elseif ($t = $this->safeGetenv('PHP_BIN')) {
                   97507:                 $this->php_bin   = dirname($t);
                   97508:             } elseif ($t = System::which('php')) {
                   97509:                 $this->php_bin = dirname($t);
                   97510:             } elseif (is_file($this->prefix . '\cli\php.exe')) {
                   97511:                 $this->php_bin = $this->prefix . '\cli';
                   97512:             } elseif (is_file($this->prefix . '\php.exe')) {
                   97513:                 $this->php_bin = $this->prefix;
                   97514:             }
                   97515:             $phpexe = OS_WINDOWS ? '\\php.exe' : '/php';
                   97516:             if ($this->php_bin && !is_file($this->php_bin . $phpexe)) {
                   97517:                 $this->php_bin = '';
                   97518:             } else {
                   97519:                 if (strpos($this->php_bin, ':') === 0) {
                   97520:                     $this->php_bin = getcwd() . DIRECTORY_SEPARATOR . $this->php_bin;
                   97521:                 }
                   97522:             }
                   97523:             if (!is_file($this->php_bin . $phpexe)) {
                   97524:                 if (is_file('c:/php/cli/php.exe')) {
                   97525:                     $this->php_bin = 'c"\\php\\cli';
                   97526:                 } elseif (is_file('c:/php5/php.exe')) {
                   97527:                     $this->php_bin = 'c:\\php5';
                   97528:                 } elseif (is_file('c:/php4/cli/php.exe')) {
                   97529:                     $this->php_bin = 'c:\\php4\\cli';
                   97530:                 } else {
                   97531:                     $this->validPHPBin = false;
                   97532:                 }
                   97533:             }
                   97534:         } else {
                   97535:             $this->prefix = dirname(PHP_BINDIR);
                   97536:             $this->pear_conf = PEAR_CONFIG_SYSCONFDIR . '/pear.conf';
                   97537:             if (get_current_user() != 'root') {
                   97538:                 $this->prefix = $this->safeGetenv('HOME') . '/pear';
                   97539:                 $this->pear_conf = $this->safeGetenv('HOME') . '.pearrc';
                   97540:             }
                   97541:             $this->bin_dir   = '$prefix/bin';
                   97542:             $this->php_dir   = '$prefix/share/pear';
                   97543:             $this->temp_dir  = '/tmp/pear/install';
                   97544:             $this->download_dir  = '/tmp/pear/install';
                   97545:             $this->doc_dir   = '$prefix/docs';
                   97546:             $this->www_dir   = '$prefix/www';
                   97547:             $this->cfg_dir   = '$prefix/cfg';
                   97548:             $this->data_dir  = '$prefix/data';
                   97549:             $this->test_dir  = '$prefix/tests';
                   97550:             // check if the user has installed PHP with PHP or GNU layout
                   97551:             if (@is_dir("$this->prefix/lib/php/.registry")) {
                   97552:                 $this->php_dir = '$prefix/lib/php';
                   97553:             } elseif (@is_dir("$this->prefix/share/pear/lib/.registry")) {
                   97554:                 $this->php_dir = '$prefix/share/pear/lib';
                   97555:                 $this->doc_dir   = '$prefix/share/pear/docs';
                   97556:                 $this->data_dir  = '$prefix/share/pear/data';
                   97557:                 $this->test_dir  = '$prefix/share/pear/tests';
                   97558:             } elseif (@is_dir("$this->prefix/share/php/.registry")) {
                   97559:                 $this->php_dir = '$prefix/share/php';
                   97560:             }
                   97561:         }
                   97562:     }
                   97563: 
                   97564:     function safeGetenv($var)
                   97565:     {
                   97566:         if (is_array($_ENV) && isset($_ENV[$var])) {
                   97567:             return $_ENV[$var];
                   97568:         }
                   97569: 
                   97570:         return getenv($var);
                   97571:     }
                   97572: 
                   97573:     function show($stuff)
                   97574:     {
                   97575:         print $stuff;
                   97576:     }
                   97577: 
                   97578:     function locatePackagesToInstall()
                   97579:     {
                   97580:         $dp = @opendir(dirname(__FILE__) . '/go-pear-tarballs');
                   97581:         if (empty($dp)) {
                   97582:             return PEAR::raiseError("while locating packages to install: opendir('" .
                   97583:                 dirname(__FILE__) . "/go-pear-tarballs') failed");
                   97584:         }
                   97585: 
                   97586:         $potentials = array();
                   97587:         while (false !== ($entry = readdir($dp))) {
                   97588:             if ($entry{0} == '.' || !in_array(substr($entry, -4), array('.tar', '.tgz'))) {
                   97589:                 continue;
                   97590:             }
                   97591:             $potentials[] = $entry;
                   97592:         }
                   97593: 
                   97594:         closedir($dp);
                   97595:         $notfound = array();
                   97596:         foreach ($this->corePackages as $package) {
                   97597:             foreach ($potentials as $i => $candidate) {
                   97598:                 if (preg_match('/^' . $package . '-' . _PEAR_COMMON_PACKAGE_VERSION_PREG
                   97599:                       . '\.(tar|tgz)\\z/', $candidate)) {
                   97600:                     $this->tarball[$package] = dirname(__FILE__) . '/go-pear-tarballs/' . $candidate;
                   97601:                     unset($potentials[$i]);
                   97602:                     continue 2;
                   97603:                 }
                   97604:             }
                   97605: 
                   97606:             $notfound[] = $package;
                   97607:         }
                   97608: 
                   97609:         if (count($notfound)) {
                   97610:             return PEAR::raiseError("No tarballs found for core packages: " .
                   97611:                     implode(', ', $notfound));
                   97612:         }
                   97613: 
                   97614:         $this->tarball = array_merge($this->tarball, $potentials);
                   97615:     }
                   97616: 
                   97617:     function setupTempStuff()
                   97618:     {
                   97619:         if (!($this->ptmp = System::mktemp(array('-d')))) {
                   97620:             $this->show("System's Tempdir failed, trying to use \$prefix/tmp ...");
                   97621:             $res = System::mkDir(array($this->prefix . '/tmp'));
                   97622:             if (!$res) {
                   97623:                 return PEAR::raiseError('mkdir ' . $this->prefix . '/tmp ... failed');
                   97624:             }
                   97625: 
                   97626:             $_temp = tempnam($this->prefix . '/tmp', 'gope');
                   97627:             System::rm(array('-rf', $_temp));
                   97628:             System::mkdir(array('-p','-m', '0700', $_temp));
                   97629:             $this->ptmp = $this->prefix . '/tmp';
                   97630:             $ok = @chdir($this->ptmp);
                   97631: 
                   97632:             if (!$ok) { // This should not happen, really ;)
                   97633:                 $this->bail('chdir ' . $this->ptmp . ' ... failed');
                   97634:             }
                   97635: 
                   97636:             print "ok\n";
                   97637: 
                   97638:             // Adjust TEMPDIR envvars
                   97639:             if (!isset($_ENV)) {
                   97640:                 $_ENV = array();
                   97641:             };
                   97642:             $_ENV['TMPDIR'] = $_ENV['TEMP'] = $this->prefix . '/tmp';
                   97643:         }
                   97644: 
                   97645:         return @chdir($this->ptmp);
                   97646:     }
                   97647: 
                   97648:     /**
                   97649:      * Try to detect the kind of SAPI used by the
                   97650:      * the given php.exe.
                   97651:      * @author Pierrre-Alain Joye
                   97652:      */
                   97653:     function win32DetectPHPSAPI()
                   97654:     {
                   97655:         if ($this->php_bin != '') {
                   97656:             if (OS_WINDOWS) {
                   97657:                 exec('"' . $this->php_bin . '\\php.exe" -v', $res);
                   97658:             } else {
                   97659:                 exec('"' . $this->php_bin . '/php" -v', $res);
                   97660:             }
                   97661: 
                   97662:             if (is_array($res)) {
                   97663:                 if (isset($res[0]) && strpos($res[0],"(cli)")) {
                   97664:                     return 'cli';
                   97665:                 }
                   97666: 
                   97667:                 if (isset($res[0]) && strpos($res[0],"cgi")) {
                   97668:                     return 'cgi';
                   97669:                 }
                   97670: 
                   97671:                 if (isset($res[0]) && strpos($res[0],"cgi-fcgi")) {
                   97672:                     return 'cgi';
                   97673:                 }
                   97674: 
                   97675:                 return 'unknown';
                   97676:             }
                   97677:         }
                   97678: 
                   97679:         return 'unknown';
                   97680:     }
                   97681: 
                   97682:     function doInstall()
                   97683:     {
                   97684:         print "Beginning install...\n";
                   97685:         // finish php_bin config
                   97686:         if (OS_WINDOWS) {
                   97687:             $this->php_bin .= '\\php.exe';
                   97688:         } else {
                   97689:             $this->php_bin .= '/php';
                   97690:         }
                   97691:         $this->PEARConfig = &PEAR_Config::singleton($this->pear_conf, $this->pear_conf);
                   97692:         $this->PEARConfig->set('preferred_state', 'stable');
                   97693:         foreach ($this->config as $var) {
                   97694:             if ($var == 'pear_conf' || $var == 'prefix') {
                   97695:                 continue;
                   97696:             }
                   97697:             $this->PEARConfig->set($var, $this->$var);
                   97698:         }
                   97699: 
                   97700:         $this->PEARConfig->store();
                   97701: //       $this->PEARConfig->set('verbose', 6);
                   97702:         print "Configuration written to $this->pear_conf...\n";
                   97703:         $this->registry = &$this->PEARConfig->getRegistry();
                   97704:         print "Initialized registry...\n";
                   97705:         $install = &PEAR_Command::factory('install', $this->PEARConfig);
                   97706:         print "Preparing to install...\n";
                   97707:         $options = array(
                   97708:             'nodeps' => true,
                   97709:             'force' => true,
                   97710:             'upgrade' => true,
                   97711:             );
                   97712:         foreach ($this->tarball as $pkg => $src) {
                   97713:             print "installing $src...\n";
                   97714:         }
                   97715:         $install->run('install', $options, array_values($this->tarball));
                   97716:     }
                   97717: 
                   97718:     function postProcessConfigVars()
                   97719:     {
                   97720:         foreach ($this->config as $n => $var) {
                   97721:             for ($m = 1; $m <= count($this->config); $m++) {
                   97722:                 $var2 = $this->config[$m];
                   97723:                 $this->$var = str_replace('$'.$var2, $this->$var2, $this->$var);
                   97724:             }
                   97725:         }
                   97726: 
                   97727:         foreach ($this->config as $var) {
                   97728:             $dir = $this->$var;
                   97729: 
                   97730:             if (!preg_match('/_dir\\z/', $var)) {
                   97731:                 continue;
                   97732:             }
                   97733: 
                   97734:             if (!@is_dir($dir)) {
                   97735:                 if (!System::mkDir(array('-p', $dir))) {
                   97736:                     $root = OS_WINDOWS ? 'administrator' : 'root';
                   97737:                     return PEAR::raiseError("Unable to create {$this->configPrompt[$var]} $dir.
                   97738: Run this script as $root or pick another location.\n");
                   97739:                 }
                   97740:             }
                   97741:         }
                   97742:     }
                   97743: 
                   97744:     /**
                   97745:      * Get the php.ini file used with the current
                   97746:      * process or with the given php.exe
                   97747:      *
                   97748:      * Horrible hack, but well ;)
                   97749:      *
                   97750:      * Not used yet, will add the support later
                   97751:      * @author Pierre-Alain Joye <paj@pearfr.org>
                   97752:      */
                   97753:     function getPhpiniPath()
                   97754:     {
                   97755:         $pathIni = get_cfg_var('cfg_file_path');
                   97756:         if ($pathIni && is_file($pathIni)) {
                   97757:             return $pathIni;
                   97758:         }
                   97759: 
                   97760:         // Oh well, we can keep this too :)
                   97761:         // I dunno if get_cfg_var() is safe on every OS
                   97762:         if (OS_WINDOWS) {
                   97763:             // on Windows, we can be pretty sure that there is a php.ini
                   97764:             // file somewhere
                   97765:             do {
                   97766:                 $php_ini = PHP_CONFIG_FILE_PATH . DIRECTORY_SEPARATOR . 'php.ini';
                   97767:                 if (@file_exists($php_ini)) {
                   97768:                     break;
                   97769:                 }
                   97770:                 $php_ini = 'c:\winnt\php.ini';
                   97771:                 if (@file_exists($php_ini)) {
                   97772:                     break;
                   97773:                 }
                   97774:                 $php_ini = 'c:\windows\php.ini';
                   97775:             } while (false);
                   97776:         } else {
                   97777:             $php_ini = PHP_CONFIG_FILE_PATH . DIRECTORY_SEPARATOR . 'php.ini';
                   97778:         }
                   97779: 
                   97780:         if (@is_file($php_ini)) {
                   97781:             return $php_ini;
                   97782:         }
                   97783: 
                   97784:         // We re running in hackz&troubles :)
                   97785:         ob_implicit_flush(false);
                   97786:         ob_start();
                   97787:         phpinfo(INFO_GENERAL);
                   97788:         $strInfo = ob_get_contents();
                   97789:         ob_end_clean();
                   97790:         ob_implicit_flush(true);
                   97791: 
                   97792:         if (php_sapi_name() != 'cli') {
                   97793:             $strInfo = strip_tags($strInfo,'<td>');
                   97794:             $arrayInfo = explode("</td>", $strInfo );
                   97795:             $cli = false;
                   97796:         } else {
                   97797:             $arrayInfo = explode("\n", $strInfo);
                   97798:             $cli = true;
                   97799:         }
                   97800: 
                   97801:         foreach ($arrayInfo as $val) {
                   97802:             if (strpos($val,"php.ini")) {
                   97803:                 if ($cli) {
                   97804:                     list(,$pathIni) = explode('=>', $val);
                   97805:                 } else {
                   97806:                     $pathIni = strip_tags(trim($val));
                   97807:                 }
                   97808:                 $pathIni = trim($pathIni);
                   97809:                 if (is_file($pathIni)) {
                   97810:                     return $pathIni;
                   97811:                 }
                   97812:             }
                   97813:         }
                   97814: 
                   97815:         return false;
                   97816:     }
                   97817: }
                   97818: ?>
                   97819: <?php
                   97820: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Start.php';
                   97821: class PEAR_Start_CLI extends PEAR_Start
                   97822: {
                   97823: 
                   97824:     var $descLength;
                   97825:     var $descFormat;
                   97826:     var $first;
                   97827:     var $last;
                   97828:     var $origpwd;
                   97829:     var $tty;
                   97830: 
                   97831:     function PEAR_Start_CLI()
                   97832:     {
                   97833:         parent::PEAR_Start();
                   97834:         ini_set('html_errors', 0);
                   97835:         define('WIN32GUI', OS_WINDOWS && php_sapi_name() == 'cli' && System::which('cscript'));
                   97836:         $this->tty = OS_WINDOWS ? @fopen('\con', 'r') : @fopen('/dev/tty', 'r');
                   97837: 
                   97838:         if (!$this->tty) {
                   97839:             $this->tty = fopen('php://stdin', 'r');
                   97840:         }
                   97841:         $this->origpwd = getcwd();
                   97842:         $this->config = array_keys($this->configPrompt);
                   97843: 
                   97844:         // make indices run from 1...
                   97845:         array_unshift($this->config, "");
                   97846:         unset($this->config[0]);
                   97847:         reset($this->config);
                   97848:         $this->descLength = max(array_map('strlen', $this->configPrompt));
                   97849:         $this->descFormat = "%-{$this->descLength}s";
                   97850:         $this->first = key($this->config);
                   97851:         end($this->config);
                   97852:         $this->last = key($this->config);
                   97853:         PEAR_Command::setFrontendType('CLI');
                   97854:     }
                   97855: 
                   97856:     function _PEAR_Start_CLI()
                   97857:     {
                   97858:         if ($this->tty) {
                   97859:             @fclose($this->tty);
                   97860:         }
                   97861:     }
                   97862: 
                   97863:     function run()
                   97864:     {
                   97865:         if (PEAR::isError($err = $this->locatePackagesToInstall())) {
                   97866:             return $err;
                   97867:         }
                   97868:         $this->startupQuestion();
                   97869:         $this->setupTempStuff();
                   97870:         $this->getInstallLocations();
                   97871:         $this->displayPreamble();
                   97872:         if (PEAR::isError($err = $this->postProcessConfigVars())) {
                   97873:             return $err;
                   97874:         }
                   97875:         $this->doInstall();
                   97876:         $this->finishInstall();
                   97877:     }
                   97878: 
                   97879:     function startupQuestion()
                   97880:     {
                   97881:         if (OS_WINDOWS) {
                   97882:             print "
                   97883: Are you installing a system-wide PEAR or a local copy?
                   97884: (system|local) [system] : ";
                   97885:             $tmp = trim(fgets($this->tty, 1024));
                   97886:             if (!empty($tmp) && strtolower($tmp) !== 'system') {
                   97887:                 print "Please confirm local copy by typing 'yes' : ";
                   97888:                 $tmp = trim(fgets($this->tty, 1024));
                   97889:                 if (strtolower($tmp) == 'yes') {
                   97890:                     $slash = "\\";
                   97891:                     if (strrpos($this->prefix, '\\') === (strlen($this->prefix) - 1)) {
                   97892:                         $slash = '';
                   97893:                     }
                   97894: 
                   97895:                     $this->localInstall = true;
                   97896:                     $this->pear_conf = '$prefix' . $slash . 'pear.ini';
                   97897:                 }
                   97898:             }
                   97899:         } else {
                   97900:             if (get_current_user() == 'root') {
                   97901:                 return;
                   97902:             }
                   97903:             $this->pear_conf = $this->safeGetenv('HOME') . '/.pearrc';
                   97904:         }
                   97905:     }
                   97906: 
                   97907:     function getInstallLocations()
                   97908:     {
                   97909:         while (true) {
                   97910:             print "
                   97911: Below is a suggested file layout for your new PEAR installation.  To
                   97912: change individual locations, type the number in front of the
                   97913: directory.  Type 'all' to change all of them or simply press Enter to
                   97914: accept these locations.
                   97915: 
                   97916: ";
                   97917: 
                   97918:             foreach ($this->config as $n => $var) {
                   97919:                 $fullvar = $this->$var;
                   97920:                 foreach ($this->config as $blah => $unused) {
                   97921:                     foreach ($this->config as $m => $var2) {
                   97922:                         $fullvar = str_replace('$'.$var2, $this->$var2, $fullvar);
                   97923:                     }
                   97924:                 }
                   97925:                 printf("%2d. $this->descFormat : %s\n", $n, $this->configPrompt[$var], $fullvar);
                   97926:             }
                   97927: 
                   97928:             print "\n$this->first-$this->last, 'all' or Enter to continue: ";
                   97929:             $tmp = trim(fgets($this->tty, 1024));
                   97930:             if (empty($tmp)) {
                   97931:                 if (OS_WINDOWS && !$this->validPHPBin) {
                   97932:                     echo "**ERROR**
                   97933: Please, enter the php.exe path.
                   97934: 
                   97935: ";
                   97936:                 } else {
                   97937:                     break;
                   97938:                 }
                   97939:             }
                   97940: 
                   97941:             if (isset($this->config[(int)$tmp])) {
                   97942:                 $var = $this->config[(int)$tmp];
                   97943:                 $desc = $this->configPrompt[$var];
                   97944:                 $current = $this->$var;
                   97945:                 if (WIN32GUI && $var != 'pear_conf'){
                   97946:                     $tmp = $this->win32BrowseForFolder("Choose a Folder for $desc [$current] :");
                   97947:                     $tmp.= '\\';
                   97948:                 } else {
                   97949:                     print "(Use \$prefix as a shortcut for '$this->prefix', etc.)
                   97950: $desc [$current] : ";
                   97951:                     $tmp = trim(fgets($this->tty, 1024));
                   97952:                 }
                   97953:                 $old = $this->$var;
                   97954:                 $this->$var = $$var = $tmp;
                   97955:                 if (OS_WINDOWS && $var=='php_bin') {
                   97956:                     if ($this->validatePhpExecutable($tmp)) {
                   97957:                         $this->php_bin = $tmp;
                   97958:                     } else {
                   97959:                         $this->php_bin = $old;
                   97960:                     }
                   97961:                 }
                   97962:             } elseif ($tmp == 'all') {
                   97963:                 foreach ($this->config as $n => $var) {
                   97964:                     $desc = $this->configPrompt[$var];
                   97965:                     $current = $this->$var;
                   97966:                     print "$desc [$current] : ";
                   97967:                     $tmp = trim(fgets($this->tty, 1024));
                   97968:                     if (!empty($tmp)) {
                   97969:                         $this->$var = $tmp;
                   97970:                     }
                   97971:                 }
                   97972:             }
                   97973:         }
                   97974:     }
                   97975: 
                   97976:     function validatePhpExecutable($tmp)
                   97977:     {
                   97978:         if (OS_WINDOWS) {
                   97979:             if (strpos($tmp, 'php.exe')) {
                   97980:                 $tmp = str_replace('php.exe', '', $tmp);
                   97981:             }
                   97982:             if (file_exists($tmp . DIRECTORY_SEPARATOR . 'php.exe')) {
                   97983:                 $tmp = $tmp . DIRECTORY_SEPARATOR . 'php.exe';
                   97984:                 $this->php_bin_sapi = $this->win32DetectPHPSAPI();
                   97985:                 if ($this->php_bin_sapi=='cgi'){
                   97986:                     print "
                   97987: ******************************************************************************
                   97988: NOTICE! We found php.exe under $this->php_bin, it uses a $this->php_bin_sapi SAPI.
                   97989: PEAR commandline tool works well with it.
                   97990: If you have a CLI php.exe available, we recommend using it.
                   97991: 
                   97992: Press Enter to continue...";
                   97993:                     $tmp = trim(fgets($this->tty, 1024));
                   97994:                 } elseif ($this->php_bin_sapi=='unknown') {
                   97995:                     print "
                   97996: ******************************************************************************
                   97997: WARNING! We found php.exe under $this->php_bin, it uses an $this->php_bin_sapi SAPI.
                   97998: PEAR commandline tool has NOT been tested with it.
                   97999: If you have a CLI (or CGI) php.exe available, we strongly recommend using it.
                   98000: 
                   98001: Press Enter to continue...";
                   98002:                     $tmp = trim(fgets($this->tty, 1024));
                   98003:                 }
                   98004:                 echo "php.exe (sapi: $this->php_bin_sapi) found.\n\n";
                   98005:                 return $this->validPHPBin = true;
                   98006:             } else {
                   98007:                 echo "**ERROR**: not a folder, or no php.exe found in this folder.
                   98008: Press Enter to continue...";
                   98009:                 $tmp = trim(fgets($this->tty, 1024));
                   98010:                 return $this->validPHPBin = false;
                   98011:             }
                   98012:         }
                   98013:     }
                   98014: 
                   98015:     /**
                   98016:      * Create a vbs script to browse the getfolder dialog, called
                   98017:      * by cscript, if it's available.
                   98018:      * $label is the label text in the header of the dialog box
                   98019:      *
                   98020:      * TODO:
                   98021:      * - Do not show Control panel
                   98022:      * - Replace WSH with calls to w32 as soon as callbacks work
                   98023:      * @author Pierrre-Alain Joye
                   98024:      */
                   98025:     function win32BrowseForFolder($label)
                   98026:     {
                   98027:         static $wshSaved=false;
                   98028:         static $cscript='';
                   98029:     $wsh_browserfolder = 'Option Explicit
                   98030: Dim ArgObj, var1, var2, sa, sFld
                   98031: Set ArgObj = WScript.Arguments
                   98032: Const BIF_EDITBOX = &H10
                   98033: Const BIF_NEWDIALOGSTYLE = &H40
                   98034: Const BIF_RETURNONLYFSDIRS   = &H0001
                   98035: Const BIF_DONTGOBELOWDOMAIN  = &H0002
                   98036: Const BIF_STATUSTEXT         = &H0004
                   98037: Const BIF_RETURNFSANCESTORS  = &H0008
                   98038: Const BIF_VALIDATE           = &H0020
                   98039: Const BIF_BROWSEFORCOMPUTER  = &H1000
                   98040: Const BIF_BROWSEFORPRINTER   = &H2000
                   98041: Const BIF_BROWSEINCLUDEFILES = &H4000
                   98042: Const OFN_LONGNAMES = &H200000
                   98043: Const OFN_NOLONGNAMES = &H40000
                   98044: Const ssfDRIVES = &H11
                   98045: Const ssfNETWORK = &H12
                   98046: Set sa = CreateObject("Shell.Application")
                   98047: var1=ArgObj(0)
                   98048: Set sFld = sa.BrowseForFolder(0, var1, BIF_EDITBOX + BIF_VALIDATE + BIF_BROWSEINCLUDEFILES + BIF_RETURNFSANCESTORS+BIF_NEWDIALOGSTYLE , ssfDRIVES )
                   98049: if not sFld is nothing Then
                   98050:     if not left(sFld.items.item.path,1)=":" Then
                   98051:         WScript.Echo sFld.items.item.path
                   98052:     Else
                   98053:         WScript.Echo "invalid"
                   98054:     End If
                   98055: Else
                   98056:     WScript.Echo "cancel"
                   98057: End If
                   98058: ';
                   98059:         if( !$wshSaved){
                   98060:             $cscript = $this->ptmp . DIRECTORY_SEPARATOR . "bf.vbs";
                   98061:             $fh = fopen($cscript, "wb+");
                   98062:             fwrite($fh, $wsh_browserfolder, strlen($wsh_browserfolder));
                   98063:             fclose($fh);
                   98064:             $wshSaved  = true;
                   98065:         }
                   98066: 
                   98067:         exec('cscript ' . escapeshellarg($cscript) . ' "' . escapeshellarg($label) . '" //noLogo', $arPath);
                   98068:         if (!count($arPath) || $arPath[0]=='' || $arPath[0]=='cancel') {
                   98069:             return '';
                   98070:         } elseif ($arPath[0]=='invalid') {
                   98071:             echo "Invalid Path.\n";
                   98072:             return '';
                   98073:         }
                   98074: 
                   98075:         @unlink($cscript);
                   98076:         return $arPath[0];
                   98077:     }
                   98078: 
                   98079:     function displayPreamble()
                   98080:     {
                   98081:         if (OS_WINDOWS) {
                   98082:             /*
                   98083:              * Checks PHP SAPI version under windows/CLI
                   98084:              */
                   98085:             if ($this->php_bin == '') {
                   98086:                 print "
1.1.1.2 ! misho    98087: We do not find any php.exe, please select the php.exe folder (CLI is
1.1       misho    98088: recommended, usually in c:\php\cli\php.exe)
                   98089: ";
                   98090:                 $this->validPHPBin = false;
                   98091:             } elseif (strlen($this->php_bin)) {
                   98092:                 $this->php_bin_sapi = $this->win32DetectPHPSAPI();
                   98093:                 $this->validPHPBin = true;
                   98094:                 switch ($this->php_bin_sapi) {
                   98095:                     case 'cli':
                   98096:                     break;
                   98097:                     case 'cgi':
                   98098:                     case 'cgi-fcgi':
                   98099:                         print "
                   98100: *NOTICE*
                   98101: We found php.exe under $this->php_bin, it uses a $this->php_bin_sapi SAPI. PEAR commandline
                   98102: tool works well with it, if you have a CLI php.exe available, we
                   98103: recommend using it.
                   98104: ";
                   98105:                     break;
                   98106:                     default:
                   98107:                         print "
                   98108: *WARNING*
                   98109: We found php.exe under $this->php_bin, it uses an unknown SAPI. PEAR commandline
                   98110: tool has not been tested with it, if you have a CLI (or CGI) php.exe available,
                   98111: we strongly recommend using it.
                   98112: 
                   98113: ";
                   98114:                     break;
                   98115:                 }
                   98116:             }
                   98117:         }
                   98118:     }
                   98119: 
                   98120:     function finishInstall()
                   98121:     {
                   98122:         $sep = OS_WINDOWS ? ';' : ':';
                   98123:         $include_path = explode($sep, ini_get('include_path'));
                   98124:         if (OS_WINDOWS) {
                   98125:             $found = false;
                   98126:             $t = strtolower($this->php_dir);
                   98127:             foreach ($include_path as $path) {
                   98128:                 if ($t == strtolower($path)) {
                   98129:                     $found = true;
                   98130:                     break;
                   98131:                 }
                   98132:             }
                   98133:         } else {
                   98134:             $found = in_array($this->php_dir, $include_path);
                   98135:         }
                   98136:         if (!$found) {
                   98137:             print "
                   98138: ******************************************************************************
                   98139: WARNING!  The include_path defined in the currently used php.ini does not
                   98140: contain the PEAR PHP directory you just specified:
                   98141: <$this->php_dir>
                   98142: If the specified directory is also not in the include_path used by
                   98143: your scripts, you will have problems getting any PEAR packages working.
                   98144: ";
                   98145: 
                   98146:             if ($php_ini = $this->getPhpiniPath()) {
                   98147:                 print "\n\nWould you like to alter php.ini <$php_ini>? [Y/n] : ";
                   98148:                 $alter_phpini = !stristr(fgets($this->tty, 1024), "n");
                   98149:                 if ($alter_phpini) {
                   98150:                     $this->alterPhpIni($php_ini);
                   98151:                 } else {
                   98152:                     if (OS_WINDOWS) {
                   98153:                         print "
                   98154: Please look over your php.ini file to make sure
                   98155: $this->php_dir is in your include_path.";
                   98156:                     } else {
                   98157:                         print "
                   98158: I will add a workaround for this in the 'pear' command to make sure
                   98159: the installer works, but please look over your php.ini or Apache
                   98160: configuration to make sure $this->php_dir is in your include_path.
                   98161: ";
                   98162:                     }
                   98163:                 }
                   98164:             }
                   98165: 
                   98166:         print "
                   98167: Current include path           : ".ini_get('include_path')."
                   98168: Configured directory           : $this->php_dir
                   98169: Currently used php.ini (guess) : $php_ini
                   98170: ";
                   98171: 
                   98172:             print "Press Enter to continue: ";
                   98173:             fgets($this->tty, 1024);
                   98174:         }
                   98175: 
                   98176:         $pear_cmd = $this->bin_dir . DIRECTORY_SEPARATOR . 'pear';
                   98177:         $pear_cmd = OS_WINDOWS ? strtolower($pear_cmd).'.bat' : $pear_cmd;
                   98178: 
                   98179:         // check that the installed pear and the one in the path are the same (if any)
                   98180:         $pear_old = System::which(OS_WINDOWS ? 'pear.bat' : 'pear', $this->bin_dir);
                   98181:         if ($pear_old && ($pear_old != $pear_cmd)) {
                   98182:             // check if it is a link or symlink
                   98183:             $islink = OS_WINDOWS ? false : is_link($pear_old) ;
                   98184:             if ($islink && readlink($pear_old) != $pear_cmd) {
                   98185:                 print "\n** WARNING! The link $pear_old does not point to the " .
                   98186:                       "installed $pear_cmd\n";
                   98187:             } elseif (!$this->localInstall && is_writable($pear_old) && !is_dir($pear_old)) {
                   98188:                 rename($pear_old, "{$pear_old}_old");
                   98189:                 print "\n** WARNING! Backed up old pear to {$pear_old}_old\n";
                   98190:             } else {
                   98191:                 print "\n** WARNING! Old version found at $pear_old, please remove it or ".
                   98192:                       "be sure to use the new $pear_cmd command\n";
                   98193:             }
                   98194:         }
                   98195: 
                   98196:         print "\nThe 'pear' command is now at your service at $pear_cmd\n";
                   98197: 
                   98198:         // Alert the user if the pear cmd is not in PATH
                   98199:         $old_dir = $pear_old ? dirname($pear_old) : false;
                   98200:         if (!$this->which('pear', $old_dir)) {
                   98201:             print "
                   98202: ** The 'pear' command is not currently in your PATH, so you need to
                   98203: ** use '$pear_cmd' until you have added
                   98204: ** '$this->bin_dir' to your PATH environment variable.
                   98205: 
                   98206: ";
                   98207: 
                   98208:         print "Run it without parameters to see the available actions, try 'pear list'
                   98209: to see what packages are installed, or 'pear help' for help.
                   98210: 
                   98211: For more information about PEAR, see:
                   98212: 
                   98213:   http://pear.php.net/faq.php
                   98214:   http://pear.php.net/manual/
                   98215: 
                   98216: Thanks for using go-pear!
                   98217: 
                   98218: ";
                   98219:         }
                   98220: 
                   98221:         if (OS_WINDOWS && !$this->localInstall) {
                   98222:             $this->win32CreateRegEnv();
                   98223:         }
                   98224:     }
                   98225: 
                   98226:     /**
                   98227:      * System::which() does not allow path exclusion
                   98228:      */
                   98229:     function which($program, $dont_search_in = false)
                   98230:     {
                   98231:         if (OS_WINDOWS) {
                   98232:             if ($_path = $this->safeGetEnv('Path')) {
                   98233:                 $dirs = explode(';', $_path);
                   98234:             } else {
                   98235:                 $dirs = explode(';', $this->safeGetEnv('PATH'));
                   98236:             }
                   98237:             foreach ($dirs as $i => $dir) {
                   98238:                 $dirs[$i] = strtolower(realpath($dir));
                   98239:             }
                   98240:             if ($dont_search_in) {
                   98241:                 $dont_search_in = strtolower(realpath($dont_search_in));
                   98242:             }
                   98243:             if ($dont_search_in &&
                   98244:                 ($key = array_search($dont_search_in, $dirs)) !== false)
                   98245:             {
                   98246:                 unset($dirs[$key]);
                   98247:             }
                   98248: 
                   98249:             foreach ($dirs as $dir) {
                   98250:                 $dir = str_replace('\\\\', '\\', $dir);
                   98251:                 if (!strlen($dir)) {
                   98252:                     continue;
                   98253:                 }
                   98254:                 if ($dir{strlen($dir) - 1} != '\\') {
                   98255:                     $dir .= '\\';
                   98256:                 }
                   98257:                 $tmp = $dir . $program;
                   98258:                 $info = pathinfo($tmp);
                   98259:                 if (isset($info['extension']) && in_array(strtolower($info['extension']),
                   98260:                       array('exe', 'com', 'bat', 'cmd'))) {
                   98261:                     if (file_exists($tmp)) {
                   98262:                         return strtolower($tmp);
                   98263:                     }
                   98264:                 } elseif (file_exists($ret = $tmp . '.exe') ||
                   98265:                     file_exists($ret = $tmp . '.com') ||
                   98266:                     file_exists($ret = $tmp . '.bat') ||
                   98267:                     file_exists($ret = $tmp . '.cmd')) {
                   98268:                     return strtolower($ret);
                   98269:                 }
                   98270:             }
                   98271:         } else {
                   98272:             $dirs = explode(':', $this->safeGetEnv('PATH'));
                   98273:             if ($dont_search_in &&
                   98274:                 ($key = array_search($dont_search_in, $dirs)) !== false)
                   98275:             {
                   98276:                 unset($dirs[$key]);
                   98277:             }
                   98278:             foreach ($dirs as $dir) {
                   98279:                 if (is_executable("$dir/$program")) {
                   98280:                     return "$dir/$program";
                   98281:                 }
                   98282:             }
                   98283:         }
                   98284:         return false;
                   98285:     }
                   98286: 
                   98287:     /**
                   98288:      * Not optimized, but seems to work, if some nice
                   98289:      * peardev will test it? :)
                   98290:      *
                   98291:      * @author Pierre-Alain Joye <paj@pearfr.org>
                   98292:      */
                   98293:     function alterPhpIni($pathIni='')
                   98294:     {
                   98295:         $foundAt = array();
                   98296:         $iniSep = OS_WINDOWS ? ';' : ':';
                   98297: 
                   98298:         if ($pathIni=='') {
                   98299:             $pathIni =  $this->getPhpiniPath();
                   98300:         }
                   98301: 
                   98302:         $arrayIni = file($pathIni);
                   98303:         $i=0;
                   98304:         $found=0;
                   98305: 
                   98306:         // Looks for each active include_path directives
                   98307:         foreach ($arrayIni as $iniLine) {
                   98308:             $iniLine = trim($iniLine);
                   98309:             $iniLine = str_replace(array("\n", "\r"), array('', ''), $iniLine);
                   98310:             if (preg_match("/^\s*include_path/", $iniLine)) {
                   98311:                 $foundAt[] = $i;
                   98312:                 $found++;
                   98313:             }
                   98314:             $i++;
                   98315:         }
                   98316: 
                   98317:         if ($found) {
                   98318:             $includeLine = $arrayIni[$foundAt[0]];
                   98319:             list(, $currentPath) = explode('=', $includeLine);
                   98320: 
                   98321:             $currentPath = trim($currentPath);
                   98322:             if (substr($currentPath,0,1) == '"') {
                   98323:                 $currentPath = substr($currentPath, 1, strlen($currentPath) - 2);
                   98324:             }
                   98325: 
                   98326:             $arrayPath = explode($iniSep, $currentPath);
                   98327:             $newPath = array();
                   98328:             if ($arrayPath[0]=='.') {
                   98329:                 $newPath[0] = '.';
                   98330:                 $newPath[1] = $this->php_dir;
                   98331:                 array_shift($arrayPath);
                   98332:             } else {
                   98333:                 $newPath[0] = $this->php_dir;
                   98334:             }
                   98335: 
                   98336:             foreach ($arrayPath as $path) {
                   98337:                 $newPath[]= $path;
                   98338:             }
                   98339:         } else {
                   98340:             $newPath = array();
                   98341:             $newPath[0] = '.';
                   98342:             $newPath[1] = $this->php_dir;
                   98343:             $foundAt[] = count($arrayIni); // add a new line if none is present
                   98344:         }
                   98345:         $nl = OS_WINDOWS ? "\r\n" : "\n";
                   98346:         $includepath = 'include_path="' . implode($iniSep,$newPath) . '"';
                   98347:         $newInclude = "$nl$nl;***** Added by go-pear$nl" .
                   98348:                        $includepath .
                   98349:                        $nl . ";*****" .
                   98350:                        $nl . $nl;
                   98351: 
                   98352:         $arrayIni[$foundAt[0]] = $newInclude;
                   98353: 
                   98354:         for ($i=1; $i<$found; $i++) {
                   98355:             $arrayIni[$foundAt[$i]]=';' . trim($arrayIni[$foundAt[$i]]);
                   98356:         }
                   98357: 
                   98358:         $newIni = implode("", $arrayIni);
                   98359:         if (!($fh = @fopen($pathIni, "wb+"))) {
                   98360:             $prefixIni = $this->prefix . DIRECTORY_SEPARATOR . "php.ini-gopear";
                   98361:             $fh = fopen($prefixIni, "wb+");
                   98362:             if (!$fh) {
                   98363:                 echo "
                   98364: ******************************************************************************
                   98365: WARNING: Cannot write to $pathIni nor in $this->prefix/php.ini-gopear. Please
                   98366: modify manually your php.ini by adding:
                   98367: 
                   98368: $includepath
                   98369: 
                   98370: ";
                   98371:                 return false;
                   98372:             } else {
                   98373:                 fwrite($fh, $newIni, strlen($newIni));
                   98374:                 fclose($fh);
                   98375:                 echo "
                   98376: ******************************************************************************
                   98377: WARNING: Cannot write to $pathIni, but php.ini was successfully created
                   98378: at <$this->prefix/php.ini-gopear>. Please replace the file <$pathIni> with
                   98379: <$prefixIni> or modify your php.ini by adding:
                   98380: 
                   98381: $includepath
                   98382: 
                   98383: ";
                   98384: 
                   98385:             }
                   98386:         } else {
                   98387:             fwrite($fh, $newIni, strlen($newIni));
                   98388:             fclose($fh);
                   98389:             echo "
                   98390: php.ini <$pathIni> include_path updated.
                   98391: ";
                   98392:         }
                   98393:         return true;
                   98394:     }
                   98395: 
                   98396:     /**
                   98397:      * Generates a registry addOn for Win32 platform
                   98398:      * This addon set PEAR environment variables
                   98399:      * @author Pierrre-Alain Joye
                   98400:      */
                   98401:     function win32CreateRegEnv()
                   98402:     {
                   98403:         $nl = "\r\n";
                   98404:         $reg ='REGEDIT4'.$nl.
                   98405:                 '[HKEY_CURRENT_USER\Environment]'. $nl .
                   98406:                 '"PHP_PEAR_SYSCONF_DIR"="' . addslashes($this->prefix) . '"' . $nl .
                   98407:                 '"PHP_PEAR_INSTALL_DIR"="' . addslashes($this->php_dir) . '"' . $nl .
                   98408:                 '"PHP_PEAR_DOC_DIR"="' . addslashes($this->doc_dir) . '"' . $nl .
                   98409:                 '"PHP_PEAR_BIN_DIR"="' . addslashes($this->bin_dir) . '"' . $nl .
                   98410:                 '"PHP_PEAR_DATA_DIR"="' . addslashes($this->data_dir) . '"' . $nl .
                   98411:                 '"PHP_PEAR_PHP_BIN"="' . addslashes($this->php_bin) . '"' . $nl .
                   98412:                 '"PHP_PEAR_TEST_DIR"="' . addslashes($this->test_dir) . '"' . $nl;
                   98413: 
                   98414:         $fh = fopen($this->prefix . DIRECTORY_SEPARATOR . 'PEAR_ENV.reg', 'wb');
                   98415:         if($fh){
                   98416:             fwrite($fh, $reg, strlen($reg));
                   98417:             fclose($fh);
                   98418:             echo "
                   98419: 
                   98420: * WINDOWS ENVIRONMENT VARIABLES *
                   98421: For convenience, a REG file is available under {$this->prefix}PEAR_ENV.reg .
                   98422: This file creates ENV variables for the current user.
                   98423: 
                   98424: Double-click this file to add it to the current user registry.
                   98425: 
                   98426: ";
                   98427:         }
                   98428:     }
                   98429: 
                   98430:     function displayHTMLProgress()
                   98431:     {
                   98432:     }
                   98433: }
                   98434: ?><?php
                   98435: /**
                   98436:  * PEAR_Task_Common, base class for installer tasks
                   98437:  *
                   98438:  * PHP versions 4 and 5
                   98439:  *
                   98440:  * @category   pear
                   98441:  * @package    PEAR
                   98442:  * @author     Greg Beaver <cellog@php.net>
                   98443:  * @copyright  1997-2009 The Authors
                   98444:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    98445:  * @version    CVS: $Id: Common.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    98446:  * @link       http://pear.php.net/package/PEAR
                   98447:  * @since      File available since Release 1.4.0a1
                   98448:  */
                   98449: /**#@+
                   98450:  * Error codes for task validation routines
                   98451:  */
                   98452: define('PEAR_TASK_ERROR_NOATTRIBS', 1);
                   98453: define('PEAR_TASK_ERROR_MISSING_ATTRIB', 2);
                   98454: define('PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE', 3);
                   98455: define('PEAR_TASK_ERROR_INVALID', 4);
                   98456: /**#@-*/
                   98457: define('PEAR_TASK_PACKAGE', 1);
                   98458: define('PEAR_TASK_INSTALL', 2);
                   98459: define('PEAR_TASK_PACKAGEANDINSTALL', 3);
                   98460: /**
                   98461:  * A task is an operation that manipulates the contents of a file.
                   98462:  *
                   98463:  * Simple tasks operate on 1 file.  Multiple tasks are executed after all files have been
                   98464:  * processed and installed, and are designed to operate on all files containing the task.
                   98465:  * The Post-install script task simply takes advantage of the fact that it will be run
                   98466:  * after installation, replace is a simple task.
                   98467:  *
                   98468:  * Combining tasks is possible, but ordering is significant.
                   98469:  *
                   98470:  * <file name="test.php" role="php">
                   98471:  *  <tasks:replace from="@data-dir@" to="data_dir" type="pear-config"/>
                   98472:  *  <tasks:postinstallscript/>
                   98473:  * </file>
                   98474:  *
                   98475:  * This will first replace any instance of @data-dir@ in the test.php file
                   98476:  * with the path to the current data directory.  Then, it will include the
                   98477:  * test.php file and run the script it contains to configure the package post-installation.
                   98478:  * @category   pear
                   98479:  * @package    PEAR
                   98480:  * @author     Greg Beaver <cellog@php.net>
                   98481:  * @copyright  1997-2009 The Authors
                   98482:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    98483:  * @version    Release: 1.9.4
1.1       misho    98484:  * @link       http://pear.php.net/package/PEAR
                   98485:  * @since      Class available since Release 1.4.0a1
                   98486:  * @abstract
                   98487:  */
                   98488: class PEAR_Task_Common
                   98489: {
                   98490:     /**
                   98491:      * Valid types for this version are 'simple' and 'multiple'
                   98492:      *
                   98493:      * - simple tasks operate on the contents of a file and write out changes to disk
                   98494:      * - multiple tasks operate on the contents of many files and write out the
                   98495:      *   changes directly to disk
                   98496:      *
                   98497:      * Child task classes must override this property.
                   98498:      * @access protected
                   98499:      */
                   98500:     var $type = 'simple';
                   98501:     /**
                   98502:      * Determines which install phase this task is executed under
                   98503:      */
                   98504:     var $phase = PEAR_TASK_INSTALL;
                   98505:     /**
                   98506:      * @access protected
                   98507:      */
                   98508:     var $config;
                   98509:     /**
                   98510:      * @access protected
                   98511:      */
                   98512:     var $registry;
                   98513:     /**
                   98514:      * @access protected
                   98515:      */
                   98516:     var $logger;
                   98517:     /**
                   98518:      * @access protected
                   98519:      */
                   98520:     var $installphase;
                   98521:     /**
                   98522:      * @param PEAR_Config
                   98523:      * @param PEAR_Common
                   98524:      */
                   98525:     function PEAR_Task_Common(&$config, &$logger, $phase)
                   98526:     {
                   98527:         $this->config = &$config;
                   98528:         $this->registry = &$config->getRegistry();
                   98529:         $this->logger = &$logger;
                   98530:         $this->installphase = $phase;
                   98531:         if ($this->type == 'multiple') {
                   98532:             $GLOBALS['_PEAR_TASK_POSTINSTANCES'][get_class($this)][] = &$this;
                   98533:         }
                   98534:     }
                   98535: 
                   98536:     /**
                   98537:      * Validate the basic contents of a task tag.
                   98538:      * @param PEAR_PackageFile_v2
                   98539:      * @param array
                   98540:      * @param PEAR_Config
                   98541:      * @param array the entire parsed <file> tag
                   98542:      * @return true|array On error, return an array in format:
                   98543:      *    array(PEAR_TASK_ERROR_???[, param1][, param2][, ...])
                   98544:      *
                   98545:      *    For PEAR_TASK_ERROR_MISSING_ATTRIB, pass the attribute name in
                   98546:      *    For PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, pass the attribute name and an array
                   98547:      *    of legal values in
                   98548:      * @static
                   98549:      * @abstract
                   98550:      */
                   98551:     function validateXml($pkg, $xml, $config, $fileXml)
                   98552:     {
                   98553:     }
                   98554: 
                   98555:     /**
                   98556:      * Initialize a task instance with the parameters
                   98557:      * @param array raw, parsed xml
                   98558:      * @param array attributes from the <file> tag containing this task
                   98559:      * @param string|null last installed version of this package
                   98560:      * @abstract
                   98561:      */
                   98562:     function init($xml, $fileAttributes, $lastVersion)
                   98563:     {
                   98564:     }
                   98565: 
                   98566:     /**
                   98567:      * Begin a task processing session.  All multiple tasks will be processed after each file
                   98568:      * has been successfully installed, all simple tasks should perform their task here and
                   98569:      * return any errors using the custom throwError() method to allow forward compatibility
                   98570:      *
                   98571:      * This method MUST NOT write out any changes to disk
                   98572:      * @param PEAR_PackageFile_v2
                   98573:      * @param string file contents
                   98574:      * @param string the eventual final file location (informational only)
                   98575:      * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
                   98576:      *         (use $this->throwError), otherwise return the new contents
                   98577:      * @abstract
                   98578:      */
                   98579:     function startSession($pkg, $contents, $dest)
                   98580:     {
                   98581:     }
                   98582: 
                   98583:     /**
                   98584:      * This method is used to process each of the tasks for a particular multiple class
                   98585:      * type.  Simple tasks need not implement this method.
                   98586:      * @param array an array of tasks
                   98587:      * @access protected
                   98588:      * @static
                   98589:      * @abstract
                   98590:      */
                   98591:     function run($tasks)
                   98592:     {
                   98593:     }
                   98594: 
                   98595:     /**
                   98596:      * @static
                   98597:      * @final
                   98598:      */
                   98599:     function hasPostinstallTasks()
                   98600:     {
                   98601:         return isset($GLOBALS['_PEAR_TASK_POSTINSTANCES']);
                   98602:     }
                   98603: 
                   98604:     /**
                   98605:      * @static
                   98606:      * @final
                   98607:      */
                   98608:      function runPostinstallTasks()
                   98609:      {
                   98610:          foreach ($GLOBALS['_PEAR_TASK_POSTINSTANCES'] as $class => $tasks) {
                   98611:              $err = call_user_func(array($class, 'run'),
                   98612:                   $GLOBALS['_PEAR_TASK_POSTINSTANCES'][$class]);
                   98613:              if ($err) {
                   98614:                  return PEAR_Task_Common::throwError($err);
                   98615:              }
                   98616:          }
                   98617:          unset($GLOBALS['_PEAR_TASK_POSTINSTANCES']);
                   98618:     }
                   98619: 
                   98620:     /**
                   98621:      * Determines whether a role is a script
                   98622:      * @return bool
                   98623:      */
                   98624:     function isScript()
                   98625:     {
                   98626:         return $this->type == 'script';
                   98627:     }
                   98628: 
                   98629:     function throwError($msg, $code = -1)
                   98630:     {
                   98631:         include_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   98632:         return PEAR::raiseError($msg, $code);
                   98633:     }
                   98634: }
                   98635: ?><?php
                   98636: /**
                   98637:  * <tasks:postinstallscript>
                   98638:  *
                   98639:  * PHP versions 4 and 5
                   98640:  *
                   98641:  * @category   pear
                   98642:  * @package    PEAR
                   98643:  * @author     Greg Beaver <cellog@php.net>
                   98644:  * @copyright  1997-2009 The Authors
                   98645:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    98646:  * @version    CVS: $Id: Postinstallscript.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    98647:  * @link       http://pear.php.net/package/PEAR
                   98648:  * @since      File available since Release 1.4.0a1
                   98649:  */
                   98650: /**
                   98651:  * Base class
                   98652:  */
                   98653: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Common.php';
                   98654: /**
                   98655:  * Implements the postinstallscript file task.
                   98656:  *
                   98657:  * Note that post-install scripts are handled separately from installation, by the
                   98658:  * "pear run-scripts" command
                   98659:  * @category   pear
                   98660:  * @package    PEAR
                   98661:  * @author     Greg Beaver <cellog@php.net>
                   98662:  * @copyright  1997-2009 The Authors
                   98663:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    98664:  * @version    Release: 1.9.4
1.1       misho    98665:  * @link       http://pear.php.net/package/PEAR
                   98666:  * @since      Class available since Release 1.4.0a1
                   98667:  */
                   98668: class PEAR_Task_Postinstallscript extends PEAR_Task_Common
                   98669: {
                   98670:     var $type = 'script';
                   98671:     var $_class;
                   98672:     var $_params;
                   98673:     var $_obj;
                   98674:     /**
                   98675:      *
                   98676:      * @var PEAR_PackageFile_v2
                   98677:      */
                   98678:     var $_pkg;
                   98679:     var $_contents;
                   98680:     var $phase = PEAR_TASK_INSTALL;
                   98681: 
                   98682:     /**
                   98683:      * Validate the raw xml at parsing-time.
                   98684:      *
                   98685:      * This also attempts to validate the script to make sure it meets the criteria
                   98686:      * for a post-install script
                   98687:      * @param PEAR_PackageFile_v2
                   98688:      * @param array The XML contents of the <postinstallscript> tag
                   98689:      * @param PEAR_Config
                   98690:      * @param array the entire parsed <file> tag
                   98691:      * @static
                   98692:      */
                   98693:     function validateXml($pkg, $xml, $config, $fileXml)
                   98694:     {
                   98695:         if ($fileXml['role'] != 'php') {
                   98696:             return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   98697:             $fileXml['name'] . '" must be role="php"');
                   98698:         }
                   98699:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   98700:         $file = $pkg->getFileContents($fileXml['name']);
                   98701:         if (PEAR::isError($file)) {
                   98702:             PEAR::popErrorHandling();
                   98703:             return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   98704:                 $fileXml['name'] . '" is not valid: ' .
                   98705:                 $file->getMessage());
                   98706:         } elseif ($file === null) {
                   98707:             return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   98708:                 $fileXml['name'] . '" could not be retrieved for processing!');
                   98709:         } else {
                   98710:             $analysis = $pkg->analyzeSourceCode($file, true);
                   98711:             if (!$analysis) {
                   98712:                 PEAR::popErrorHandling();
                   98713:                 $warnings = '';
                   98714:                 foreach ($pkg->getValidationWarnings() as $warn) {
                   98715:                     $warnings .= $warn['message'] . "\n";
                   98716:                 }
                   98717:                 return array(PEAR_TASK_ERROR_INVALID, 'Analysis of post-install script "' .
                   98718:                     $fileXml['name'] . '" failed: ' . $warnings);
                   98719:             }
                   98720:             if (count($analysis['declared_classes']) != 1) {
                   98721:                 PEAR::popErrorHandling();
                   98722:                 return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   98723:                     $fileXml['name'] . '" must declare exactly 1 class');
                   98724:             }
                   98725:             $class = $analysis['declared_classes'][0];
                   98726:             if ($class != str_replace(array('/', '.php'), array('_', ''),
                   98727:                   $fileXml['name']) . '_postinstall') {
                   98728:                 PEAR::popErrorHandling();
                   98729:                 return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   98730:                     $fileXml['name'] . '" class "' . $class . '" must be named "' .
                   98731:                     str_replace(array('/', '.php'), array('_', ''),
                   98732:                     $fileXml['name']) . '_postinstall"');
                   98733:             }
                   98734:             if (!isset($analysis['declared_methods'][$class])) {
                   98735:                 PEAR::popErrorHandling();
                   98736:                 return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   98737:                     $fileXml['name'] . '" must declare methods init() and run()');
                   98738:             }
                   98739:             $methods = array('init' => 0, 'run' => 1);
                   98740:             foreach ($analysis['declared_methods'][$class] as $method) {
                   98741:                 if (isset($methods[$method])) {
                   98742:                     unset($methods[$method]);
                   98743:                 }
                   98744:             }
                   98745:             if (count($methods)) {
                   98746:                 PEAR::popErrorHandling();
                   98747:                 return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   98748:                     $fileXml['name'] . '" must declare methods init() and run()');
                   98749:             }
                   98750:         }
                   98751:         PEAR::popErrorHandling();
                   98752:         $definedparams = array();
                   98753:         $tasksNamespace = $pkg->getTasksNs() . ':';
                   98754:         if (!isset($xml[$tasksNamespace . 'paramgroup']) && isset($xml['paramgroup'])) {
                   98755:             // in order to support the older betas, which did not expect internal tags
                   98756:             // to also use the namespace
                   98757:             $tasksNamespace = '';
                   98758:         }
                   98759:         if (isset($xml[$tasksNamespace . 'paramgroup'])) {
                   98760:             $params = $xml[$tasksNamespace . 'paramgroup'];
                   98761:             if (!is_array($params) || !isset($params[0])) {
                   98762:                 $params = array($params);
                   98763:             }
                   98764:             foreach ($params as $param) {
                   98765:                 if (!isset($param[$tasksNamespace . 'id'])) {
                   98766:                     return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   98767:                         $fileXml['name'] . '" <paramgroup> must have ' .
                   98768:                         'an ' . $tasksNamespace . 'id> tag');
                   98769:                 }
                   98770:                 if (isset($param[$tasksNamespace . 'name'])) {
                   98771:                     if (!in_array($param[$tasksNamespace . 'name'], $definedparams)) {
                   98772:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   98773:                             $fileXml['name'] . '" ' . $tasksNamespace .
                   98774:                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
                   98775:                             '" parameter "' . $param[$tasksNamespace . 'name'] .
                   98776:                             '" has not been previously defined');
                   98777:                     }
                   98778:                     if (!isset($param[$tasksNamespace . 'conditiontype'])) {
                   98779:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   98780:                             $fileXml['name'] . '" ' . $tasksNamespace .
                   98781:                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
                   98782:                             '" must have a ' . $tasksNamespace .
                   98783:                             'conditiontype> tag containing either "=", ' .
                   98784:                             '"!=", or "preg_match"');
                   98785:                     }
                   98786:                     if (!in_array($param[$tasksNamespace . 'conditiontype'],
                   98787:                           array('=', '!=', 'preg_match'))) {
                   98788:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   98789:                             $fileXml['name'] . '" ' . $tasksNamespace .
                   98790:                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
                   98791:                             '" must have a ' . $tasksNamespace .
                   98792:                             'conditiontype> tag containing either "=", ' .
                   98793:                             '"!=", or "preg_match"');
                   98794:                     }
                   98795:                     if (!isset($param[$tasksNamespace . 'value'])) {
                   98796:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   98797:                             $fileXml['name'] . '" ' . $tasksNamespace .
                   98798:                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
                   98799:                             '" must have a ' . $tasksNamespace .
                   98800:                             'value> tag containing expected parameter value');
                   98801:                     }
                   98802:                 }
                   98803:                 if (isset($param[$tasksNamespace . 'instructions'])) {
                   98804:                     if (!is_string($param[$tasksNamespace . 'instructions'])) {
                   98805:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   98806:                             $fileXml['name'] . '" ' . $tasksNamespace .
                   98807:                             'paramgroup> id "' . $param[$tasksNamespace . 'id'] .
                   98808:                             '" ' . $tasksNamespace . 'instructions> must be simple text');
                   98809:                     }
                   98810:                 }
                   98811:                 if (!isset($param[$tasksNamespace . 'param'])) {
                   98812:                     continue; // <param> is no longer required
                   98813:                 }
                   98814:                 $subparams = $param[$tasksNamespace . 'param'];
                   98815:                 if (!is_array($subparams) || !isset($subparams[0])) {
                   98816:                     $subparams = array($subparams);
                   98817:                 }
                   98818:                 foreach ($subparams as $subparam) {
                   98819:                     if (!isset($subparam[$tasksNamespace . 'name'])) {
                   98820:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   98821:                             $fileXml['name'] . '" parameter for ' .
                   98822:                             $tasksNamespace . 'paramgroup> id "' .
                   98823:                             $param[$tasksNamespace . 'id'] . '" must have ' .
                   98824:                             'a ' . $tasksNamespace . 'name> tag');
                   98825:                     }
                   98826:                     if (!preg_match('/[a-zA-Z0-9]+/',
                   98827:                           $subparam[$tasksNamespace . 'name'])) {
                   98828:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   98829:                             $fileXml['name'] . '" parameter "' .
                   98830:                             $subparam[$tasksNamespace . 'name'] .
                   98831:                             '" for ' . $tasksNamespace . 'paramgroup> id "' .
                   98832:                             $param[$tasksNamespace . 'id'] .
                   98833:                             '" is not a valid name.  Must contain only alphanumeric characters');
                   98834:                     }
                   98835:                     if (!isset($subparam[$tasksNamespace . 'prompt'])) {
                   98836:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   98837:                             $fileXml['name'] . '" parameter "' .
                   98838:                             $subparam[$tasksNamespace . 'name'] .
                   98839:                             '" for ' . $tasksNamespace . 'paramgroup> id "' .
                   98840:                             $param[$tasksNamespace . 'id'] .
                   98841:                             '" must have a ' . $tasksNamespace . 'prompt> tag');
                   98842:                     }
                   98843:                     if (!isset($subparam[$tasksNamespace . 'type'])) {
                   98844:                         return array(PEAR_TASK_ERROR_INVALID, 'Post-install script "' .
                   98845:                             $fileXml['name'] . '" parameter "' .
                   98846:                             $subparam[$tasksNamespace . 'name'] .
                   98847:                             '" for ' . $tasksNamespace . 'paramgroup> id "' .
                   98848:                             $param[$tasksNamespace . 'id'] .
                   98849:                             '" must have a ' . $tasksNamespace . 'type> tag');
                   98850:                     }
                   98851:                     $definedparams[] = $param[$tasksNamespace . 'id'] . '::' .
                   98852:                     $subparam[$tasksNamespace . 'name'];
                   98853:                 }
                   98854:             }
                   98855:         }
                   98856:         return true;
                   98857:     }
                   98858: 
                   98859:     /**
                   98860:      * Initialize a task instance with the parameters
                   98861:      * @param array raw, parsed xml
                   98862:      * @param array attributes from the <file> tag containing this task
                   98863:      * @param string|null last installed version of this package, if any (useful for upgrades)
                   98864:      */
                   98865:     function init($xml, $fileattribs, $lastversion)
                   98866:     {
                   98867:         $this->_class = str_replace('/', '_', $fileattribs['name']);
                   98868:         $this->_filename = $fileattribs['name'];
                   98869:         $this->_class = str_replace ('.php', '', $this->_class) . '_postinstall';
                   98870:         $this->_params = $xml;
                   98871:         $this->_lastversion = $lastversion;
                   98872:     }
                   98873: 
                   98874:     /**
                   98875:      * Strip the tasks: namespace from internal params
                   98876:      *
                   98877:      * @access private
                   98878:      */
                   98879:     function _stripNamespace($params = null)
                   98880:     {
                   98881:         if ($params === null) {
                   98882:             $params = array();
                   98883:             if (!is_array($this->_params)) {
                   98884:                 return;
                   98885:             }
                   98886:             foreach ($this->_params as $i => $param) {
                   98887:                 if (is_array($param)) {
                   98888:                     $param = $this->_stripNamespace($param);
                   98889:                 }
                   98890:                 $params[str_replace($this->_pkg->getTasksNs() . ':', '', $i)] = $param;
                   98891:             }
                   98892:             $this->_params = $params;
                   98893:         } else {
                   98894:             $newparams = array();
                   98895:             foreach ($params as $i => $param) {
                   98896:                 if (is_array($param)) {
                   98897:                     $param = $this->_stripNamespace($param);
                   98898:                 }
                   98899:                 $newparams[str_replace($this->_pkg->getTasksNs() . ':', '', $i)] = $param;
                   98900:             }
                   98901:             return $newparams;
                   98902:         }
                   98903:     }
                   98904: 
                   98905:     /**
                   98906:      * Unlike other tasks, the installed file name is passed in instead of the file contents,
                   98907:      * because this task is handled post-installation
                   98908:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   98909:      * @param string file name
                   98910:      * @return bool|PEAR_Error false to skip this file, PEAR_Error to fail
                   98911:      *         (use $this->throwError)
                   98912:      */
                   98913:     function startSession($pkg, $contents)
                   98914:     {
                   98915:         if ($this->installphase != PEAR_TASK_INSTALL) {
                   98916:             return false;
                   98917:         }
                   98918:         // remove the tasks: namespace if present
                   98919:         $this->_pkg = $pkg;
                   98920:         $this->_stripNamespace();
                   98921:         $this->logger->log(0, 'Including external post-installation script "' .
                   98922:             $contents . '" - any errors are in this script');
                   98923:         include_once 'phar://install-pear-nozlib.phar/' . $contents;
                   98924:         if (class_exists($this->_class)) {
                   98925:             $this->logger->log(0, 'Inclusion succeeded');
                   98926:         } else {
                   98927:             return $this->throwError('init of post-install script class "' . $this->_class
                   98928:                 . '" failed');
                   98929:         }
                   98930:         $this->_obj = new $this->_class;
                   98931:         $this->logger->log(1, 'running post-install script "' . $this->_class . '->init()"');
                   98932:         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
                   98933:         $res = $this->_obj->init($this->config, $pkg, $this->_lastversion);
                   98934:         PEAR::popErrorHandling();
                   98935:         if ($res) {
                   98936:             $this->logger->log(0, 'init succeeded');
                   98937:         } else {
                   98938:             return $this->throwError('init of post-install script "' . $this->_class .
                   98939:                 '->init()" failed');
                   98940:         }
                   98941:         $this->_contents = $contents;
                   98942:         return true;
                   98943:     }
                   98944: 
                   98945:     /**
                   98946:      * No longer used
                   98947:      * @see PEAR_PackageFile_v2::runPostinstallScripts()
                   98948:      * @param array an array of tasks
                   98949:      * @param string install or upgrade
                   98950:      * @access protected
                   98951:      * @static
                   98952:      */
                   98953:     function run()
                   98954:     {
                   98955:     }
                   98956: }
                   98957: ?><?php
                   98958: /**
                   98959:  * <tasks:postinstallscript> - read/write version
                   98960:  *
                   98961:  * PHP versions 4 and 5
                   98962:  *
                   98963:  * @category   pear
                   98964:  * @package    PEAR
                   98965:  * @author     Greg Beaver <cellog@php.net>
                   98966:  * @copyright  1997-2009 The Authors
                   98967:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    98968:  * @version    CVS: $Id: rw.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    98969:  * @link       http://pear.php.net/package/PEAR
                   98970:  * @since      File available since Release 1.4.0a10
                   98971:  */
                   98972: /**
                   98973:  * Base class
                   98974:  */
                   98975: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Postinstallscript.php';
                   98976: /**
                   98977:  * Abstracts the postinstallscript file task xml.
                   98978:  * @category   pear
                   98979:  * @package    PEAR
                   98980:  * @author     Greg Beaver <cellog@php.net>
                   98981:  * @copyright  1997-2009 The Authors
                   98982:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    98983:  * @version    Release: 1.9.4
1.1       misho    98984:  * @link       http://pear.php.net/package/PEAR
                   98985:  * @since      Class available since Release 1.4.0a10
                   98986:  */
                   98987: class PEAR_Task_Postinstallscript_rw extends PEAR_Task_Postinstallscript
                   98988: {
                   98989:     /**
                   98990:      * parent package file object
                   98991:      *
                   98992:      * @var PEAR_PackageFile_v2_rw
                   98993:      */
                   98994:     var $_pkg;
                   98995:     /**
                   98996:      * Enter description here...
                   98997:      *
                   98998:      * @param PEAR_PackageFile_v2_rw $pkg
                   98999:      * @param PEAR_Config $config
                   99000:      * @param PEAR_Frontend $logger
                   99001:      * @param array $fileXml
                   99002:      * @return PEAR_Task_Postinstallscript_rw
                   99003:      */
                   99004:     function PEAR_Task_Postinstallscript_rw(&$pkg, &$config, &$logger, $fileXml)
                   99005:     {
                   99006:         parent::PEAR_Task_Common($config, $logger, PEAR_TASK_PACKAGE);
                   99007:         $this->_contents = $fileXml;
                   99008:         $this->_pkg = &$pkg;
                   99009:         $this->_params = array();
                   99010:     }
                   99011: 
                   99012:     function validate()
                   99013:     {
                   99014:         return $this->validateXml($this->_pkg, $this->_params, $this->config, $this->_contents);
                   99015:     }
                   99016: 
                   99017:     function getName()
                   99018:     {
                   99019:         return 'postinstallscript';
                   99020:     }
                   99021: 
                   99022:     /**
                   99023:      * add a simple <paramgroup> to the post-install script
                   99024:      *
                   99025:      * Order is significant, so call this method in the same
                   99026:      * sequence the users should see the paramgroups.  The $params
                   99027:      * parameter should either be the result of a call to {@link getParam()}
                   99028:      * or an array of calls to getParam().
                   99029:      *
                   99030:      * Use {@link addConditionTypeGroup()} to add a <paramgroup> containing
                   99031:      * a <conditiontype> tag
                   99032:      * @param string $id <paramgroup> id as seen by the script
                   99033:      * @param array|false $params array of getParam() calls, or false for no params
                   99034:      * @param string|false $instructions
                   99035:      */
                   99036:     function addParamGroup($id, $params = false, $instructions = false)
                   99037:     {
                   99038:         if ($params && isset($params[0]) && !isset($params[1])) {
                   99039:             $params = $params[0];
                   99040:         }
                   99041:         $stuff =
                   99042:             array(
                   99043:                 $this->_pkg->getTasksNs() . ':id' => $id,
                   99044:             );
                   99045:         if ($instructions) {
                   99046:             $stuff[$this->_pkg->getTasksNs() . ':instructions'] = $instructions;
                   99047:         }
                   99048:         if ($params) {
                   99049:             $stuff[$this->_pkg->getTasksNs() . ':param'] = $params;
                   99050:         }
                   99051:         $this->_params[$this->_pkg->getTasksNs() . ':paramgroup'][] = $stuff;
                   99052:     }
                   99053: 
                   99054:     /**
                   99055:      * add a complex <paramgroup> to the post-install script with conditions
                   99056:      *
                   99057:      * This inserts a <paramgroup> with
                   99058:      *
                   99059:      * Order is significant, so call this method in the same
                   99060:      * sequence the users should see the paramgroups.  The $params
                   99061:      * parameter should either be the result of a call to {@link getParam()}
                   99062:      * or an array of calls to getParam().
                   99063:      *
                   99064:      * Use {@link addParamGroup()} to add a simple <paramgroup>
                   99065:      *
                   99066:      * @param string $id <paramgroup> id as seen by the script
                   99067:      * @param string $oldgroup <paramgroup> id of the section referenced by
                   99068:      *                         <conditiontype>
                   99069:      * @param string $param name of the <param> from the older section referenced
                   99070:      *                      by <contitiontype>
                   99071:      * @param string $value value to match of the parameter
                   99072:      * @param string $conditiontype one of '=', '!=', 'preg_match'
                   99073:      * @param array|false $params array of getParam() calls, or false for no params
                   99074:      * @param string|false $instructions
                   99075:      */
                   99076:     function addConditionTypeGroup($id, $oldgroup, $param, $value, $conditiontype = '=',
                   99077:                                    $params = false, $instructions = false)
                   99078:     {
                   99079:         if ($params && isset($params[0]) && !isset($params[1])) {
                   99080:             $params = $params[0];
                   99081:         }
                   99082:         $stuff = array(
                   99083:             $this->_pkg->getTasksNs() . ':id' => $id,
                   99084:         );
                   99085:         if ($instructions) {
                   99086:             $stuff[$this->_pkg->getTasksNs() . ':instructions'] = $instructions;
                   99087:         }
                   99088:         $stuff[$this->_pkg->getTasksNs() . ':name'] = $oldgroup . '::' . $param;
                   99089:         $stuff[$this->_pkg->getTasksNs() . ':conditiontype'] = $conditiontype;
                   99090:         $stuff[$this->_pkg->getTasksNs() . ':value'] = $value;
                   99091:         if ($params) {
                   99092:             $stuff[$this->_pkg->getTasksNs() . ':param'] = $params;
                   99093:         }
                   99094:         $this->_params[$this->_pkg->getTasksNs() . ':paramgroup'][] = $stuff;
                   99095:     }
                   99096: 
                   99097:     function getXml()
                   99098:     {
                   99099:         return $this->_params;
                   99100:     }
                   99101: 
                   99102:     /**
                   99103:      * Use to set up a param tag for use in creating a paramgroup
                   99104:      * @static
                   99105:      */
                   99106:     function getParam($name, $prompt, $type = 'string', $default = null)
                   99107:     {
                   99108:         if ($default !== null) {
                   99109:             return
                   99110:             array(
                   99111:                 $this->_pkg->getTasksNs() . ':name' => $name,
                   99112:                 $this->_pkg->getTasksNs() . ':prompt' => $prompt,
                   99113:                 $this->_pkg->getTasksNs() . ':type' => $type,
                   99114:                 $this->_pkg->getTasksNs() . ':default' => $default
                   99115:             );
                   99116:         }
                   99117:         return
                   99118:             array(
                   99119:                 $this->_pkg->getTasksNs() . ':name' => $name,
                   99120:                 $this->_pkg->getTasksNs() . ':prompt' => $prompt,
                   99121:                 $this->_pkg->getTasksNs() . ':type' => $type,
                   99122:             );
                   99123:     }
                   99124: }
                   99125: ?><?php
                   99126: /**
                   99127:  * <tasks:replace>
                   99128:  *
                   99129:  * PHP versions 4 and 5
                   99130:  *
                   99131:  * @category   pear
                   99132:  * @package    PEAR
                   99133:  * @author     Greg Beaver <cellog@php.net>
                   99134:  * @copyright  1997-2009 The Authors
                   99135:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    99136:  * @version    CVS: $Id: Replace.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    99137:  * @link       http://pear.php.net/package/PEAR
                   99138:  * @since      File available since Release 1.4.0a1
                   99139:  */
                   99140: /**
                   99141:  * Base class
                   99142:  */
                   99143: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Common.php';
                   99144: /**
                   99145:  * Implements the replace file task.
                   99146:  * @category   pear
                   99147:  * @package    PEAR
                   99148:  * @author     Greg Beaver <cellog@php.net>
                   99149:  * @copyright  1997-2009 The Authors
                   99150:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    99151:  * @version    Release: 1.9.4
1.1       misho    99152:  * @link       http://pear.php.net/package/PEAR
                   99153:  * @since      Class available since Release 1.4.0a1
                   99154:  */
                   99155: class PEAR_Task_Replace extends PEAR_Task_Common
                   99156: {
                   99157:     var $type = 'simple';
                   99158:     var $phase = PEAR_TASK_PACKAGEANDINSTALL;
                   99159:     var $_replacements;
                   99160: 
                   99161:     /**
                   99162:      * Validate the raw xml at parsing-time.
                   99163:      * @param PEAR_PackageFile_v2
                   99164:      * @param array raw, parsed xml
                   99165:      * @param PEAR_Config
                   99166:      * @static
                   99167:      */
                   99168:     function validateXml($pkg, $xml, $config, $fileXml)
                   99169:     {
                   99170:         if (!isset($xml['attribs'])) {
                   99171:             return array(PEAR_TASK_ERROR_NOATTRIBS);
                   99172:         }
                   99173:         if (!isset($xml['attribs']['type'])) {
                   99174:             return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'type');
                   99175:         }
                   99176:         if (!isset($xml['attribs']['to'])) {
                   99177:             return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'to');
                   99178:         }
                   99179:         if (!isset($xml['attribs']['from'])) {
                   99180:             return array(PEAR_TASK_ERROR_MISSING_ATTRIB, 'from');
                   99181:         }
                   99182:         if ($xml['attribs']['type'] == 'pear-config') {
                   99183:             if (!in_array($xml['attribs']['to'], $config->getKeys())) {
                   99184:                 return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'],
                   99185:                     $config->getKeys());
                   99186:             }
                   99187:         } elseif ($xml['attribs']['type'] == 'php-const') {
                   99188:             if (defined($xml['attribs']['to'])) {
                   99189:                 return true;
                   99190:             } else {
                   99191:                 return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'],
                   99192:                     array('valid PHP constant'));
                   99193:             }
                   99194:         } elseif ($xml['attribs']['type'] == 'package-info') {
                   99195:             if (in_array($xml['attribs']['to'],
                   99196:                 array('name', 'summary', 'channel', 'notes', 'extends', 'description',
                   99197:                     'release_notes', 'license', 'release-license', 'license-uri',
                   99198:                     'version', 'api-version', 'state', 'api-state', 'release_date',
                   99199:                     'date', 'time'))) {
                   99200:                 return true;
                   99201:             } else {
                   99202:                 return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'to', $xml['attribs']['to'],
                   99203:                     array('name', 'summary', 'channel', 'notes', 'extends', 'description',
                   99204:                     'release_notes', 'license', 'release-license', 'license-uri',
                   99205:                     'version', 'api-version', 'state', 'api-state', 'release_date',
                   99206:                     'date', 'time'));
                   99207:             }
                   99208:         } else {
                   99209:             return array(PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE, 'type', $xml['attribs']['type'],
                   99210:                 array('pear-config', 'package-info', 'php-const'));
                   99211:         }
                   99212:         return true;
                   99213:     }
                   99214: 
                   99215:     /**
                   99216:      * Initialize a task instance with the parameters
                   99217:      * @param array raw, parsed xml
                   99218:      * @param unused
                   99219:      */
                   99220:     function init($xml, $attribs)
                   99221:     {
                   99222:         $this->_replacements = isset($xml['attribs']) ? array($xml) : $xml;
                   99223:     }
                   99224: 
                   99225:     /**
                   99226:      * Do a package.xml 1.0 replacement, with additional package-info fields available
                   99227:      *
                   99228:      * See validateXml() source for the complete list of allowed fields
                   99229:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   99230:      * @param string file contents
                   99231:      * @param string the eventual final file location (informational only)
                   99232:      * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
                   99233:      *         (use $this->throwError), otherwise return the new contents
                   99234:      */
                   99235:     function startSession($pkg, $contents, $dest)
                   99236:     {
                   99237:         $subst_from = $subst_to = array();
                   99238:         foreach ($this->_replacements as $a) {
                   99239:             $a = $a['attribs'];
                   99240:             $to = '';
                   99241:             if ($a['type'] == 'pear-config') {
                   99242:                 if ($this->installphase == PEAR_TASK_PACKAGE) {
                   99243:                     return false;
                   99244:                 }
                   99245:                 if ($a['to'] == 'master_server') {
                   99246:                     $chan = $this->registry->getChannel($pkg->getChannel());
                   99247:                     if (!PEAR::isError($chan)) {
                   99248:                         $to = $chan->getServer();
                   99249:                     } else {
                   99250:                         $this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]");
                   99251:                         return false;
                   99252:                     }
                   99253:                 } else {
                   99254:                     if ($this->config->isDefinedLayer('ftp')) {
                   99255:                         // try the remote config file first
                   99256:                         $to = $this->config->get($a['to'], 'ftp', $pkg->getChannel());
                   99257:                         if (is_null($to)) {
                   99258:                             // then default to local
                   99259:                             $to = $this->config->get($a['to'], null, $pkg->getChannel());
                   99260:                         }
                   99261:                     } else {
                   99262:                         $to = $this->config->get($a['to'], null, $pkg->getChannel());
                   99263:                     }
                   99264:                 }
                   99265:                 if (is_null($to)) {
                   99266:                     $this->logger->log(0, "$dest: invalid pear-config replacement: $a[to]");
                   99267:                     return false;
                   99268:                 }
                   99269:             } elseif ($a['type'] == 'php-const') {
                   99270:                 if ($this->installphase == PEAR_TASK_PACKAGE) {
                   99271:                     return false;
                   99272:                 }
                   99273:                 if (defined($a['to'])) {
                   99274:                     $to = constant($a['to']);
                   99275:                 } else {
                   99276:                     $this->logger->log(0, "$dest: invalid php-const replacement: $a[to]");
                   99277:                     return false;
                   99278:                 }
                   99279:             } else {
                   99280:                 if ($t = $pkg->packageInfo($a['to'])) {
                   99281:                     $to = $t;
                   99282:                 } else {
                   99283:                     $this->logger->log(0, "$dest: invalid package-info replacement: $a[to]");
                   99284:                     return false;
                   99285:                 }
                   99286:             }
                   99287:             if (!is_null($to)) {
                   99288:                 $subst_from[] = $a['from'];
                   99289:                 $subst_to[] = $to;
                   99290:             }
                   99291:         }
                   99292:         $this->logger->log(3, "doing " . sizeof($subst_from) .
                   99293:             " substitution(s) for $dest");
                   99294:         if (sizeof($subst_from)) {
                   99295:             $contents = str_replace($subst_from, $subst_to, $contents);
                   99296:         }
                   99297:         return $contents;
                   99298:     }
                   99299: }
                   99300: ?><?php
                   99301: /**
                   99302:  * <tasks:replace> - read/write version
                   99303:  *
                   99304:  * PHP versions 4 and 5
                   99305:  *
                   99306:  * @category   pear
                   99307:  * @package    PEAR
                   99308:  * @author     Greg Beaver <cellog@php.net>
                   99309:  * @copyright  1997-2009 The Authors
                   99310:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    99311:  * @version    CVS: $Id: rw.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    99312:  * @link       http://pear.php.net/package/PEAR
                   99313:  * @since      File available since Release 1.4.0a10
                   99314:  */
                   99315: /**
                   99316:  * Base class
                   99317:  */
                   99318: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Replace.php';
                   99319: /**
                   99320:  * Abstracts the replace task xml.
                   99321:  * @category   pear
                   99322:  * @package    PEAR
                   99323:  * @author     Greg Beaver <cellog@php.net>
                   99324:  * @copyright  1997-2009 The Authors
                   99325:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    99326:  * @version    Release: 1.9.4
1.1       misho    99327:  * @link       http://pear.php.net/package/PEAR
                   99328:  * @since      Class available since Release 1.4.0a10
                   99329:  */
                   99330: class PEAR_Task_Replace_rw extends PEAR_Task_Replace
                   99331: {
                   99332:     function PEAR_Task_Replace_rw(&$pkg, &$config, &$logger, $fileXml)
                   99333:     {
                   99334:         parent::PEAR_Task_Common($config, $logger, PEAR_TASK_PACKAGE);
                   99335:         $this->_contents = $fileXml;
                   99336:         $this->_pkg = &$pkg;
                   99337:         $this->_params = array();
                   99338:     }
                   99339: 
                   99340:     function validate()
                   99341:     {
                   99342:         return $this->validateXml($this->_pkg, $this->_params, $this->config, $this->_contents);
                   99343:     }
                   99344: 
                   99345:     function setInfo($from, $to, $type)
                   99346:     {
                   99347:         $this->_params = array('attribs' => array('from' => $from, 'to' => $to, 'type' => $type));
                   99348:     }
                   99349: 
                   99350:     function getName()
                   99351:     {
                   99352:         return 'replace';
                   99353:     }
                   99354: 
                   99355:     function getXml()
                   99356:     {
                   99357:         return $this->_params;
                   99358:     }
                   99359: }
                   99360: ?><?php
                   99361: /**
                   99362:  * <tasks:unixeol>
                   99363:  *
                   99364:  * PHP versions 4 and 5
                   99365:  *
                   99366:  * @category   pear
                   99367:  * @package    PEAR
                   99368:  * @author     Greg Beaver <cellog@php.net>
                   99369:  * @copyright  1997-2009 The Authors
                   99370:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    99371:  * @version    CVS: $Id: Unixeol.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    99372:  * @link       http://pear.php.net/package/PEAR
                   99373:  * @since      File available since Release 1.4.0a1
                   99374:  */
                   99375: /**
                   99376:  * Base class
                   99377:  */
                   99378: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Common.php';
                   99379: /**
                   99380:  * Implements the unix line endings file task.
                   99381:  * @category   pear
                   99382:  * @package    PEAR
                   99383:  * @author     Greg Beaver <cellog@php.net>
                   99384:  * @copyright  1997-2009 The Authors
                   99385:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    99386:  * @version    Release: 1.9.4
1.1       misho    99387:  * @link       http://pear.php.net/package/PEAR
                   99388:  * @since      Class available since Release 1.4.0a1
                   99389:  */
                   99390: class PEAR_Task_Unixeol extends PEAR_Task_Common
                   99391: {
                   99392:     var $type = 'simple';
                   99393:     var $phase = PEAR_TASK_PACKAGE;
                   99394:     var $_replacements;
                   99395: 
                   99396:     /**
                   99397:      * Validate the raw xml at parsing-time.
                   99398:      * @param PEAR_PackageFile_v2
                   99399:      * @param array raw, parsed xml
                   99400:      * @param PEAR_Config
                   99401:      * @static
                   99402:      */
                   99403:     function validateXml($pkg, $xml, $config, $fileXml)
                   99404:     {
                   99405:         if ($xml != '') {
                   99406:             return array(PEAR_TASK_ERROR_INVALID, 'no attributes allowed');
                   99407:         }
                   99408:         return true;
                   99409:     }
                   99410: 
                   99411:     /**
                   99412:      * Initialize a task instance with the parameters
                   99413:      * @param array raw, parsed xml
                   99414:      * @param unused
                   99415:      */
                   99416:     function init($xml, $attribs)
                   99417:     {
                   99418:     }
                   99419: 
                   99420:     /**
                   99421:      * Replace all line endings with line endings customized for the current OS
                   99422:      *
                   99423:      * See validateXml() source for the complete list of allowed fields
                   99424:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   99425:      * @param string file contents
                   99426:      * @param string the eventual final file location (informational only)
                   99427:      * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
                   99428:      *         (use $this->throwError), otherwise return the new contents
                   99429:      */
                   99430:     function startSession($pkg, $contents, $dest)
                   99431:     {
                   99432:         $this->logger->log(3, "replacing all line endings with \\n in $dest");
                   99433:         return preg_replace("/\r\n|\n\r|\r|\n/", "\n", $contents);
                   99434:     }
                   99435: }
                   99436: ?><?php
                   99437: /**
                   99438:  * <tasks:unixeol> - read/write version
                   99439:  *
                   99440:  * PHP versions 4 and 5
                   99441:  *
                   99442:  * @category   pear
                   99443:  * @package    PEAR
                   99444:  * @author     Greg Beaver <cellog@php.net>
                   99445:  * @copyright  1997-2009 The Authors
                   99446:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    99447:  * @version    CVS: $Id: rw.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    99448:  * @link       http://pear.php.net/package/PEAR
                   99449:  * @since      File available since Release 1.4.0a10
                   99450:  */
                   99451: /**
                   99452:  * Base class
                   99453:  */
                   99454: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Unixeol.php';
                   99455: /**
                   99456:  * Abstracts the unixeol task xml.
                   99457:  * @category   pear
                   99458:  * @package    PEAR
                   99459:  * @author     Greg Beaver <cellog@php.net>
                   99460:  * @copyright  1997-2009 The Authors
                   99461:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    99462:  * @version    Release: 1.9.4
1.1       misho    99463:  * @link       http://pear.php.net/package/PEAR
                   99464:  * @since      Class available since Release 1.4.0a10
                   99465:  */
                   99466: class PEAR_Task_Unixeol_rw extends PEAR_Task_Unixeol
                   99467: {
                   99468:     function PEAR_Task_Unixeol_rw(&$pkg, &$config, &$logger, $fileXml)
                   99469:     {
                   99470:         parent::PEAR_Task_Common($config, $logger, PEAR_TASK_PACKAGE);
                   99471:         $this->_contents = $fileXml;
                   99472:         $this->_pkg = &$pkg;
                   99473:         $this->_params = array();
                   99474:     }
                   99475: 
                   99476:     function validate()
                   99477:     {
                   99478:         return true;
                   99479:     }
                   99480: 
                   99481:     function getName()
                   99482:     {
                   99483:         return 'unixeol';
                   99484:     }
                   99485: 
                   99486:     function getXml()
                   99487:     {
                   99488:         return '';
                   99489:     }
                   99490: }
                   99491: ?><?php
                   99492: /**
                   99493:  * <tasks:windowseol>
                   99494:  *
                   99495:  * PHP versions 4 and 5
                   99496:  *
                   99497:  * @category   pear
                   99498:  * @package    PEAR
                   99499:  * @author     Greg Beaver <cellog@php.net>
                   99500:  * @copyright  1997-2009 The Authors
                   99501:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    99502:  * @version    CVS: $Id: Windowseol.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    99503:  * @link       http://pear.php.net/package/PEAR
                   99504:  * @since      File available since Release 1.4.0a1
                   99505:  */
                   99506: /**
                   99507:  * Base class
                   99508:  */
                   99509: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Common.php';
                   99510: /**
                   99511:  * Implements the windows line endsings file task.
                   99512:  * @category   pear
                   99513:  * @package    PEAR
                   99514:  * @author     Greg Beaver <cellog@php.net>
                   99515:  * @copyright  1997-2009 The Authors
                   99516:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    99517:  * @version    Release: 1.9.4
1.1       misho    99518:  * @link       http://pear.php.net/package/PEAR
                   99519:  * @since      Class available since Release 1.4.0a1
                   99520:  */
                   99521: class PEAR_Task_Windowseol extends PEAR_Task_Common
                   99522: {
                   99523:     var $type = 'simple';
                   99524:     var $phase = PEAR_TASK_PACKAGE;
                   99525:     var $_replacements;
                   99526: 
                   99527:     /**
                   99528:      * Validate the raw xml at parsing-time.
                   99529:      * @param PEAR_PackageFile_v2
                   99530:      * @param array raw, parsed xml
                   99531:      * @param PEAR_Config
                   99532:      * @static
                   99533:      */
                   99534:     function validateXml($pkg, $xml, $config, $fileXml)
                   99535:     {
                   99536:         if ($xml != '') {
                   99537:             return array(PEAR_TASK_ERROR_INVALID, 'no attributes allowed');
                   99538:         }
                   99539:         return true;
                   99540:     }
                   99541: 
                   99542:     /**
                   99543:      * Initialize a task instance with the parameters
                   99544:      * @param array raw, parsed xml
                   99545:      * @param unused
                   99546:      */
                   99547:     function init($xml, $attribs)
                   99548:     {
                   99549:     }
                   99550: 
                   99551:     /**
                   99552:      * Replace all line endings with windows line endings
                   99553:      *
                   99554:      * See validateXml() source for the complete list of allowed fields
                   99555:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   99556:      * @param string file contents
                   99557:      * @param string the eventual final file location (informational only)
                   99558:      * @return string|false|PEAR_Error false to skip this file, PEAR_Error to fail
                   99559:      *         (use $this->throwError), otherwise return the new contents
                   99560:      */
                   99561:     function startSession($pkg, $contents, $dest)
                   99562:     {
                   99563:         $this->logger->log(3, "replacing all line endings with \\r\\n in $dest");
                   99564:         return preg_replace("/\r\n|\n\r|\r|\n/", "\r\n", $contents);
                   99565:     }
                   99566: }
                   99567: ?><?php
                   99568: /**
                   99569:  * <tasks:windowseol> - read/write version
                   99570:  *
                   99571:  * PHP versions 4 and 5
                   99572:  *
                   99573:  * @category   pear
                   99574:  * @package    PEAR
                   99575:  * @author     Greg Beaver <cellog@php.net>
                   99576:  * @copyright  1997-2009 The Authors
                   99577:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    99578:  * @version    CVS: $Id: rw.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    99579:  * @link       http://pear.php.net/package/PEAR
                   99580:  * @since      File available since Release 1.4.0a10
                   99581:  */
                   99582: /**
                   99583:  * Base class
                   99584:  */
                   99585: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Task/Windowseol.php';
                   99586: /**
                   99587:  * Abstracts the windowseol task xml.
                   99588:  * @category   pear
                   99589:  * @package    PEAR
                   99590:  * @author     Greg Beaver <cellog@php.net>
                   99591:  * @copyright  1997-2009 The Authors
                   99592:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    99593:  * @version    Release: 1.9.4
1.1       misho    99594:  * @link       http://pear.php.net/package/PEAR
                   99595:  * @since      Class available since Release 1.4.0a10
                   99596:  */
                   99597: class PEAR_Task_Windowseol_rw extends PEAR_Task_Windowseol
                   99598: {
                   99599:     function PEAR_Task_Windowseol_rw(&$pkg, &$config, &$logger, $fileXml)
                   99600:     {
                   99601:         parent::PEAR_Task_Common($config, $logger, PEAR_TASK_PACKAGE);
                   99602:         $this->_contents = $fileXml;
                   99603:         $this->_pkg = &$pkg;
                   99604:         $this->_params = array();
                   99605:     }
                   99606: 
                   99607:     function validate()
                   99608:     {
                   99609:         return true;
                   99610:     }
                   99611: 
                   99612:     function getName()
                   99613:     {
                   99614:         return 'windowseol';
                   99615:     }
                   99616: 
                   99617:     function getXml()
                   99618:     {
                   99619:         return '';
                   99620:     }
                   99621: }
                   99622: ?><?php
                   99623: /**
                   99624:  * PEAR_Validate
                   99625:  *
                   99626:  * PHP versions 4 and 5
                   99627:  *
                   99628:  * @category   pear
                   99629:  * @package    PEAR
                   99630:  * @author     Greg Beaver <cellog@php.net>
                   99631:  * @copyright  1997-2009 The Authors
                   99632:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    99633:  * @version    CVS: $Id: Validate.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    99634:  * @link       http://pear.php.net/package/PEAR
                   99635:  * @since      File available since Release 1.4.0a1
                   99636:  */
                   99637: /**#@+
                   99638:  * Constants for install stage
                   99639:  */
                   99640: define('PEAR_VALIDATE_INSTALLING', 1);
                   99641: define('PEAR_VALIDATE_UNINSTALLING', 2); // this is not bit-mapped like the others
                   99642: define('PEAR_VALIDATE_NORMAL', 3);
                   99643: define('PEAR_VALIDATE_DOWNLOADING', 4); // this is not bit-mapped like the others
                   99644: define('PEAR_VALIDATE_PACKAGING', 7);
                   99645: /**#@-*/
                   99646: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Common.php';
                   99647: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Validator/PECL.php';
                   99648: 
                   99649: /**
                   99650:  * Validation class for package.xml - channel-level advanced validation
                   99651:  * @category   pear
                   99652:  * @package    PEAR
                   99653:  * @author     Greg Beaver <cellog@php.net>
                   99654:  * @copyright  1997-2009 The Authors
                   99655:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    99656:  * @version    Release: 1.9.4
1.1       misho    99657:  * @link       http://pear.php.net/package/PEAR
                   99658:  * @since      Class available since Release 1.4.0a1
                   99659:  */
                   99660: class PEAR_Validate
                   99661: {
                   99662:     var $packageregex = _PEAR_COMMON_PACKAGE_NAME_PREG;
                   99663:     /**
                   99664:      * @var PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   99665:      */
                   99666:     var $_packagexml;
                   99667:     /**
                   99668:      * @var int one of the PEAR_VALIDATE_* constants
                   99669:      */
                   99670:     var $_state = PEAR_VALIDATE_NORMAL;
                   99671:     /**
                   99672:      * Format: ('error' => array('field' => name, 'reason' => reason), 'warning' => same)
                   99673:      * @var array
                   99674:      * @access private
                   99675:      */
                   99676:     var $_failures = array('error' => array(), 'warning' => array());
                   99677: 
                   99678:     /**
                   99679:      * Override this method to handle validation of normal package names
                   99680:      * @param string
                   99681:      * @return bool
                   99682:      * @access protected
                   99683:      */
                   99684:     function _validPackageName($name)
                   99685:     {
                   99686:         return (bool) preg_match('/^' . $this->packageregex . '\\z/', $name);
                   99687:     }
                   99688: 
                   99689:     /**
                   99690:      * @param string package name to validate
                   99691:      * @param string name of channel-specific validation package
                   99692:      * @final
                   99693:      */
                   99694:     function validPackageName($name, $validatepackagename = false)
                   99695:     {
                   99696:         if ($validatepackagename) {
                   99697:             if (strtolower($name) == strtolower($validatepackagename)) {
                   99698:                 return (bool) preg_match('/^[a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)*\\z/', $name);
                   99699:             }
                   99700:         }
                   99701:         return $this->_validPackageName($name);
                   99702:     }
                   99703: 
                   99704:     /**
                   99705:      * This validates a bundle name, and bundle names must conform
                   99706:      * to the PEAR naming convention, so the method is final and static.
                   99707:      * @param string
                   99708:      * @final
                   99709:      * @static
                   99710:      */
                   99711:     function validGroupName($name)
                   99712:     {
                   99713:         return (bool) preg_match('/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/', $name);
                   99714:     }
                   99715: 
                   99716:     /**
                   99717:      * Determine whether $state represents a valid stability level
                   99718:      * @param string
                   99719:      * @return bool
                   99720:      * @static
                   99721:      * @final
                   99722:      */
                   99723:     function validState($state)
                   99724:     {
                   99725:         return in_array($state, array('snapshot', 'devel', 'alpha', 'beta', 'stable'));
                   99726:     }
                   99727: 
                   99728:     /**
                   99729:      * Get a list of valid stability levels
                   99730:      * @return array
                   99731:      * @static
                   99732:      * @final
                   99733:      */
                   99734:     function getValidStates()
                   99735:     {
                   99736:         return array('snapshot', 'devel', 'alpha', 'beta', 'stable');
                   99737:     }
                   99738: 
                   99739:     /**
                   99740:      * Determine whether a version is a properly formatted version number that can be used
                   99741:      * by version_compare
                   99742:      * @param string
                   99743:      * @return bool
                   99744:      * @static
                   99745:      * @final
                   99746:      */
                   99747:     function validVersion($ver)
                   99748:     {
                   99749:         return (bool) preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver);
                   99750:     }
                   99751: 
                   99752:     /**
                   99753:      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
                   99754:      */
                   99755:     function setPackageFile(&$pf)
                   99756:     {
                   99757:         $this->_packagexml = &$pf;
                   99758:     }
                   99759: 
                   99760:     /**
                   99761:      * @access private
                   99762:      */
                   99763:     function _addFailure($field, $reason)
                   99764:     {
                   99765:         $this->_failures['errors'][] = array('field' => $field, 'reason' => $reason);
                   99766:     }
                   99767: 
                   99768:     /**
                   99769:      * @access private
                   99770:      */
                   99771:     function _addWarning($field, $reason)
                   99772:     {
                   99773:         $this->_failures['warnings'][] = array('field' => $field, 'reason' => $reason);
                   99774:     }
                   99775: 
                   99776:     function getFailures()
                   99777:     {
                   99778:         $failures = $this->_failures;
                   99779:         $this->_failures = array('warnings' => array(), 'errors' => array());
                   99780:         return $failures;
                   99781:     }
                   99782: 
                   99783:     /**
                   99784:      * @param int one of the PEAR_VALIDATE_* constants
                   99785:      */
                   99786:     function validate($state = null)
                   99787:     {
                   99788:         if (!isset($this->_packagexml)) {
                   99789:             return false;
                   99790:         }
                   99791:         if ($state !== null) {
                   99792:             $this->_state = $state;
                   99793:         }
                   99794:         $this->_failures = array('warnings' => array(), 'errors' => array());
                   99795:         $this->validatePackageName();
                   99796:         $this->validateVersion();
                   99797:         $this->validateMaintainers();
                   99798:         $this->validateDate();
                   99799:         $this->validateSummary();
                   99800:         $this->validateDescription();
                   99801:         $this->validateLicense();
                   99802:         $this->validateNotes();
                   99803:         if ($this->_packagexml->getPackagexmlVersion() == '1.0') {
                   99804:             $this->validateState();
                   99805:             $this->validateFilelist();
                   99806:         } elseif ($this->_packagexml->getPackagexmlVersion() == '2.0' ||
                   99807:                   $this->_packagexml->getPackagexmlVersion() == '2.1') {
                   99808:             $this->validateTime();
                   99809:             $this->validateStability();
                   99810:             $this->validateDeps();
                   99811:             $this->validateMainFilelist();
                   99812:             $this->validateReleaseFilelist();
                   99813:             //$this->validateGlobalTasks();
                   99814:             $this->validateChangelog();
                   99815:         }
                   99816:         return !((bool) count($this->_failures['errors']));
                   99817:     }
                   99818: 
                   99819:     /**
                   99820:      * @access protected
                   99821:      */
                   99822:     function validatePackageName()
                   99823:     {
                   99824:         if ($this->_state == PEAR_VALIDATE_PACKAGING ||
                   99825:               $this->_state == PEAR_VALIDATE_NORMAL) {
                   99826:             if (($this->_packagexml->getPackagexmlVersion() == '2.0' ||
                   99827:                  $this->_packagexml->getPackagexmlVersion() == '2.1') &&
                   99828:                   $this->_packagexml->getExtends()) {
                   99829:                 $version = $this->_packagexml->getVersion() . '';
                   99830:                 $name = $this->_packagexml->getPackage();
                   99831:                 $test = array_shift($a = explode('.', $version));
                   99832:                 if ($test == '0') {
                   99833:                     return true;
                   99834:                 }
                   99835:                 $vlen = strlen($test);
                   99836:                 $majver = substr($name, strlen($name) - $vlen);
                   99837:                 while ($majver && !is_numeric($majver{0})) {
                   99838:                     $majver = substr($majver, 1);
                   99839:                 }
                   99840:                 if ($majver != $test) {
                   99841:                     $this->_addWarning('package', "package $name extends package " .
                   99842:                         $this->_packagexml->getExtends() . ' and so the name should ' .
                   99843:                         'have a postfix equal to the major version like "' .
                   99844:                         $this->_packagexml->getExtends() . $test . '"');
                   99845:                     return true;
                   99846:                 } elseif (substr($name, 0, strlen($name) - $vlen) !=
                   99847:                             $this->_packagexml->getExtends()) {
                   99848:                     $this->_addWarning('package', "package $name extends package " .
                   99849:                         $this->_packagexml->getExtends() . ' and so the name must ' .
                   99850:                         'be an extension like "' . $this->_packagexml->getExtends() .
                   99851:                         $test . '"');
                   99852:                     return true;
                   99853:                 }
                   99854:             }
                   99855:         }
                   99856:         if (!$this->validPackageName($this->_packagexml->getPackage())) {
                   99857:             $this->_addFailure('name', 'package name "' .
                   99858:                 $this->_packagexml->getPackage() . '" is invalid');
                   99859:             return false;
                   99860:         }
                   99861:     }
                   99862: 
                   99863:     /**
                   99864:      * @access protected
                   99865:      */
                   99866:     function validateVersion()
                   99867:     {
                   99868:         if ($this->_state != PEAR_VALIDATE_PACKAGING) {
                   99869:             if (!$this->validVersion($this->_packagexml->getVersion())) {
                   99870:                 $this->_addFailure('version',
                   99871:                     'Invalid version number "' . $this->_packagexml->getVersion() . '"');
                   99872:             }
                   99873:             return false;
                   99874:         }
                   99875:         $version = $this->_packagexml->getVersion();
                   99876:         $versioncomponents = explode('.', $version);
                   99877:         if (count($versioncomponents) != 3) {
                   99878:             $this->_addWarning('version',
                   99879:                 'A version number should have 3 decimals (x.y.z)');
                   99880:             return true;
                   99881:         }
                   99882:         $name = $this->_packagexml->getPackage();
                   99883:         // version must be based upon state
                   99884:         switch ($this->_packagexml->getState()) {
                   99885:             case 'snapshot' :
                   99886:                 return true;
                   99887:             case 'devel' :
                   99888:                 if ($versioncomponents[0] . 'a' == '0a') {
                   99889:                     return true;
                   99890:                 }
                   99891:                 if ($versioncomponents[0] == 0) {
                   99892:                     $versioncomponents[0] = '0';
                   99893:                     $this->_addWarning('version',
                   99894:                         'version "' . $version . '" should be "' .
                   99895:                         implode('.' ,$versioncomponents) . '"');
                   99896:                 } else {
                   99897:                     $this->_addWarning('version',
                   99898:                         'packages with devel stability must be < version 1.0.0');
                   99899:                 }
                   99900:                 return true;
                   99901:             break;
                   99902:             case 'alpha' :
                   99903:             case 'beta' :
                   99904:                 // check for a package that extends a package,
                   99905:                 // like Foo and Foo2
                   99906:                 if ($this->_state == PEAR_VALIDATE_PACKAGING) {
                   99907:                     if (substr($versioncomponents[2], 1, 2) == 'rc') {
                   99908:                         $this->_addFailure('version', 'Release Candidate versions ' .
                   99909:                             'must have capital RC, not lower-case rc');
                   99910:                         return false;
                   99911:                     }
                   99912:                 }
                   99913:                 if (!$this->_packagexml->getExtends()) {
                   99914:                     if ($versioncomponents[0] == '1') {
                   99915:                         if ($versioncomponents[2]{0} == '0') {
                   99916:                             if ($versioncomponents[2] == '0') {
                   99917:                                 // version 1.*.0000
                   99918:                                 $this->_addWarning('version',
                   99919:                                     'version 1.' . $versioncomponents[1] .
                   99920:                                         '.0 probably should not be alpha or beta');
                   99921:                                 return true;
                   99922:                             } elseif (strlen($versioncomponents[2]) > 1) {
                   99923:                                 // version 1.*.0RC1 or 1.*.0beta24 etc.
                   99924:                                 return true;
                   99925:                             } else {
                   99926:                                 // version 1.*.0
                   99927:                                 $this->_addWarning('version',
                   99928:                                     'version 1.' . $versioncomponents[1] .
                   99929:                                         '.0 probably should not be alpha or beta');
                   99930:                                 return true;
                   99931:                             }
                   99932:                         } else {
                   99933:                             $this->_addWarning('version',
                   99934:                                 'bugfix versions (1.3.x where x > 0) probably should ' .
                   99935:                                 'not be alpha or beta');
                   99936:                             return true;
                   99937:                         }
                   99938:                     } elseif ($versioncomponents[0] != '0') {
                   99939:                         $this->_addWarning('version',
                   99940:                             'major versions greater than 1 are not allowed for packages ' .
                   99941:                             'without an <extends> tag or an identical postfix (foo2 v2.0.0)');
                   99942:                         return true;
                   99943:                     }
                   99944:                     if ($versioncomponents[0] . 'a' == '0a') {
                   99945:                         return true;
                   99946:                     }
                   99947:                     if ($versioncomponents[0] == 0) {
                   99948:                         $versioncomponents[0] = '0';
                   99949:                         $this->_addWarning('version',
                   99950:                             'version "' . $version . '" should be "' .
                   99951:                             implode('.' ,$versioncomponents) . '"');
                   99952:                     }
                   99953:                 } else {
                   99954:                     $vlen = strlen($versioncomponents[0] . '');
                   99955:                     $majver = substr($name, strlen($name) - $vlen);
                   99956:                     while ($majver && !is_numeric($majver{0})) {
                   99957:                         $majver = substr($majver, 1);
                   99958:                     }
                   99959:                     if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) {
                   99960:                         $this->_addWarning('version', 'first version number "' .
                   99961:                             $versioncomponents[0] . '" must match the postfix of ' .
                   99962:                             'package name "' . $name . '" (' .
                   99963:                             $majver . ')');
                   99964:                         return true;
                   99965:                     }
                   99966:                     if ($versioncomponents[0] == $majver) {
                   99967:                         if ($versioncomponents[2]{0} == '0') {
                   99968:                             if ($versioncomponents[2] == '0') {
                   99969:                                 // version 2.*.0000
                   99970:                                 $this->_addWarning('version',
                   99971:                                     "version $majver." . $versioncomponents[1] .
                   99972:                                         '.0 probably should not be alpha or beta');
                   99973:                                 return false;
                   99974:                             } elseif (strlen($versioncomponents[2]) > 1) {
                   99975:                                 // version 2.*.0RC1 or 2.*.0beta24 etc.
                   99976:                                 return true;
                   99977:                             } else {
                   99978:                                 // version 2.*.0
                   99979:                                 $this->_addWarning('version',
                   99980:                                     "version $majver." . $versioncomponents[1] .
                   99981:                                         '.0 cannot be alpha or beta');
                   99982:                                 return true;
                   99983:                             }
                   99984:                         } else {
                   99985:                             $this->_addWarning('version',
                   99986:                                 "bugfix versions ($majver.x.y where y > 0) should " .
                   99987:                                 'not be alpha or beta');
                   99988:                             return true;
                   99989:                         }
                   99990:                     } elseif ($versioncomponents[0] != '0') {
                   99991:                         $this->_addWarning('version',
                   99992:                             "only versions 0.x.y and $majver.x.y are allowed for alpha/beta releases");
                   99993:                         return true;
                   99994:                     }
                   99995:                     if ($versioncomponents[0] . 'a' == '0a') {
                   99996:                         return true;
                   99997:                     }
                   99998:                     if ($versioncomponents[0] == 0) {
                   99999:                         $versioncomponents[0] = '0';
                   100000:                         $this->_addWarning('version',
                   100001:                             'version "' . $version . '" should be "' .
                   100002:                             implode('.' ,$versioncomponents) . '"');
                   100003:                     }
                   100004:                 }
                   100005:                 return true;
                   100006:             break;
                   100007:             case 'stable' :
                   100008:                 if ($versioncomponents[0] == '0') {
                   100009:                     $this->_addWarning('version', 'versions less than 1.0.0 cannot ' .
                   100010:                     'be stable');
                   100011:                     return true;
                   100012:                 }
                   100013:                 if (!is_numeric($versioncomponents[2])) {
                   100014:                     if (preg_match('/\d+(rc|a|alpha|b|beta)\d*/i',
                   100015:                           $versioncomponents[2])) {
                   100016:                         $this->_addWarning('version', 'version "' . $version . '" or any ' .
                   100017:                             'RC/beta/alpha version cannot be stable');
                   100018:                         return true;
                   100019:                     }
                   100020:                 }
                   100021:                 // check for a package that extends a package,
                   100022:                 // like Foo and Foo2
                   100023:                 if ($this->_packagexml->getExtends()) {
                   100024:                     $vlen = strlen($versioncomponents[0] . '');
                   100025:                     $majver = substr($name, strlen($name) - $vlen);
                   100026:                     while ($majver && !is_numeric($majver{0})) {
                   100027:                         $majver = substr($majver, 1);
                   100028:                     }
                   100029:                     if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) {
                   100030:                         $this->_addWarning('version', 'first version number "' .
                   100031:                             $versioncomponents[0] . '" must match the postfix of ' .
                   100032:                             'package name "' . $name . '" (' .
                   100033:                             $majver . ')');
                   100034:                         return true;
                   100035:                     }
                   100036:                 } elseif ($versioncomponents[0] > 1) {
                   100037:                     $this->_addWarning('version', 'major version x in x.y.z may not be greater than ' .
                   100038:                         '1 for any package that does not have an <extends> tag');
                   100039:                 }
                   100040:                 return true;
                   100041:             break;
                   100042:             default :
                   100043:                 return false;
                   100044:             break;
                   100045:         }
                   100046:     }
                   100047: 
                   100048:     /**
                   100049:      * @access protected
                   100050:      */
                   100051:     function validateMaintainers()
                   100052:     {
                   100053:         // maintainers can only be truly validated server-side for most channels
                   100054:         // but allow this customization for those who wish it
                   100055:         return true;
                   100056:     }
                   100057: 
                   100058:     /**
                   100059:      * @access protected
                   100060:      */
                   100061:     function validateDate()
                   100062:     {
                   100063:         if ($this->_state == PEAR_VALIDATE_NORMAL ||
                   100064:               $this->_state == PEAR_VALIDATE_PACKAGING) {
                   100065: 
                   100066:             if (!preg_match('/(\d\d\d\d)\-(\d\d)\-(\d\d)/',
                   100067:                   $this->_packagexml->getDate(), $res) ||
                   100068:                   count($res) < 4
                   100069:                   || !checkdate($res[2], $res[3], $res[1])
                   100070:                 ) {
                   100071:                 $this->_addFailure('date', 'invalid release date "' .
                   100072:                     $this->_packagexml->getDate() . '"');
                   100073:                 return false;
                   100074:             }
                   100075: 
                   100076:             if ($this->_state == PEAR_VALIDATE_PACKAGING &&
                   100077:                   $this->_packagexml->getDate() != date('Y-m-d')) {
                   100078:                 $this->_addWarning('date', 'Release Date "' .
                   100079:                     $this->_packagexml->getDate() . '" is not today');
                   100080:             }
                   100081:         }
                   100082:         return true;
                   100083:     }
                   100084: 
                   100085:     /**
                   100086:      * @access protected
                   100087:      */
                   100088:     function validateTime()
                   100089:     {
                   100090:         if (!$this->_packagexml->getTime()) {
                   100091:             // default of no time value set
                   100092:             return true;
                   100093:         }
                   100094: 
                   100095:         // packager automatically sets time, so only validate if pear validate is called
                   100096:         if ($this->_state = PEAR_VALIDATE_NORMAL) {
                   100097:             if (!preg_match('/\d\d:\d\d:\d\d/',
                   100098:                   $this->_packagexml->getTime())) {
                   100099:                 $this->_addFailure('time', 'invalid release time "' .
                   100100:                     $this->_packagexml->getTime() . '"');
                   100101:                 return false;
                   100102:             }
                   100103: 
                   100104:             $result = preg_match('|\d{2}\:\d{2}\:\d{2}|', $this->_packagexml->getTime(), $matches);
                   100105:             if ($result === false || empty($matches)) {
                   100106:                 $this->_addFailure('time', 'invalid release time "' .
                   100107:                     $this->_packagexml->getTime() . '"');
                   100108:                 return false;
                   100109:             }
                   100110:         }
                   100111: 
                   100112:         return true;
                   100113:     }
                   100114: 
                   100115:     /**
                   100116:      * @access protected
                   100117:      */
                   100118:     function validateState()
                   100119:     {
                   100120:         // this is the closest to "final" php4 can get
                   100121:         if (!PEAR_Validate::validState($this->_packagexml->getState())) {
                   100122:             if (strtolower($this->_packagexml->getState() == 'rc')) {
                   100123:                 $this->_addFailure('state', 'RC is not a state, it is a version ' .
                   100124:                     'postfix, use ' . $this->_packagexml->getVersion() . 'RC1, state beta');
                   100125:             }
                   100126:             $this->_addFailure('state', 'invalid release state "' .
                   100127:                 $this->_packagexml->getState() . '", must be one of: ' .
                   100128:                 implode(', ', PEAR_Validate::getValidStates()));
                   100129:             return false;
                   100130:         }
                   100131:         return true;
                   100132:     }
                   100133: 
                   100134:     /**
                   100135:      * @access protected
                   100136:      */
                   100137:     function validateStability()
                   100138:     {
                   100139:         $ret = true;
                   100140:         $packagestability = $this->_packagexml->getState();
                   100141:         $apistability = $this->_packagexml->getState('api');
                   100142:         if (!PEAR_Validate::validState($packagestability)) {
                   100143:             $this->_addFailure('state', 'invalid release stability "' .
                   100144:                 $this->_packagexml->getState() . '", must be one of: ' .
                   100145:                 implode(', ', PEAR_Validate::getValidStates()));
                   100146:             $ret = false;
                   100147:         }
                   100148:         $apistates = PEAR_Validate::getValidStates();
                   100149:         array_shift($apistates); // snapshot is not allowed
                   100150:         if (!in_array($apistability, $apistates)) {
                   100151:             $this->_addFailure('state', 'invalid API stability "' .
                   100152:                 $this->_packagexml->getState('api') . '", must be one of: ' .
                   100153:                 implode(', ', $apistates));
                   100154:             $ret = false;
                   100155:         }
                   100156:         return $ret;
                   100157:     }
                   100158: 
                   100159:     /**
                   100160:      * @access protected
                   100161:      */
                   100162:     function validateSummary()
                   100163:     {
                   100164:         return true;
                   100165:     }
                   100166: 
                   100167:     /**
                   100168:      * @access protected
                   100169:      */
                   100170:     function validateDescription()
                   100171:     {
                   100172:         return true;
                   100173:     }
                   100174: 
                   100175:     /**
                   100176:      * @access protected
                   100177:      */
                   100178:     function validateLicense()
                   100179:     {
                   100180:         return true;
                   100181:     }
                   100182: 
                   100183:     /**
                   100184:      * @access protected
                   100185:      */
                   100186:     function validateNotes()
                   100187:     {
                   100188:         return true;
                   100189:     }
                   100190: 
                   100191:     /**
                   100192:      * for package.xml 2.0 only - channels can't use package.xml 1.0
                   100193:      * @access protected
                   100194:      */
                   100195:     function validateDependencies()
                   100196:     {
                   100197:         return true;
                   100198:     }
                   100199: 
                   100200:     /**
                   100201:      * for package.xml 1.0 only
                   100202:      * @access private
                   100203:      */
                   100204:     function _validateFilelist()
                   100205:     {
                   100206:         return true; // placeholder for now
                   100207:     }
                   100208: 
                   100209:     /**
                   100210:      * for package.xml 2.0 only
                   100211:      * @access protected
                   100212:      */
                   100213:     function validateMainFilelist()
                   100214:     {
                   100215:         return true; // placeholder for now
                   100216:     }
                   100217: 
                   100218:     /**
                   100219:      * for package.xml 2.0 only
                   100220:      * @access protected
                   100221:      */
                   100222:     function validateReleaseFilelist()
                   100223:     {
                   100224:         return true; // placeholder for now
                   100225:     }
                   100226: 
                   100227:     /**
                   100228:      * @access protected
                   100229:      */
                   100230:     function validateChangelog()
                   100231:     {
                   100232:         return true;
                   100233:     }
                   100234: 
                   100235:     /**
                   100236:      * @access protected
                   100237:      */
                   100238:     function validateFilelist()
                   100239:     {
                   100240:         return true;
                   100241:     }
                   100242: 
                   100243:     /**
                   100244:      * @access protected
                   100245:      */
                   100246:     function validateDeps()
                   100247:     {
                   100248:         return true;
                   100249:     }
                   100250: }<?php
                   100251: /**
                   100252:  * Channel Validator for the pecl.php.net channel
                   100253:  *
                   100254:  * PHP 4 and PHP 5
                   100255:  *
                   100256:  * @category   pear
                   100257:  * @package    PEAR
                   100258:  * @author     Greg Beaver <cellog@php.net>
                   100259:  * @copyright  1997-2006 The PHP Group
                   100260:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    100261:  * @version    CVS: $Id: PECL.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    100262:  * @link       http://pear.php.net/package/PEAR
                   100263:  * @since      File available since Release 1.4.0a5
                   100264:  */
                   100265: /**
                   100266:  * This is the parent class for all validators
                   100267:  */
                   100268: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR/Validate.php';
                   100269: /**
                   100270:  * Channel Validator for the pecl.php.net channel
                   100271:  * @category   pear
                   100272:  * @package    PEAR
                   100273:  * @author     Greg Beaver <cellog@php.net>
                   100274:  * @copyright  1997-2009 The Authors
                   100275:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    100276:  * @version    Release: 1.9.4
1.1       misho    100277:  * @link       http://pear.php.net/package/PEAR
                   100278:  * @since      Class available since Release 1.4.0a5
                   100279:  */
                   100280: class PEAR_Validator_PECL extends PEAR_Validate
                   100281: {
                   100282:     function validateVersion()
                   100283:     {
                   100284:         if ($this->_state == PEAR_VALIDATE_PACKAGING) {
                   100285:             $version = $this->_packagexml->getVersion();
                   100286:             $versioncomponents = explode('.', $version);
                   100287:             $last = array_pop($versioncomponents);
                   100288:             if (substr($last, 1, 2) == 'rc') {
                   100289:                 $this->_addFailure('version', 'Release Candidate versions must have ' .
                   100290:                 'upper-case RC, not lower-case rc');
                   100291:                 return false;
                   100292:             }
                   100293:         }
                   100294:         return true;
                   100295:     }
                   100296: 
                   100297:     function validatePackageName()
                   100298:     {
                   100299:         $ret = parent::validatePackageName();
                   100300:         if ($this->_packagexml->getPackageType() == 'extsrc' ||
                   100301:               $this->_packagexml->getPackageType() == 'zendextsrc') {
                   100302:             if (strtolower($this->_packagexml->getPackage()) !=
                   100303:                   strtolower($this->_packagexml->getProvidesExtension())) {
                   100304:                 $this->_addWarning('providesextension', 'package name "' .
                   100305:                     $this->_packagexml->getPackage() . '" is different from extension name "' .
                   100306:                     $this->_packagexml->getProvidesExtension() . '"');
                   100307:             }
                   100308:         }
                   100309:         return $ret;
                   100310:     }
                   100311: }
                   100312: ?><?php
                   100313: /**
                   100314:  * PEAR_XMLParser
                   100315:  *
                   100316:  * PHP versions 4 and 5
                   100317:  *
                   100318:  * @category   pear
                   100319:  * @package    PEAR
                   100320:  * @author     Greg Beaver <cellog@php.net>
                   100321:  * @author     Stephan Schmidt (original XML_Unserializer code)
                   100322:  * @copyright  1997-2009 The Authors
                   100323:  * @license   http://opensource.org/licenses/bsd-license New BSD License
1.1.1.2 ! misho    100324:  * @version    CVS: $Id: XMLParser.php 313023 2011-07-06 19:17:11Z dufuz $
1.1       misho    100325:  * @link       http://pear.php.net/package/PEAR
                   100326:  * @since      File available since Release 1.4.0a1
                   100327:  */
                   100328: 
                   100329: /**
                   100330:  * Parser for any xml file
                   100331:  * @category  pear
                   100332:  * @package   PEAR
                   100333:  * @author    Greg Beaver <cellog@php.net>
                   100334:  * @author    Stephan Schmidt (original XML_Unserializer code)
                   100335:  * @copyright 1997-2009 The Authors
                   100336:  * @license   http://opensource.org/licenses/bsd-license New BSD License
1.1.1.2 ! misho    100337:  * @version   Release: 1.9.4
1.1       misho    100338:  * @link      http://pear.php.net/package/PEAR
                   100339:  * @since     Class available since Release 1.4.0a1
                   100340:  */
                   100341: class PEAR_XMLParser
                   100342: {
                   100343:     /**
                   100344:      * unserilialized data
                   100345:      * @var string $_serializedData
                   100346:      */
                   100347:     var $_unserializedData = null;
                   100348: 
                   100349:     /**
                   100350:      * name of the root tag
                   100351:      * @var string $_root
                   100352:      */
                   100353:     var $_root = null;
                   100354: 
                   100355:     /**
                   100356:      * stack for all data that is found
                   100357:      * @var array    $_dataStack
                   100358:      */
                   100359:     var $_dataStack = array();
                   100360: 
                   100361:     /**
                   100362:      * stack for all values that are generated
                   100363:      * @var array    $_valStack
                   100364:      */
                   100365:     var $_valStack = array();
                   100366: 
                   100367:     /**
                   100368:      * current tag depth
                   100369:      * @var int    $_depth
                   100370:      */
                   100371:     var $_depth = 0;
                   100372: 
                   100373:     /**
                   100374:      * The XML encoding to use
                   100375:      * @var string $encoding
                   100376:      */
                   100377:     var $encoding = 'ISO-8859-1';
                   100378: 
                   100379:     /**
                   100380:      * @return array
                   100381:      */
                   100382:     function getData()
                   100383:     {
                   100384:         return $this->_unserializedData;
                   100385:     }
                   100386: 
                   100387:     /**
                   100388:      * @param string xml content
                   100389:      * @return true|PEAR_Error
                   100390:      */
                   100391:     function parse($data)
                   100392:     {
                   100393:         if (!extension_loaded('xml')) {
                   100394:             include_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   100395:             return PEAR::raiseError("XML Extension not found", 1);
                   100396:         }
                   100397:         $this->_dataStack =  $this->_valStack = array();
                   100398:         $this->_depth = 0;
                   100399: 
                   100400:         if (
                   100401:             strpos($data, 'encoding="UTF-8"')
                   100402:             || strpos($data, 'encoding="utf-8"')
                   100403:             || strpos($data, "encoding='UTF-8'")
                   100404:             || strpos($data, "encoding='utf-8'")
                   100405:         ) {
                   100406:             $this->encoding = 'UTF-8';
                   100407:         }
                   100408: 
                   100409:         if (version_compare(phpversion(), '5.0.0', 'lt') && $this->encoding == 'UTF-8') {
                   100410:             $data = utf8_decode($data);
                   100411:             $this->encoding = 'ISO-8859-1';
                   100412:         }
                   100413: 
                   100414:         $xp = xml_parser_create($this->encoding);
                   100415:         xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, 0);
                   100416:         xml_set_object($xp, $this);
                   100417:         xml_set_element_handler($xp, 'startHandler', 'endHandler');
                   100418:         xml_set_character_data_handler($xp, 'cdataHandler');
                   100419:         if (!xml_parse($xp, $data)) {
                   100420:             $msg = xml_error_string(xml_get_error_code($xp));
                   100421:             $line = xml_get_current_line_number($xp);
                   100422:             xml_parser_free($xp);
                   100423:             include_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   100424:             return PEAR::raiseError("XML Error: '$msg' on line '$line'", 2);
                   100425:         }
                   100426:         xml_parser_free($xp);
                   100427:         return true;
                   100428:     }
                   100429: 
                   100430:     /**
                   100431:      * Start element handler for XML parser
                   100432:      *
                   100433:      * @access private
                   100434:      * @param  object $parser  XML parser object
                   100435:      * @param  string $element XML element
                   100436:      * @param  array  $attribs attributes of XML tag
                   100437:      * @return void
                   100438:      */
                   100439:     function startHandler($parser, $element, $attribs)
                   100440:     {
                   100441:         $this->_depth++;
                   100442:         $this->_dataStack[$this->_depth] = null;
                   100443: 
                   100444:         $val = array(
                   100445:             'name'         => $element,
                   100446:             'value'        => null,
                   100447:             'type'         => 'string',
                   100448:             'childrenKeys' => array(),
                   100449:             'aggregKeys'   => array()
                   100450:        );
                   100451: 
                   100452:         if (count($attribs) > 0) {
                   100453:             $val['children'] = array();
                   100454:             $val['type'] = 'array';
                   100455:             $val['children']['attribs'] = $attribs;
                   100456:         }
                   100457: 
                   100458:         array_push($this->_valStack, $val);
                   100459:     }
                   100460: 
                   100461:     /**
                   100462:      * post-process data
                   100463:      *
                   100464:      * @param string $data
                   100465:      * @param string $element element name
                   100466:      */
                   100467:     function postProcess($data, $element)
                   100468:     {
                   100469:         return trim($data);
                   100470:     }
                   100471: 
                   100472:     /**
                   100473:      * End element handler for XML parser
                   100474:      *
                   100475:      * @access private
                   100476:      * @param  object XML parser object
                   100477:      * @param  string
                   100478:      * @return void
                   100479:      */
                   100480:     function endHandler($parser, $element)
                   100481:     {
                   100482:         $value = array_pop($this->_valStack);
                   100483:         $data  = $this->postProcess($this->_dataStack[$this->_depth], $element);
                   100484: 
                   100485:         // adjust type of the value
                   100486:         switch (strtolower($value['type'])) {
                   100487:             // unserialize an array
                   100488:             case 'array':
                   100489:                 if ($data !== '') {
                   100490:                     $value['children']['_content'] = $data;
                   100491:                 }
                   100492: 
                   100493:                 $value['value'] = isset($value['children']) ? $value['children'] : array();
                   100494:                 break;
                   100495: 
                   100496:             /*
                   100497:              * unserialize a null value
                   100498:              */
                   100499:             case 'null':
                   100500:                 $data = null;
                   100501:                 break;
                   100502: 
                   100503:             /*
                   100504:              * unserialize any scalar value
                   100505:              */
                   100506:             default:
                   100507:                 settype($data, $value['type']);
                   100508:                 $value['value'] = $data;
                   100509:                 break;
                   100510:         }
                   100511: 
                   100512:         $parent = array_pop($this->_valStack);
                   100513:         if ($parent === null) {
                   100514:             $this->_unserializedData = &$value['value'];
                   100515:             $this->_root = &$value['name'];
                   100516:             return true;
                   100517:         }
                   100518: 
                   100519:         // parent has to be an array
                   100520:         if (!isset($parent['children']) || !is_array($parent['children'])) {
                   100521:             $parent['children'] = array();
                   100522:             if ($parent['type'] != 'array') {
                   100523:                 $parent['type'] = 'array';
                   100524:             }
                   100525:         }
                   100526: 
                   100527:         if (!empty($value['name'])) {
                   100528:             // there already has been a tag with this name
                   100529:             if (in_array($value['name'], $parent['childrenKeys'])) {
                   100530:                 // no aggregate has been created for this tag
                   100531:                 if (!in_array($value['name'], $parent['aggregKeys'])) {
                   100532:                     if (isset($parent['children'][$value['name']])) {
                   100533:                         $parent['children'][$value['name']] = array($parent['children'][$value['name']]);
                   100534:                     } else {
                   100535:                         $parent['children'][$value['name']] = array();
                   100536:                     }
                   100537:                     array_push($parent['aggregKeys'], $value['name']);
                   100538:                 }
                   100539:                 array_push($parent['children'][$value['name']], $value['value']);
                   100540:             } else {
                   100541:                 $parent['children'][$value['name']] = &$value['value'];
                   100542:                 array_push($parent['childrenKeys'], $value['name']);
                   100543:             }
                   100544:         } else {
                   100545:             array_push($parent['children'],$value['value']);
                   100546:         }
                   100547:         array_push($this->_valStack, $parent);
                   100548: 
                   100549:         $this->_depth--;
                   100550:     }
                   100551: 
                   100552:     /**
                   100553:      * Handler for character data
                   100554:      *
                   100555:      * @access private
                   100556:      * @param  object XML parser object
                   100557:      * @param  string CDATA
                   100558:      * @return void
                   100559:      */
                   100560:     function cdataHandler($parser, $cdata)
                   100561:     {
                   100562:         $this->_dataStack[$this->_depth] .= $cdata;
                   100563:     }
                   100564: }<?php
                   100565: /**
                   100566:  * This is only meant for PHP 5 to get rid of certain strict warning
                   100567:  * that doesn't get hidden since it's in the shutdown function
                   100568:  */
                   100569: class PEAR5
                   100570: {
                   100571:     /**
                   100572:     * If you have a class that's mostly/entirely static, and you need static
                   100573:     * properties, you can use this method to simulate them. Eg. in your method(s)
                   100574:     * do this: $myVar = &PEAR5::getStaticProperty('myclass', 'myVar');
                   100575:     * You MUST use a reference, or they will not persist!
                   100576:     *
                   100577:     * @access public
                   100578:     * @param  string $class  The calling classname, to prevent clashes
                   100579:     * @param  string $var    The variable to retrieve.
                   100580:     * @return mixed   A reference to the variable. If not set it will be
                   100581:     *                 auto initialised to NULL.
                   100582:     */
                   100583:     static function &getStaticProperty($class, $var)
                   100584:     {
                   100585:         static $properties;
                   100586:         if (!isset($properties[$class])) {
                   100587:             $properties[$class] = array();
                   100588:         }
                   100589: 
                   100590:         if (!array_key_exists($var, $properties[$class])) {
                   100591:             $properties[$class][$var] = null;
                   100592:         }
                   100593: 
                   100594:         return $properties[$class][$var];
                   100595:     }
                   100596: }<?php
                   100597: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
                   100598: // +-----------------------------------------------------------------------------+
                   100599: // | Copyright (c) 2003 Sérgio Gonçalves Carvalho                                |
                   100600: // +-----------------------------------------------------------------------------+
                   100601: // | This file is part of Structures_Graph.                                      |
                   100602: // |                                                                             |
                   100603: // | Structures_Graph is free software; you can redistribute it and/or modify    |
                   100604: // | it under the terms of the GNU Lesser General Public License as published by |
                   100605: // | the Free Software Foundation; either version 2.1 of the License, or         |
                   100606: // | (at your option) any later version.                                         |
                   100607: // |                                                                             |
                   100608: // | Structures_Graph is distributed in the hope that it will be useful,         |
                   100609: // | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
                   100610: // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
                   100611: // | GNU Lesser General Public License for more details.                         |
                   100612: // |                                                                             |
                   100613: // | You should have received a copy of the GNU Lesser General Public License    |
                   100614: // | along with Structures_Graph; if not, write to the Free Software             |
                   100615: // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
                   100616: // | 02111-1307 USA                                                              |
                   100617: // +-----------------------------------------------------------------------------+
                   100618: // | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com>                  |
                   100619: // +-----------------------------------------------------------------------------+
                   100620: //
                   100621: /**
                   100622:  * The Graph.php file contains the definition of the Structures_Graph class 
                   100623:  *
                   100624:  * @see Structures_Graph
                   100625:  * @package Structures_Graph
                   100626:  */
                   100627: 
                   100628: /* dependencies {{{ */
                   100629: /** PEAR base classes */
                   100630: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   100631: /** Graph Node */
                   100632: require_once 'phar://install-pear-nozlib.phar/' . 'Structures/Graph/Node.php';
                   100633: /* }}} */
                   100634: 
                   100635: define('STRUCTURES_GRAPH_ERROR_GENERIC', 100);
                   100636: 
                   100637: /* class Structures_Graph {{{ */
                   100638: /**
                   100639:  * The Structures_Graph class represents a graph data structure. 
                   100640:  *
                   100641:  * A Graph is a data structure composed by a set of nodes, connected by arcs.
                   100642:  * Graphs may either be directed or undirected. In a directed graph, arcs are 
                   100643:  * directional, and can be traveled only one way. In an undirected graph, arcs
                   100644:  * are bidirectional, and can be traveled both ways.
                   100645:  *
                   100646:  * @author             Sérgio Carvalho <sergio.carvalho@portugalmail.com> 
                   100647:  * @copyright  (c) 2004 by Sérgio Carvalho
                   100648:  * @package Structures_Graph
                   100649:  */
                   100650: /* }}} */
                   100651: class Structures_Graph {
                   100652:     /* fields {{{ */
                   100653:     /**
                   100654:      * @access private
                   100655:      */
                   100656:     var $_nodes = array();
                   100657:     /**
                   100658:      * @access private
                   100659:      */
                   100660:     var $_directed = false;
                   100661:     /* }}} */
                   100662: 
                   100663:     /* Constructor {{{ */
                   100664:     /**
                   100665:     *
                   100666:     * Constructor
                   100667:     *
                   100668:     * @param    boolean    Set to true if the graph is directed. Set to false if it is not directed. (Optional, defaults to true)
                   100669:     * @access  public
                   100670:     */
                   100671:     function Structures_Graph($directed = true) {
                   100672:         $this->_directed = $directed;
                   100673:     }
                   100674:     /* }}} */
                   100675: 
                   100676:     /* isDirected {{{ */
                   100677:     /**
                   100678:     *
                   100679:     * Return true if a graph is directed
                   100680:     *
                   100681:     * @return  boolean  true if the graph is directed
                   100682:     * @access  public
                   100683:     */
                   100684:     function isDirected() {
                   100685:         return (boolean) $this->_directed;
                   100686:     }
                   100687:     /* }}} */
                   100688: 
                   100689:     /* addNode {{{ */
                   100690:     /**
                   100691:     *
                   100692:     * Add a Node to the Graph
                   100693:     *
                   100694:     * @param    Structures_Graph_Node   The node to be added.
                   100695:     * @access  public
                   100696:     */
                   100697:     function addNode(&$newNode) {
                   100698:         // We only add nodes
                   100699:         if (!is_a($newNode, 'Structures_Graph_Node')) return Pear::raiseError('Structures_Graph::addNode received an object that is not a Structures_Graph_Node', STRUCTURES_GRAPH_ERROR_GENERIC);
                   100700:         // Graphs are node *sets*, so duplicates are forbidden. We allow nodes that are exactly equal, but disallow equal references.
                   100701:         foreach($this->_nodes as $key => $node) {
                   100702:             /*
                   100703:              ZE1 equality operators choke on the recursive cycle introduced by the _graph field in the Node object.
                   100704:              So, we'll check references the hard way (change $this->_nodes[$key] and check if the change reflects in 
                   100705:              $node)
                   100706:             */
                   100707:             $savedData = $this->_nodes[$key];
                   100708:             $referenceIsEqualFlag = false;
                   100709:             $this->_nodes[$key] = true;
                   100710:             if ($node === true) {
                   100711:                 $this->_nodes[$key] = false;
                   100712:                 if ($node === false) $referenceIsEqualFlag = true;
                   100713:             }
                   100714:             $this->_nodes[$key] = $savedData;
                   100715:             if ($referenceIsEqualFlag) return Pear::raiseError('Structures_Graph::addNode received an object that is a duplicate for this dataset', STRUCTURES_GRAPH_ERROR_GENERIC);
                   100716:         }
                   100717:         $this->_nodes[] =& $newNode;
                   100718:         $newNode->setGraph($this);
                   100719:     }
                   100720:     /* }}} */
                   100721: 
                   100722:     /* removeNode (unimplemented) {{{ */
                   100723:     /**
                   100724:     *
                   100725:     * Remove a Node from the Graph
                   100726:     *
                   100727:     * @todo     This is unimplemented
                   100728:     * @param    Structures_Graph_Node   The node to be removed from the graph
                   100729:     * @access  public
                   100730:     */
                   100731:     function removeNode(&$node) {
                   100732:     }
                   100733:     /* }}} */
                   100734: 
                   100735:     /* getNodes {{{ */
                   100736:     /**
                   100737:     *
                   100738:     * Return the node set, in no particular order. For ordered node sets, use a Graph Manipulator insted.
                   100739:     *
                   100740:     * @access   public
                   100741:     * @see      Structures_Graph_Manipulator_TopologicalSorter
                   100742:     * @return   array The set of nodes in this graph
                   100743:     */
                   100744:     function &getNodes() {
                   100745:         return $this->_nodes;
                   100746:     }
                   100747:     /* }}} */
                   100748: }
                   100749: ?>
                   100750: <?php
                   100751: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
                   100752: // +-----------------------------------------------------------------------------+
                   100753: // | Copyright (c) 2003 Sérgio Gonçalves Carvalho                                |
                   100754: // +-----------------------------------------------------------------------------+
                   100755: // | This file is part of Structures_Graph.                                      |
                   100756: // |                                                                             |
                   100757: // | Structures_Graph is free software; you can redistribute it and/or modify    |
                   100758: // | it under the terms of the GNU Lesser General Public License as published by |
                   100759: // | the Free Software Foundation; either version 2.1 of the License, or         |
                   100760: // | (at your option) any later version.                                         |
                   100761: // |                                                                             |
                   100762: // | Structures_Graph is distributed in the hope that it will be useful,         |
                   100763: // | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
                   100764: // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
                   100765: // | GNU Lesser General Public License for more details.                         |
                   100766: // |                                                                             |
                   100767: // | You should have received a copy of the GNU Lesser General Public License    |
                   100768: // | along with Structures_Graph; if not, write to the Free Software             |
                   100769: // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
                   100770: // | 02111-1307 USA                                                              |
                   100771: // +-----------------------------------------------------------------------------+
                   100772: // | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com>                  |
                   100773: // +-----------------------------------------------------------------------------+
                   100774: //
                   100775: /**
                   100776:  * This file contains the definition of the Structures_Graph_Manipulator_AcyclicTest graph manipulator.
                   100777:  * 
                   100778:  * @see Structures_Graph_Manipulator_AcyclicTest
                   100779:  * @package Structures_Graph
                   100780:  */
                   100781: 
                   100782: /* dependencies {{{ */
                   100783: /** */
                   100784: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   100785: /** */
                   100786: require_once 'phar://install-pear-nozlib.phar/' . 'Structures/Graph.php';
                   100787: /** */
                   100788: require_once 'phar://install-pear-nozlib.phar/' . 'Structures/Graph/Node.php';
                   100789: /* }}} */
                   100790: 
                   100791: /* class Structures_Graph_Manipulator_AcyclicTest {{{ */
                   100792: /**
                   100793:  * The Structures_Graph_Manipulator_AcyclicTest is a graph manipulator
                   100794:  * which tests whether a graph contains a cycle. 
                   100795:  * 
                   100796:  * The definition of an acyclic graph used in this manipulator is that of a 
                   100797:  * DAG. The graph must be directed, or else it is considered cyclic, even when 
                   100798:  * there are no arcs.
                   100799:  *
                   100800:  * @author             Sérgio Carvalho <sergio.carvalho@portugalmail.com> 
                   100801:  * @copyright  (c) 2004 by Sérgio Carvalho
                   100802:  * @package Structures_Graph
                   100803:  */
                   100804: class Structures_Graph_Manipulator_AcyclicTest {
                   100805:     /* _nonVisitedInDegree {{{ */
                   100806:     /**
                   100807:     *
                   100808:     * This is a variant of Structures_Graph::inDegree which does 
                   100809:     * not count nodes marked as visited.
                   100810:     *
                   100811:     * @access   private
                   100812:     * @return  integer  Number of non-visited nodes that link to this one
                   100813:     */
                   100814:     function _nonVisitedInDegree(&$node) {
                   100815:         $result = 0;
                   100816:         $graphNodes =& $node->_graph->getNodes();
                   100817:         foreach (array_keys($graphNodes) as $key) {
                   100818:             if ((!$graphNodes[$key]->getMetadata('acyclic-test-visited')) && $graphNodes[$key]->connectsTo($node)) $result++;
                   100819:         }
                   100820:         return $result;
                   100821:         
                   100822:     }
                   100823:     /* }}} */
                   100824: 
                   100825:     /* _isAcyclic {{{ */
                   100826:     /**
                   100827:     * @access   private
                   100828:     */
                   100829:     function _isAcyclic(&$graph) {
                   100830:         // Mark every node as not visited
                   100831:         $nodes =& $graph->getNodes();
                   100832:         $nodeKeys = array_keys($nodes);
                   100833:         $refGenerator = array();
                   100834:         foreach($nodeKeys as $key) {
                   100835:             $refGenerator[] = false;
                   100836:             $nodes[$key]->setMetadata('acyclic-test-visited', $refGenerator[sizeof($refGenerator) - 1]);
                   100837:         }
                   100838: 
                   100839:         // Iteratively peel off leaf nodes
                   100840:         do {
                   100841:             // Find out which nodes are leafs (excluding visited nodes)
                   100842:             $leafNodes = array();
                   100843:             foreach($nodeKeys as $key) {
                   100844:                 if ((!$nodes[$key]->getMetadata('acyclic-test-visited')) && Structures_Graph_Manipulator_AcyclicTest::_nonVisitedInDegree($nodes[$key]) == 0) {
                   100845:                     $leafNodes[] =& $nodes[$key];
                   100846:                 }
                   100847:             }
                   100848:             // Mark leafs as visited
                   100849:             for ($i=sizeof($leafNodes) - 1; $i>=0; $i--) {
                   100850:                 $visited =& $leafNodes[$i]->getMetadata('acyclic-test-visited');
                   100851:                 $visited = true;
                   100852:                 $leafNodes[$i]->setMetadata('acyclic-test-visited', $visited);
                   100853:             }
                   100854:         } while (sizeof($leafNodes) > 0);
                   100855: 
                   100856:         // If graph is a DAG, there should be no non-visited nodes. Let's try to prove otherwise
                   100857:         $result = true;
                   100858:         foreach($nodeKeys as $key) if (!$nodes[$key]->getMetadata('acyclic-test-visited')) $result = false;
                   100859:         
                   100860:         // Cleanup visited marks
                   100861:         foreach($nodeKeys as $key) $nodes[$key]->unsetMetadata('acyclic-test-visited');
                   100862: 
                   100863:         return $result;
                   100864:     }
                   100865:     /* }}} */
                   100866: 
                   100867:     /* isAcyclic {{{ */
                   100868:     /**
                   100869:     *
                   100870:     * isAcyclic returns true if a graph contains no cycles, false otherwise.
                   100871:     *
                   100872:     * @return  boolean  true iff graph is acyclic
                   100873:     * @access  public
                   100874:     */
                   100875:     function isAcyclic(&$graph) {
                   100876:         // We only test graphs
                   100877:         if (!is_a($graph, 'Structures_Graph')) return Pear::raiseError('Structures_Graph_Manipulator_AcyclicTest::isAcyclic received an object that is not a Structures_Graph', STRUCTURES_GRAPH_ERROR_GENERIC);
                   100878:         if (!$graph->isDirected()) return false; // Only directed graphs may be acyclic
                   100879: 
                   100880:         return Structures_Graph_Manipulator_AcyclicTest::_isAcyclic($graph);
                   100881:     }
                   100882:     /* }}} */
                   100883: }
                   100884: /* }}} */
                   100885: ?>
                   100886: <?php
                   100887: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
                   100888: // +-----------------------------------------------------------------------------+
                   100889: // | Copyright (c) 2003 Sérgio Gonçalves Carvalho                                |
                   100890: // +-----------------------------------------------------------------------------+
                   100891: // | This file is part of Structures_Graph.                                      |
                   100892: // |                                                                             |
                   100893: // | Structures_Graph is free software; you can redistribute it and/or modify    |
                   100894: // | it under the terms of the GNU Lesser General Public License as published by |
                   100895: // | the Free Software Foundation; either version 2.1 of the License, or         |
                   100896: // | (at your option) any later version.                                         |
                   100897: // |                                                                             |
                   100898: // | Structures_Graph is distributed in the hope that it will be useful,         |
                   100899: // | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
                   100900: // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
                   100901: // | GNU Lesser General Public License for more details.                         |
                   100902: // |                                                                             |
                   100903: // | You should have received a copy of the GNU Lesser General Public License    |
                   100904: // | along with Structures_Graph; if not, write to the Free Software             |
                   100905: // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
                   100906: // | 02111-1307 USA                                                              |
                   100907: // +-----------------------------------------------------------------------------+
                   100908: // | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com>                  |
                   100909: // +-----------------------------------------------------------------------------+
                   100910: //
                   100911: /**
                   100912:  * This file contains the definition of the Structures_Graph_Manipulator_TopologicalSorter class.
                   100913:  * 
                   100914:  * @see Structures_Graph_Manipulator_TopologicalSorter
                   100915:  * @package Structures_Graph
                   100916:  */
                   100917: 
                   100918: /* dependencies {{{ */
                   100919: /** */
                   100920: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   100921: /** */
                   100922: require_once 'phar://install-pear-nozlib.phar/' . 'Structures/Graph.php';
                   100923: /** */
                   100924: require_once 'phar://install-pear-nozlib.phar/' . 'Structures/Graph/Node.php';
                   100925: /** */
                   100926: require_once 'phar://install-pear-nozlib.phar/' . 'Structures/Graph/Manipulator/AcyclicTest.php';
                   100927: /* }}} */
                   100928: 
                   100929: /* class Structures_Graph_Manipulator_TopologicalSorter {{{ */
                   100930: /**
                   100931:  * The Structures_Graph_Manipulator_TopologicalSorter is a manipulator 
                   100932:  * which is able to return the set of nodes in a graph, sorted by topological 
                   100933:  * order.
                   100934:  *
                   100935:  * A graph may only be sorted topologically iff it's a DAG. You can test it
                   100936:  * with the Structures_Graph_Manipulator_AcyclicTest.
                   100937:  * 
                   100938:  * @author             Sérgio Carvalho <sergio.carvalho@portugalmail.com> 
                   100939:  * @copyright  (c) 2004 by Sérgio Carvalho
                   100940:  * @see     Structures_Graph_Manipulator_AcyclicTest
                   100941:  * @package Structures_Graph
                   100942:  */
                   100943: class Structures_Graph_Manipulator_TopologicalSorter {
                   100944:     /* _nonVisitedInDegree {{{ */
                   100945:     /**
                   100946:     *
                   100947:     * This is a variant of Structures_Graph::inDegree which does 
                   100948:     * not count nodes marked as visited.
                   100949:     *
                   100950:     * @access   private
                   100951:     * @return  integer  Number of non-visited nodes that link to this one
                   100952:     */
                   100953:     function _nonVisitedInDegree(&$node) {
                   100954:         $result = 0;
                   100955:         $graphNodes =& $node->_graph->getNodes();
                   100956:         foreach (array_keys($graphNodes) as $key) {
                   100957:             if ((!$graphNodes[$key]->getMetadata('topological-sort-visited')) && $graphNodes[$key]->connectsTo($node)) $result++;
                   100958:         }
                   100959:         return $result;
                   100960:         
                   100961:     }
                   100962:     /* }}} */
                   100963: 
                   100964:     /* _sort {{{ */
                   100965:     /**
                   100966:     * @access   private
                   100967:     */
                   100968:     function _sort(&$graph) {
                   100969:         // Mark every node as not visited
                   100970:         $nodes =& $graph->getNodes();
                   100971:         $nodeKeys = array_keys($nodes);
                   100972:         $refGenerator = array();
                   100973:         foreach($nodeKeys as $key) {
                   100974:             $refGenerator[] = false;
                   100975:             $nodes[$key]->setMetadata('topological-sort-visited', $refGenerator[sizeof($refGenerator) - 1]);
                   100976:         }
                   100977: 
                   100978:         // Iteratively peel off leaf nodes
                   100979:         $topologicalLevel = 0;
                   100980:         do {
                   100981:             // Find out which nodes are leafs (excluding visited nodes)
                   100982:             $leafNodes = array();
                   100983:             foreach($nodeKeys as $key) {
                   100984:                 if ((!$nodes[$key]->getMetadata('topological-sort-visited')) && Structures_Graph_Manipulator_TopologicalSorter::_nonVisitedInDegree($nodes[$key]) == 0) {
                   100985:                     $leafNodes[] =& $nodes[$key];
                   100986:                 }
                   100987:             }
                   100988:             // Mark leafs as visited
                   100989:             $refGenerator[] = $topologicalLevel;
                   100990:             for ($i=sizeof($leafNodes) - 1; $i>=0; $i--) {
                   100991:                 $visited =& $leafNodes[$i]->getMetadata('topological-sort-visited');
                   100992:                 $visited = true;
                   100993:                 $leafNodes[$i]->setMetadata('topological-sort-visited', $visited);
                   100994:                 $leafNodes[$i]->setMetadata('topological-sort-level', $refGenerator[sizeof($refGenerator) - 1]);
                   100995:             }
                   100996:             $topologicalLevel++;
                   100997:         } while (sizeof($leafNodes) > 0);
                   100998: 
                   100999:         // Cleanup visited marks
                   101000:         foreach($nodeKeys as $key) $nodes[$key]->unsetMetadata('topological-sort-visited');
                   101001:     }
                   101002:     /* }}} */
                   101003: 
                   101004:     /* sort {{{ */
                   101005:     /**
                   101006:     *
                   101007:     * sort returns the graph's nodes, sorted by topological order. 
                   101008:     * 
                   101009:     * The result is an array with 
                   101010:     * as many entries as topological levels. Each entry in this array is an array of nodes within
                   101011:     * the given topological level.
                   101012:     *
                   101013:     * @return  array    The graph's nodes, sorted by topological order.
                   101014:     * @access  public
                   101015:     */
                   101016:     function sort(&$graph) {
                   101017:         // We only sort graphs
                   101018:         if (!is_a($graph, 'Structures_Graph')) return Pear::raiseError('Structures_Graph_Manipulator_TopologicalSorter::sort received an object that is not a Structures_Graph', STRUCTURES_GRAPH_ERROR_GENERIC);
                   101019:         if (!Structures_Graph_Manipulator_AcyclicTest::isAcyclic($graph)) return Pear::raiseError('Structures_Graph_Manipulator_TopologicalSorter::sort received an graph that has cycles', STRUCTURES_GRAPH_ERROR_GENERIC);
                   101020: 
                   101021:         Structures_Graph_Manipulator_TopologicalSorter::_sort($graph);
                   101022:         $result = array();
                   101023: 
                   101024:         // Fill out result array
                   101025:         $nodes =& $graph->getNodes();
                   101026:         $nodeKeys = array_keys($nodes);
                   101027:         foreach($nodeKeys as $key) {
                   101028:             if (!array_key_exists($nodes[$key]->getMetadata('topological-sort-level'), $result)) $result[$nodes[$key]->getMetadata('topological-sort-level')] = array();
                   101029:             $result[$nodes[$key]->getMetadata('topological-sort-level')][] =& $nodes[$key];
                   101030:             $nodes[$key]->unsetMetadata('topological-sort-level');
                   101031:         }
                   101032: 
                   101033:         return $result;
                   101034:     }
                   101035:     /* }}} */
                   101036: }
                   101037: /* }}} */
                   101038: ?>
                   101039: <?php
                   101040: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
                   101041: // +-----------------------------------------------------------------------------+
                   101042: // | Copyright (c) 2003 Sérgio Gonçalves Carvalho                                |
                   101043: // +-----------------------------------------------------------------------------+
                   101044: // | This file is part of Structures_Graph.                                      |
                   101045: // |                                                                             |
                   101046: // | Structures_Graph is free software; you can redistribute it and/or modify    |
                   101047: // | it under the terms of the GNU Lesser General Public License as published by |
                   101048: // | the Free Software Foundation; either version 2.1 of the License, or         |
                   101049: // | (at your option) any later version.                                         |
                   101050: // |                                                                             |
                   101051: // | Structures_Graph is distributed in the hope that it will be useful,         |
                   101052: // | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
                   101053: // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
                   101054: // | GNU Lesser General Public License for more details.                         |
                   101055: // |                                                                             |
                   101056: // | You should have received a copy of the GNU Lesser General Public License    |
                   101057: // | along with Structures_Graph; if not, write to the Free Software             |
                   101058: // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
                   101059: // | 02111-1307 USA                                                              |
                   101060: // +-----------------------------------------------------------------------------+
                   101061: // | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com>                  |
                   101062: // +-----------------------------------------------------------------------------+
                   101063: //
                   101064: /**
                   101065:  * This file contains the definition of the Structures_Graph_Node class
                   101066:  * 
                   101067:  * @see Structures_Graph_Node
                   101068:  * @package Structures_Graph
                   101069:  */
                   101070: 
                   101071: /* dependencies {{{ */
                   101072: /** */
                   101073: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   101074: /** */
                   101075: require_once 'phar://install-pear-nozlib.phar/' . 'Structures/Graph.php';
                   101076: /* }}} */
                   101077: 
                   101078: /* class Structures_Graph_Node {{{ */
                   101079: /**
                   101080:  * The Structures_Graph_Node class represents a Node that can be member of a 
                   101081:  * graph node set.
                   101082:  *
                   101083:  * A graph node can contain data. Under this API, the node contains default data, 
                   101084:  * and key index data. It behaves, thus, both as a regular data node, and as a 
                   101085:  * dictionary (or associative array) node.
                   101086:  * 
                   101087:  * Regular data is accessed via getData and setData. Key indexed data is accessed
                   101088:  * via getMetadata and setMetadata.
                   101089:  *
                   101090:  * @author             Sérgio Carvalho <sergio.carvalho@portugalmail.com> 
                   101091:  * @copyright  (c) 2004 by Sérgio Carvalho
                   101092:  * @package Structures_Graph
                   101093:  */
                   101094: /* }}} */
                   101095: class Structures_Graph_Node {
                   101096:     /* fields {{{ */
                   101097:     /** 
                   101098:      * @access private 
                   101099:      */
                   101100:     var $_data = null;
                   101101:     /** @access private */
                   101102:     var $_metadata = array();
                   101103:     /** @access private */
                   101104:     var $_arcs = array();
                   101105:     /** @access private */
                   101106:     var $_graph = null;
                   101107:     /* }}} */
                   101108: 
                   101109:     /* Constructor {{{ */
                   101110:     /**
                   101111:     *
                   101112:     * Constructor
                   101113:     *
                   101114:     * @access  public
                   101115:     */
                   101116:     function Structures_Graph_Node() {
                   101117:     }
                   101118:     /* }}} */
                   101119: 
                   101120:     /* getGraph {{{ */
                   101121:     /**
                   101122:     *
                   101123:     * Node graph getter
                   101124:     *
                   101125:     * @return  Structures_Graph        Graph where node is stored
                   101126:     * @access  public
                   101127:     */
                   101128:     function &getGraph() {
                   101129:         return $this->_graph;
                   101130:     }
                   101131:     /* }}} */
                   101132: 
                   101133:     /* setGraph {{{ */
                   101134:     /**
                   101135:     *
                   101136:     * Node graph setter. This method should not be called directly. Use Graph::addNode instead.
                   101137:     *
                   101138:     * @param    Structures_Graph   Set the graph for this node. 
                   101139:     * @see      Structures_Graph::addNode()
                   101140:     * @access  public
                   101141:     */
                   101142:     function setGraph(&$graph) {
                   101143:         $this->_graph =& $graph;
                   101144:     }
                   101145:     /* }}} */
                   101146: 
                   101147:     /* getData {{{ */
                   101148:     /**
                   101149:     *
                   101150:     * Node data getter.
                   101151:     * 
                   101152:     * Each graph node can contain a reference to one variable. This is the getter for that reference.
                   101153:     *
                   101154:     * @return  mixed   Data stored in node
                   101155:     * @access  public
                   101156:     */
                   101157:     function &getData() {
                   101158:         return $this->_data;
                   101159:     }
                   101160:     /* }}} */
                   101161: 
                   101162:     /* setData {{{ */
                   101163:     /**
                   101164:     *
                   101165:     * Node data setter
                   101166:     *
                   101167:     * Each graph node can contain a reference to one variable. This is the setter for that reference.
                   101168:     *
                   101169:     * @return  mixed   Data to store in node
                   101170:     * @access  public
                   101171:     */
                   101172:     function setData($data) {
                   101173:         $this->_data =& $data;
                   101174:     }
                   101175:     /* }}} */
                   101176: 
                   101177:     /* metadataKeyExists {{{ */
                   101178:     /**
                   101179:     *
                   101180:     * Test for existence of metadata under a given key.
                   101181:     *
                   101182:     * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an 
                   101183:     * associative array or in a dictionary. This method tests whether a given metadata key exists for this node.
                   101184:     *
                   101185:     * @param    string    Key to test
                   101186:     * @return  boolean  
                   101187:     * @access  public
                   101188:     */
                   101189:     function metadataKeyExists($key) {
                   101190:         return array_key_exists($key, $this->_metadata);
                   101191:     }
                   101192:     /* }}} */
                   101193: 
                   101194:     /* getMetadata {{{ */
                   101195:     /**
                   101196:     *
                   101197:     * Node metadata getter
                   101198:     *
                   101199:     * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an 
                   101200:     * associative array or in a dictionary. This method gets the data under the given key. If the key does
                   101201:     * not exist, an error will be thrown, so testing using metadataKeyExists might be needed.
                   101202:     *
                   101203:     * @param    string  Key
                   101204:     * @param    boolean nullIfNonexistent (defaults to false).
                   101205:     * @return  mixed   Metadata Data stored in node under given key
                   101206:     * @see      metadataKeyExists
                   101207:     * @access  public
                   101208:     */
                   101209:     function &getMetadata($key, $nullIfNonexistent = false) {
                   101210:         if (array_key_exists($key, $this->_metadata)) {
                   101211:             return $this->_metadata[$key];
                   101212:         } else {
                   101213:             if ($nullIfNonexistent) {
                   101214:                 $a = null;
                   101215:                 return $a;
                   101216:             } else {
                   101217:                 $a = Pear::raiseError('Structures_Graph_Node::getMetadata: Requested key does not exist', STRUCTURES_GRAPH_ERROR_GENERIC);
                   101218:                 return $a;
                   101219:             }
                   101220:         }
                   101221:     }
                   101222:     /* }}} */
                   101223: 
                   101224:     /* unsetMetadata {{{ */
                   101225:     /**
                   101226:     *
                   101227:     * Delete metadata by key
                   101228:     *
                   101229:     * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an 
                   101230:     * associative array or in a dictionary. This method removes any data that might be stored under the provided key.
                   101231:     * If the key does not exist, no error is thrown, so it is safe using this method without testing for key existence.
                   101232:     *
                   101233:     * @param    string  Key
                   101234:     * @access  public
                   101235:     */
                   101236:     function unsetMetadata($key) {
                   101237:         if (array_key_exists($key, $this->_metadata)) unset($this->_metadata[$key]);
                   101238:     }
                   101239:     /* }}} */
                   101240: 
                   101241:     /* setMetadata {{{ */
                   101242:     /**
                   101243:     *
                   101244:     * Node metadata setter
                   101245:     *
                   101246:     * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an 
                   101247:     * associative array or in a dictionary. This method stores data under the given key. If the key already exists,
                   101248:     * previously stored data is discarded.
                   101249:     *
                   101250:     * @param    string  Key
                   101251:     * @param    mixed   Data 
                   101252:     * @access  public
                   101253:     */
                   101254:     function setMetadata($key, $data) {
                   101255:         $this->_metadata[$key] =& $data;
                   101256:     }
                   101257:     /* }}} */
                   101258: 
                   101259:     /* _connectTo {{{ */
                   101260:     /** @access private */
                   101261:     function _connectTo(&$destinationNode) {
                   101262:         $this->_arcs[] =& $destinationNode;
                   101263:     }
                   101264:     /* }}} */
                   101265: 
                   101266:     /* connectTo {{{ */
                   101267:     /**
                   101268:     *
                   101269:     * Connect this node to another one.
                   101270:     * 
                   101271:     * If the graph is not directed, the reverse arc, connecting $destinationNode to $this is also created.
                   101272:     *
                   101273:     * @param    Structures_Graph_Node Node to connect to
                   101274:     * @access  public
                   101275:     */
                   101276:     function connectTo(&$destinationNode) {
                   101277:         // We only connect to nodes
                   101278:         if (!is_a($destinationNode, 'Structures_Graph_Node')) return Pear::raiseError('Structures_Graph_Node::connectTo received an object that is not a Structures_Graph_Node', STRUCTURES_GRAPH_ERROR_GENERIC);
                   101279:         // Nodes must already be in graphs to be connected
                   101280:         if ($this->_graph == null) return Pear::raiseError('Structures_Graph_Node::connectTo Tried to connect a node that is not in a graph', STRUCTURES_GRAPH_ERROR_GENERIC);
                   101281:         if ($destinationNode->getGraph() == null) return Pear::raiseError('Structures_Graph_Node::connectTo Tried to connect to a node that is not in a graph', STRUCTURES_GRAPH_ERROR_GENERIC);
                   101282:         // Connect here
                   101283:         $this->_connectTo($destinationNode);
                   101284:         // If graph is undirected, connect back
                   101285:         if (!$this->_graph->isDirected()) {
                   101286:             $destinationNode->_connectTo($this);
                   101287:         }
                   101288:     }
                   101289:     /* }}} */
                   101290: 
                   101291:     /* getNeighbours {{{ */
                   101292:     /**
                   101293:     *
                   101294:     * Return nodes connected to this one.
                   101295:     * 
                   101296:     * @return   array   Array of nodes
                   101297:     * @access  public
                   101298:     */
                   101299:     function getNeighbours() {
                   101300:         return $this->_arcs;
                   101301:     }
                   101302:     /* }}} */
                   101303: 
                   101304:     /* connectsTo {{{ */
                   101305:     /**
                   101306:     *
                   101307:     * Test wether this node has an arc to the target node
                   101308:     *
                   101309:     * @return  boolean   True if the two nodes are connected
                   101310:     * @access  public
                   101311:     */
                   101312:     function connectsTo(&$target) {
                   101313:         if (version_compare(PHP_VERSION, '5.0.0') >= 0) {
                   101314:             return in_array($target, $this->getNeighbours(), true);
                   101315:         }
                   101316: 
                   101317:         $copy = $target;
                   101318:         $arcKeys = array_keys($this->_arcs);
                   101319:         foreach($arcKeys as $key) {
                   101320:             /* ZE1 chokes on this expression:
                   101321:                 if ($target === $arc) return true;
                   101322:               so, we'll use more convoluted stuff
                   101323:             */
                   101324:             $arc =& $this->_arcs[$key];
                   101325:             $target = true;
                   101326:             if ($arc === true) {
                   101327:                 $target = false;
                   101328:                 if ($arc === false) {
                   101329:                     $target = $copy;
                   101330:                     return true;
                   101331:                 }
                   101332:             }
                   101333:         }
                   101334:         $target = $copy;
                   101335:         return false;
                   101336:     }
                   101337:     /* }}} */
                   101338: 
                   101339:     /* inDegree {{{ */
                   101340:     /**
                   101341:     *
                   101342:     * Calculate the in degree of the node.
                   101343:     * 
                   101344:     * The indegree for a node is the number of arcs entering the node. For non directed graphs, 
                   101345:     * the indegree is equal to the outdegree.
                   101346:     *
                   101347:     * @return  integer  In degree of the node
                   101348:     * @access  public
                   101349:     */
                   101350:     function inDegree() {
                   101351:         if ($this->_graph == null) return 0;
                   101352:         if (!$this->_graph->isDirected()) return $this->outDegree();
                   101353:         $result = 0;
                   101354:         $graphNodes =& $this->_graph->getNodes();
                   101355:         foreach (array_keys($graphNodes) as $key) {
                   101356:             if ($graphNodes[$key]->connectsTo($this)) $result++;
                   101357:         }
                   101358:         return $result;
                   101359:         
                   101360:     }
                   101361:     /* }}} */
                   101362: 
                   101363:     /* outDegree {{{ */
                   101364:     /**
                   101365:     *
                   101366:     * Calculate the out degree of the node.
                   101367:     *
                   101368:     * The outdegree for a node is the number of arcs exiting the node. For non directed graphs,
                   101369:     * the outdegree is always equal to the indegree.
                   101370:     * 
                   101371:     * @return  integer  Out degree of the node
                   101372:     * @access  public
                   101373:     */
                   101374:     function outDegree() {
                   101375:         if ($this->_graph == null) return 0;
                   101376:         return sizeof($this->_arcs);
                   101377:     }
                   101378:     /* }}} */
                   101379: }
                   101380: ?>
                   101381: package.xml0000644000076600000240000001543011461440276012461 0ustar  bbieberstaff<?xml version="1.0" encoding="UTF-8"?>
                   101382: <package packagerversion="1.9.1" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0     http://pear.php.net/dtd/tasks-1.0.xsd     http://pear.php.net/dtd/package-2.0     http://pear.php.net/dtd/package-2.0.xsd">
                   101383:  <name>Structures_Graph</name>
                   101384:  <channel>pear.php.net</channel>
                   101385:  <summary>Graph datastructure manipulation library</summary>
                   101386:  <description>Structures_Graph is a package for creating and manipulating graph datastructures. It allows building of directed
                   101387: and undirected graphs, with data and metadata stored in nodes. The library provides functions for graph traversing
                   101388: as well as for characteristic extraction from the graph topology.</description>
                   101389:  <lead>
                   101390:   <name>Sérgio Carvalho</name>
                   101391:   <user>sergiosgc</user>
                   101392:   <email>sergio.carvalho@portugalmail.com</email>
                   101393:   <active>yes</active>
                   101394:  </lead>
                   101395:  <helper>
                   101396:   <name>Brett Bieber</name>
                   101397:   <user>saltybeagle</user>
                   101398:   <email>brett.bieber@gmail.com</email>
                   101399:   <active>yes</active>
                   101400:  </helper>
                   101401:  <date>2010-10-25</date>
                   101402:  <time>21:45:17</time>
                   101403:  <version>
                   101404:   <release>1.0.4</release>
                   101405:   <api>1.0.3</api>
                   101406:  </version>
                   101407:  <stability>
                   101408:   <release>stable</release>
                   101409:   <api>stable</api>
                   101410:  </stability>
                   101411:  <license>LGPL License</license>
                   101412:  <notes>
                   101413: Bugfix Release:
                   101414: * Bug #17108 BasicGraph::test_directed_degree fails on PHP 5 [clockwerx]
                   101415:  </notes>
                   101416:  <contents>
                   101417:   <dir baseinstalldir="/" name="/">
                   101418:    <file baseinstalldir="/" md5sum="e43ca110d02f287cdaac6357ba539fff" name="docs/html/media/banner.css" role="doc" />
                   101419:    <file baseinstalldir="/" md5sum="296dd865297508569a6e72fcfd20fa81" name="docs/html/media/stylesheet.css" role="doc" />
                   101420:    <file baseinstalldir="/" md5sum="678ccf89e31bc7337803afd6b7c58827" name="docs/html/Structures_Graph/Structures_Graph.html" role="doc" />
                   101421:    <file baseinstalldir="/" md5sum="686b7bd7108cf5ce9b1ae5f17cea79f4" name="docs/html/Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html" role="doc" />
                   101422:    <file baseinstalldir="/" md5sum="08b05a395eca4b0ca49a956fadf83da6" name="docs/html/Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html" role="doc" />
                   101423:    <file baseinstalldir="/" md5sum="3fa8a9fae581fc31fd1dfbb14f475f92" name="docs/html/Structures_Graph/Structures_Graph_Node.html" role="doc" />
                   101424:    <file baseinstalldir="/" md5sum="fd9b59eb75a39d3a25a175660dfb12be" name="docs/html/Structures_Graph/tutorial_Structures_Graph.pkg.html" role="doc" />
                   101425:    <file baseinstalldir="/" md5sum="9cfeca2ff35a44b4bb921a9a818d8fa6" name="docs/html/Structures_Graph/_Structures_Graph_Manipulator_AcyclicTest_php.html" role="doc" />
                   101426:    <file baseinstalldir="/" md5sum="4faffdcc81cbc92520104e90a651a971" name="docs/html/Structures_Graph/_Structures_Graph_Manipulator_TopologicalSorter_php.html" role="doc" />
                   101427:    <file baseinstalldir="/" md5sum="0337573b69355c8b7ad36cd8f40ce859" name="docs/html/Structures_Graph/_Structures_Graph_Node_php.html" role="doc" />
                   101428:    <file baseinstalldir="/" md5sum="7c1f852d7aa1a2fcada473723c8a46c2" name="docs/html/Structures_Graph/_Structures_Graph_php.html" role="doc" />
                   101429:    <file baseinstalldir="/" md5sum="238f8a9d335e49ef87a0a276bcfc7231" name="docs/html/classtrees_Structures_Graph.html" role="doc" />
                   101430:    <file baseinstalldir="/" md5sum="e302b63d3b18fa1c6e13f76816564d39" name="docs/html/elementindex.html" role="doc" />
                   101431:    <file baseinstalldir="/" md5sum="c97ebad7c5635abbbbf35a23e868649e" name="docs/html/elementindex_Structures_Graph.html" role="doc" />
                   101432:    <file baseinstalldir="/" md5sum="6f58a7616dd96fb8cc0cbf928f66dd33" name="docs/html/errors.html" role="doc" />
                   101433:    <file baseinstalldir="/" md5sum="cf5397f529a0d9a701fac13ac6aaaa69" name="docs/html/index.html" role="doc" />
                   101434:    <file baseinstalldir="/" md5sum="b206403136db1de58901f825ad9f9cb0" name="docs/html/li_Structures_Graph.html" role="doc" />
                   101435:    <file baseinstalldir="/" md5sum="a88b0fcc2f97dd2069f671ef1dc92b40" name="docs/html/packages.html" role="doc" />
                   101436:    <file baseinstalldir="/" md5sum="6fdd16675f2181b53a4d2dc2c419752b" name="docs/html/todolist.html" role="doc" />
                   101437:    <file baseinstalldir="/" md5sum="628eb6532a8047bf5962fe24c1c245df" name="docs/tutorials/Structures_Graph/Structures_Graph.pkg" role="doc" />
                   101438:    <file baseinstalldir="/" md5sum="ce2da39dbb75e21074eb5e96231a3379" name="docs/generate.sh" role="doc" />
                   101439:    <file baseinstalldir="/" md5sum="f0aff5a1efd188d63b4b8b9e9e840b97" name="Structures/Graph/Manipulator/AcyclicTest.php" role="php" />
                   101440:    <file baseinstalldir="/" md5sum="0492e677436d29228df93dca23629e06" name="Structures/Graph/Manipulator/TopologicalSorter.php" role="php" />
                   101441:    <file baseinstalldir="/" md5sum="254ebaba7537ad0f36e63eb8b975cc51" name="Structures/Graph/Node.php" role="php" />
                   101442:    <file baseinstalldir="/" md5sum="4f25a6275af156f6f8e7b4309cb9f40d" name="Structures/Graph.php" role="php" />
                   101443:    <file baseinstalldir="/" md5sum="5791baa61d5d36442be58ea5cd9d4bd0" name="tests/testCase/BasicGraph.php" role="test" />
                   101444:    <file baseinstalldir="/" md5sum="4fed49ef60db01eed800105aae4f2c8b" name="tests/AllTests.php" role="test" />
                   101445:    <file baseinstalldir="/" md5sum="7fbc338309ac38fefcd64b04bb903e34" name="LICENSE" role="data" />
                   101446:   </dir>
                   101447:  </contents>
                   101448:  <compatible>
                   101449:   <name>PEAR</name>
                   101450:   <channel>pear.php.net</channel>
                   101451:   <min>1.5.0RC3</min>
                   101452:   <max>1.9.1</max>
                   101453:  </compatible>
                   101454:  <dependencies>
                   101455:   <required>
                   101456:    <php>
                   101457:     <min>4.2.0</min>
                   101458:    </php>
                   101459:    <pearinstaller>
                   101460:     <min>1.4.3</min>
                   101461:    </pearinstaller>
                   101462:   </required>
                   101463:  </dependencies>
                   101464:  <phprelease />
                   101465:  <changelog>
                   101466:   <release>
                   101467:    <version>
                   101468:     <release>1.0.2</release>
                   101469:     <api>1.0.0</api>
                   101470:    </version>
                   101471:    <stability>
                   101472:     <release>stable</release>
                   101473:     <api>stable</api>
                   101474:    </stability>
                   101475:    <date>2007-01-07</date>
                   101476:    <license uri="http://opensource.org/licenses/lgpl-license.php">LGPL</license>
                   101477:    <notes>
                   101478: - Bug #9682 only variables can be returned by reference
                   101479: - fix Bug #9661 notice in Structures_Graph_Manipulator_Topological::sort()
                   101480:    </notes>
                   101481:   </release>
                   101482:   <release>
                   101483:    <version>
                   101484:     <release>1.0.3</release>
                   101485:     <api>1.0.3</api>
                   101486:    </version>
                   101487:    <stability>
                   101488:     <release>stable</release>
                   101489:     <api>stable</api>
                   101490:    </stability>
                   101491:    <date>2009-10-11</date>
                   101492:    <license>LGPL License</license>
                   101493:    <notes>
                   101494: Bugfix Release:
                   101495: Version 1.0.3 is functionally equivalent to 1.0.2 but with an updated package.xml file.
                   101496: * Correct invalid md5 sum preventing installation with pyrus [saltybeagle]
                   101497: * Add compatible tag for PEAR 1.5.0RC3-1.9.0 [saltybeagle]
                   101498: * Update package.xml
                   101499:    </notes>
                   101500:   </release>
                   101501:   <release>
                   101502:    <version>
                   101503:     <release>1.0.4</release>
                   101504:     <api>1.0.3</api>
                   101505:    </version>
                   101506:    <stability>
                   101507:     <release>stable</release>
                   101508:     <api>stable</api>
                   101509:    </stability>
                   101510:    <date>2010-10-25</date>
                   101511:    <license>LGPL License</license>
                   101512:    <notes>
                   101513: Bugfix Release:
                   101514: * Bug #17108 BasicGraph::test_directed_degree fails on PHP 5 [clockwerx]
                   101515:    </notes>
                   101516:   </release>
                   101517:  </changelog>
                   101518: </package>
                   101519: Structures_Graph-1.0.4/docs/html/media/banner.css0000644000076600000240000000061111461440275021232 0ustar  bbieberstaffbody 
                   101520: { 
                   101521:        background-color: #CCCCFF; 
                   101522:        margin: 0px; 
                   101523:        padding: 0px;
                   101524: }
                   101525: 
                   101526: /* Banner (top bar) classes */
                   101527: 
                   101528: .banner {  }
                   101529: 
                   101530: .banner-menu 
                   101531: { 
                   101532:        clear: both;
                   101533:        padding: .5em;
                   101534:        border-top: 2px solid #6666AA;  
                   101535: }
                   101536: 
                   101537: .banner-title 
                   101538: { 
                   101539:        text-align: right; 
                   101540:        font-size: 20pt; 
                   101541:        font-weight: bold; 
                   101542:        margin: .2em;
                   101543: }
                   101544: 
                   101545: .package-selector 
                   101546: { 
                   101547:        background-color: #AAAADD; 
                   101548:        border: 1px solid black; 
                   101549:        color: yellow;
                   101550: }
                   101551: Structures_Graph-1.0.4/docs/html/media/stylesheet.css0000644000076600000240000001160411461440275022162 0ustar  bbieberstaffa { color: #336699; text-decoration: none; }
                   101552: a:hover { color: #6699CC; text-decoration: underline; }
                   101553: a:active { color: #6699CC; text-decoration: underline; }
                   101554: 
                   101555: body { background : #FFFFFF; }
                   101556: body, table { font-family: Georgia, Times New Roman, Times, serif; font-size: 10pt }
                   101557: p, li { line-height: 140% }
                   101558: a img { border: 0px; }
                   101559: dd { margin-left: 0px; padding-left: 1em; }
                   101560: 
                   101561: /* Page layout/boxes */
                   101562: 
                   101563: .info-box {}
                   101564: .info-box-title { margin: 1em 0em 0em 0em; padding: .25em; font-weight: normal; font-size: 14pt; border: 2px solid #999999; background-color: #CCCCFF }
                   101565: .info-box-body { border: 1px solid #999999; padding: .5em; }
                   101566: .nav-bar { font-size: 8pt; white-space: nowrap; text-align: right; padding: .2em; margin: 0em 0em 1em 0em; }
                   101567: 
                   101568: .oddrow { background-color: #F8F8F8; border: 1px solid #AAAAAA; padding: .5em; margin-bottom: 1em}
                   101569: .evenrow { border: 1px solid #AAAAAA; padding: .5em; margin-bottom: 1em}
                   101570: 
                   101571: .page-body { max-width: 800px; margin: auto; }
                   101572: .tree dl { margin: 0px }
                   101573: 
                   101574: /* Index formatting classes */
                   101575: 
                   101576: .index-item-body { margin-top: .5em; margin-bottom: .5em}
                   101577: .index-item-description { margin-top: .25em }
                   101578: .index-item-details { font-weight: normal; font-style: italic; font-size: 8pt }
                   101579: .index-letter-section { background-color: #EEEEEE; border: 1px dotted #999999; padding: .5em; margin-bottom: 1em}
                   101580: .index-letter-title { font-size: 12pt; font-weight: bold }
                   101581: .index-letter-menu { text-align: center; margin: 1em }
                   101582: .index-letter { font-size: 12pt }
                   101583: 
                   101584: /* Docbook classes */
                   101585: 
                   101586: .description {}
                   101587: .short-description { font-weight: bold; color: #666666; }
                   101588: .tags {        padding-left: 0em; margin-left: 3em; color: #666666; list-style-type: square; }
                   101589: .parameters {  padding-left: 0em; margin-left: 3em; font-style: italic; list-style-type: square; }
                   101590: .redefinitions { font-size: 8pt; padding-left: 0em; margin-left: 2em; }
                   101591: .package {  }
                   101592: .package-title { font-weight: bold; font-size: 14pt; border-bottom: 1px solid black }
                   101593: .package-details { font-size: 85%; }
                   101594: .sub-package { font-weight: bold; font-size: 120% }
                   101595: .tutorial { border-width: thin; border-color: #0066ff }
                   101596: .tutorial-nav-box { width: 100%; border: 1px solid #999999; background-color: #F8F8F8; }
                   101597: .nav-button-disabled { color: #999999; }
                   101598: .nav-button:active, 
                   101599: .nav-button:focus, 
                   101600: .nav-button:hover { background-color: #DDDDDD; outline: 1px solid #999999; text-decoration: none }
                   101601: .folder-title { font-style: italic }
                   101602: 
                   101603: /* Generic formatting */
                   101604: 
                   101605: .field { font-weight: bold; }
                   101606: .detail { font-size: 8pt; }
                   101607: .notes { font-style: italic; font-size: 8pt; }
                   101608: .separator { background-color: #999999; height: 2px; }
                   101609: .warning {  color: #FF6600; }
                   101610: .disabled { font-style: italic; color: #999999; }
                   101611: 
                   101612: /* Code elements */
                   101613: 
                   101614: .line-number {  }
                   101615: 
                   101616: .class-table { width: 100%; }
                   101617: .class-table-header { border-bottom: 1px dotted #666666; text-align: left}
                   101618: .class-name { color: #000000; font-weight: bold; }
                   101619: 
                   101620: .method-summary { padding-left: 1em; font-size: 8pt }
                   101621: .method-header { }
                   101622: .method-definition { margin-bottom: .3em }
                   101623: .method-title { font-weight: bold; }
                   101624: .method-name { font-weight: bold; }
                   101625: .method-signature { font-size: 85%; color: #666666; margin: .5em 0em }
                   101626: .method-result { font-style: italic; }
                   101627: 
                   101628: .var-summary { padding-left: 1em; font-size: 8pt; }
                   101629: .var-header { }
                   101630: .var-title { margin-bottom: .3em }
                   101631: .var-type { font-style: italic; }
                   101632: .var-name { font-weight: bold; }
                   101633: .var-default {}
                   101634: .var-description { font-weight: normal; color: #000000; }
                   101635: 
                   101636: .include-title {  }
                   101637: .include-type { font-style: italic; }
                   101638: .include-name { font-weight: bold; }
                   101639: 
                   101640: .const-title {  }
                   101641: .const-name { font-weight: bold; }
                   101642: 
                   101643: /* Syntax highlighting */
                   101644: 
                   101645: .src-code {  border: 1px solid #336699; padding: 1em; background-color: #EEEEEE; }
                   101646: 
                   101647: .src-comm { color: green; }
                   101648: .src-id {  }
                   101649: .src-inc { color: #0000FF; }
                   101650: .src-key { color: #0000FF; }
                   101651: .src-num { color: #CC0000; }
                   101652: .src-str { color: #66cccc; }
                   101653: .src-sym { font-weight: bold; }
                   101654: .src-var { }
                   101655: 
                   101656: .src-php { font-weight: bold; }
                   101657: 
                   101658: .src-doc { color: #009999 }
                   101659: .src-doc-close-template { color: #0000FF }
                   101660: .src-doc-coretag { color: #0099FF; font-weight: bold }
                   101661: .src-doc-inlinetag { color: #0099FF }
                   101662: .src-doc-internal { color: #6699cc }
                   101663: .src-doc-tag { color: #0080CC }
                   101664: .src-doc-template { color: #0000FF }
                   101665: .src-doc-type { font-style: italic }
                   101666: .src-doc-var { font-style: italic }
                   101667: 
                   101668: /* tutorial */
                   101669: 
                   101670: .authors {  }
                   101671: .author { font-style: italic; font-weight: bold }
                   101672: .author-blurb { margin: .5em 0em .5em 2em; font-size: 85%; font-weight: normal; font-style: normal }
                   101673: .example { border: 1px dashed #999999; background-color: #EEEEEE; padding: .5em }
                   101674: .listing { border: 1px dashed #999999; background-color: #EEEEEE; padding: .5em; white-space: nowrap }
                   101675: .release-info { font-size: 85%; font-style: italic; margin: 1em 0em }
                   101676: .ref-title-box {  }
                   101677: .ref-title {  }
                   101678: .ref-purpose { font-style: italic; color: #666666 }
                   101679: .ref-synopsis {  }
                   101680: .title { font-weight: bold; margin: 1em 0em 0em 0em; padding: .25em; border: 2px solid #999999; background-color: #CCCCFF  }
                   101681: .cmd-synopsis { margin: 1em 0em }
                   101682: .cmd-title { font-weight: bold }
                   101683: .toc { margin-left: 2em; padding-left: 0em }
                   101684: 
                   101685: Structures_Graph-1.0.4/docs/html/Structures_Graph/Structures_Graph.html0000644000076600000240000002127311461440275025701 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   101686: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   101687:   <html xmlns="http://www.w3.org/1999/xhtml">
                   101688:                <head>
                   101689:                        <!-- template designed by Marco Von Ballmoos -->
                   101690:                        <title>Docs For Class Structures_Graph</title>
                   101691:                        <link rel="stylesheet" href="../media/stylesheet.css" />
                   101692:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   101693:                </head>
                   101694:                <body>
                   101695:                        <div class="page-body">                 
                   101696: <h2 class="class-name">Class Structures_Graph</h2>
                   101697: 
                   101698: <a name="sec-description"></a>
                   101699: <div class="info-box">
                   101700:        <div class="info-box-title">Description</div>
                   101701:        <div class="nav-bar">
                   101702:                                        <span class="disabled">Description</span> |
                   101703:                                                                                                                        <a href="#sec-method-summary">Methods</a> (<a href="#sec-methods">details</a>)
                   101704:                                                
                   101705:                        </div>
                   101706:        <div class="info-box-body">
                   101707:                <!-- ========== Info from phpDoc block ========= -->
                   101708: <p class="short-description">The Structures_Graph class represents a graph data structure.</p>
                   101709: <p class="description"><p>A Graph is a data structure composed by a set of nodes, connected by arcs.  Graphs may either be directed or undirected. In a directed graph, arcs are  directional, and can be traveled only one way. In an undirected graph, arcs  are bidirectional, and can be traveled both ways.</p></p>
                   101710:        <ul class="tags">
                   101711:                                <li><span class="field">copyright:</span> (c) 2004 by Sérgio Carvalho</li>
                   101712:                                <li><span class="field">author:</span> Sérgio Carvalho &lt;<a href="mailto:sergio.carvalho@portugalmail.com">mailto:sergio.carvalho@portugalmail.com</a>&gt;</li>
                   101713:                        </ul>
                   101714:                <p class="notes">
                   101715:                        Located in <a class="field" href="_Structures_Graph_php.html">/Structures/Graph.php</a> (line <span class="field">56</span>)
                   101716:                </p>
                   101717:                
                   101718:                                
                   101719:                <pre></pre>
                   101720:        
                   101721:                        </div>
                   101722: </div>
                   101723: 
                   101724: 
                   101725: 
                   101726:        <a name="sec-method-summary"></a>
                   101727:        <div class="info-box">
                   101728:                <div class="info-box-title">Method Summary</span></div>
                   101729:                <div class="nav-bar">
                   101730:                        <a href="#sec-description">Description</a> |
                   101731:                                                                        <span class="disabled">Methods</span> (<a href="#sec-methods">details</a>)
                   101732:                </div>
                   101733:                <div class="info-box-body">                     
                   101734:                        <div class="method-summary">
                   101735:                                                                
                   101736:                                <div class="method-definition">
                   101737:                                                                                        <span class="method-result">Structures_Graph</span>
                   101738:                                                                                <a href="#Structures_Graph" title="details" class="method-name">Structures_Graph</a>
                   101739:                                                                                        ([<span class="var-type">boolean</span>&nbsp;<span class="var-name">$directed</span> = <span class="var-default">true</span>])
                   101740:                                                                        </div>
                   101741:                                                                
                   101742:                                <div class="method-definition">
                   101743:                                                                                        <span class="method-result">void</span>
                   101744:                                                                                <a href="#addNode" title="details" class="method-name">addNode</a>
                   101745:                                                                                        (<span class="var-type"><a href="../Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a></span>&nbsp;<span class="var-name">&$newNode</span>)
                   101746:                                                                        </div>
                   101747:                                                                
                   101748:                                <div class="method-definition">
                   101749:                                                                                        <span class="method-result">array</span>
                   101750:                                                                                <a href="#getNodes" title="details" class="method-name">&amp;getNodes</a>
                   101751:                                                                                ()
                   101752:                                                                        </div>
                   101753:                                                                
                   101754:                                <div class="method-definition">
                   101755:                                                                                        <span class="method-result">boolean</span>
                   101756:                                                                                <a href="#isDirected" title="details" class="method-name">isDirected</a>
                   101757:                                                                                ()
                   101758:                                                                        </div>
                   101759:                                                                
                   101760:                                <div class="method-definition">
                   101761:                                                                                        <span class="method-result">void</span>
                   101762:                                                                                <a href="#removeNode" title="details" class="method-name">removeNode</a>
                   101763:                                                                                        (<span class="var-type"><a href="../Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a></span>&nbsp;<span class="var-name">&$node</span>)
                   101764:                                                                        </div>
                   101765:                                                        </div>
                   101766:                </div>
                   101767:        </div>          
                   101768: 
                   101769:        
                   101770:        <a name="sec-methods"></a>
                   101771:        <div class="info-box">
                   101772:                <div class="info-box-title">Methods</div>
                   101773:                <div class="nav-bar">
                   101774:                        <a href="#sec-description">Description</a> |
                   101775:                                                                                                        <a href="#sec-method-summary">Methods</a> (<span class="disabled">details</span>)
                   101776:                                                
                   101777:                </div>
                   101778:                <div class="info-box-body">
                   101779:                        <A NAME='method_detail'></A>
                   101780: <a name="methodStructures_Graph" id="Structures_Graph"><!-- --></a>
                   101781: <div class="evenrow">
                   101782:        
                   101783:        <div class="method-header">
                   101784:                <span class="method-title">Constructor Structures_Graph</span> (line <span class="line-number">76</span>)
                   101785:        </div> 
                   101786:        
                   101787:        <!-- ========== Info from phpDoc block ========= -->
                   101788: <p class="short-description">Constructor</p>
                   101789:        <ul class="tags">
                   101790:                                <li><span class="field">access:</span> public</li>
                   101791:                        </ul>
                   101792:        
                   101793:        <div class="method-signature">
                   101794:                <span class="method-result">Structures_Graph</span>
                   101795:                <span class="method-name">
                   101796:                        Structures_Graph
                   101797:                </span>
                   101798:                                        ([<span class="var-type">boolean</span>&nbsp;<span class="var-name">$directed</span> = <span class="var-default">true</span>])
                   101799:                        </div>
                   101800:        
                   101801:                        <ul class="parameters">
                   101802:                                        <li>
                   101803:                                <span class="var-type">boolean</span>
                   101804:                                <span class="var-name">$directed</span><span class="var-description">: Set to true if the graph is directed. Set to false if it is not directed. (Optional, defaults to true)</span>                    </li>
                   101805:                                </ul>
                   101806:                
                   101807:                
                   101808:        </div>
                   101809: <a name="methodaddNode" id="addNode"><!-- --></a>
                   101810: <div class="oddrow">
                   101811:        
                   101812:        <div class="method-header">
                   101813:                <span class="method-title">addNode</span> (line <span class="line-number">102</span>)
                   101814:        </div> 
                   101815:        
                   101816:        <!-- ========== Info from phpDoc block ========= -->
                   101817: <p class="short-description">Add a Node to the Graph</p>
                   101818:        <ul class="tags">
                   101819:                                <li><span class="field">access:</span> public</li>
                   101820:                        </ul>
                   101821:        
                   101822:        <div class="method-signature">
                   101823:                <span class="method-result">void</span>
                   101824:                <span class="method-name">
                   101825:                        addNode
                   101826:                </span>
                   101827:                                        (<span class="var-type"><a href="../Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a></span>&nbsp;<span class="var-name">&$newNode</span>)
                   101828:                        </div>
                   101829:        
                   101830:                        <ul class="parameters">
                   101831:                                        <li>
                   101832:                                <span class="var-type"><a href="../Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a></span>
                   101833:                                <span class="var-name">&$newNode</span><span class="var-description">: The node to be added.</span>                     </li>
                   101834:                                </ul>
                   101835:                
                   101836:                
                   101837:        </div>
                   101838: <a name="methodgetNodes" id="getNodes"><!-- --></a>
                   101839: <div class="evenrow">
                   101840:        
                   101841:        <div class="method-header">
                   101842:                <span class="method-title">getNodes</span> (line <span class="line-number">151</span>)
                   101843:        </div> 
                   101844:        
                   101845:        <!-- ========== Info from phpDoc block ========= -->
                   101846: <p class="short-description">Return the node set, in no particular order. For ordered node sets, use a Graph Manipulator insted.</p>
                   101847:        <ul class="tags">
                   101848:                                <li><span class="field">return:</span> The set of nodes in this graph</li>
                   101849:                                <li><span class="field">see:</span> <a href="../Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html">Structures_Graph_Manipulator_TopologicalSorter</a></li>
                   101850:                                <li><span class="field">access:</span> public</li>
                   101851:                        </ul>
                   101852:        
                   101853:        <div class="method-signature">
                   101854:                <span class="method-result">array</span>
                   101855:                <span class="method-name">
                   101856:                        &amp;getNodes
                   101857:                </span>
                   101858:                                ()
                   101859:                        </div>
                   101860:        
                   101861:                
                   101862:                
                   101863:        </div>
                   101864: <a name="methodisDirected" id="isDirected"><!-- --></a>
                   101865: <div class="oddrow">
                   101866:        
                   101867:        <div class="method-header">
                   101868:                <span class="method-title">isDirected</span> (line <span class="line-number">89</span>)
                   101869:        </div> 
                   101870:        
                   101871:        <!-- ========== Info from phpDoc block ========= -->
                   101872: <p class="short-description">Return true if a graph is directed</p>
                   101873:        <ul class="tags">
                   101874:                                <li><span class="field">return:</span> true if the graph is directed</li>
                   101875:                                <li><span class="field">access:</span> public</li>
                   101876:                        </ul>
                   101877:        
                   101878:        <div class="method-signature">
                   101879:                <span class="method-result">boolean</span>
                   101880:                <span class="method-name">
                   101881:                        isDirected
                   101882:                </span>
                   101883:                                ()
                   101884:                        </div>
                   101885:        
                   101886:                
                   101887:                
                   101888:        </div>
                   101889: <a name="methodremoveNode" id="removeNode"><!-- --></a>
                   101890: <div class="evenrow">
                   101891:        
                   101892:        <div class="method-header">
                   101893:                <span class="method-title">removeNode</span> (line <span class="line-number">138</span>)
                   101894:        </div> 
                   101895:        
                   101896:        <!-- ========== Info from phpDoc block ========= -->
                   101897: <p class="short-description">Remove a Node from the Graph</p>
                   101898:        <ul class="tags">
                   101899:                                <li><span class="field">access:</span> public</li>
                   101900:                                <li><span class="field">todo:</span> This is unimplemented</li>
                   101901:                        </ul>
                   101902:        
                   101903:        <div class="method-signature">
                   101904:                <span class="method-result">void</span>
                   101905:                <span class="method-name">
                   101906:                        removeNode
                   101907:                </span>
                   101908:                                        (<span class="var-type"><a href="../Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a></span>&nbsp;<span class="var-name">&$node</span>)
                   101909:                        </div>
                   101910:        
                   101911:                        <ul class="parameters">
                   101912:                                        <li>
                   101913:                                <span class="var-type"><a href="../Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a></span>
                   101914:                                <span class="var-name">&$node</span><span class="var-description">: The node to be removed from the graph</span>                        </li>
                   101915:                                </ul>
                   101916:                
                   101917:                
                   101918:        </div>
                   101919:                                                
                   101920:                </div>
                   101921:        </div>
                   101922:        
                   101923:        <p class="notes" id="credit">
                   101924:                Documentation generated on Fri, 30 Jan 2004 16:37:28 +0000 by <a href="http://www.phpdoc.org" target="_blank">phpDocumentor 1.2.3</a>
                   101925:        </p>
                   101926:        </div></body>
                   101927: </html>Structures_Graph-1.0.4/docs/html/Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html0000644000076600000240000000741011461440275032540 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   101928: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   101929:   <html xmlns="http://www.w3.org/1999/xhtml">
                   101930:                <head>
                   101931:                        <!-- template designed by Marco Von Ballmoos -->
                   101932:                        <title>Docs For Class Structures_Graph_Manipulator_AcyclicTest</title>
                   101933:                        <link rel="stylesheet" href="../media/stylesheet.css" />
                   101934:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   101935:                </head>
                   101936:                <body>
                   101937:                        <div class="page-body">                 
                   101938: <h2 class="class-name">Class Structures_Graph_Manipulator_AcyclicTest</h2>
                   101939: 
                   101940: <a name="sec-description"></a>
                   101941: <div class="info-box">
                   101942:        <div class="info-box-title">Description</div>
                   101943:        <div class="nav-bar">
                   101944:                                        <span class="disabled">Description</span> |
                   101945:                                                                                                                        <a href="#sec-method-summary">Methods</a> (<a href="#sec-methods">details</a>)
                   101946:                                                
                   101947:                        </div>
                   101948:        <div class="info-box-body">
                   101949:                <!-- ========== Info from phpDoc block ========= -->
                   101950: <p class="short-description">The Structures_Graph_Manipulator_AcyclicTest is a graph manipulator  which tests whether a graph contains a cycle.</p>
                   101951: <p class="description"><p>The definition of an acyclic graph used in this manipulator is that of a  DAG. The graph must be directed, or else it is considered cyclic, even when  there are no arcs.</p></p>
                   101952:        <ul class="tags">
                   101953:                                <li><span class="field">copyright:</span> (c) 2004 by Sérgio Carvalho</li>
                   101954:                                <li><span class="field">author:</span> Sérgio Carvalho &lt;<a href="mailto:sergio.carvalho@portugalmail.com">mailto:sergio.carvalho@portugalmail.com</a>&gt;</li>
                   101955:                        </ul>
                   101956:                <p class="notes">
                   101957:                        Located in <a class="field" href="_Structures_Graph_Manipulator_AcyclicTest_php.html">/Structures/Graph/Manipulator/AcyclicTest.php</a> (line <span class="field">55</span>)
                   101958:                </p>
                   101959:                
                   101960:                                
                   101961:                <pre></pre>
                   101962:        
                   101963:                        </div>
                   101964: </div>
                   101965: 
                   101966: 
                   101967: 
                   101968:        <a name="sec-method-summary"></a>
                   101969:        <div class="info-box">
                   101970:                <div class="info-box-title">Method Summary</span></div>
                   101971:                <div class="nav-bar">
                   101972:                        <a href="#sec-description">Description</a> |
                   101973:                                                                        <span class="disabled">Methods</span> (<a href="#sec-methods">details</a>)
                   101974:                </div>
                   101975:                <div class="info-box-body">                     
                   101976:                        <div class="method-summary">
                   101977:                                                                
                   101978:                                <div class="method-definition">
                   101979:                                                                                        <span class="method-result">boolean</span>
                   101980:                                                                                <a href="#isAcyclic" title="details" class="method-name">isAcyclic</a>
                   101981:                                                                                        (<span class="var-type">mixed</span>&nbsp;<span class="var-name">&$graph</span>)
                   101982:                                                                        </div>
                   101983:                                                        </div>
                   101984:                </div>
                   101985:        </div>          
                   101986: 
                   101987:        
                   101988:        <a name="sec-methods"></a>
                   101989:        <div class="info-box">
                   101990:                <div class="info-box-title">Methods</div>
                   101991:                <div class="nav-bar">
                   101992:                        <a href="#sec-description">Description</a> |
                   101993:                                                                                                        <a href="#sec-method-summary">Methods</a> (<span class="disabled">details</span>)
                   101994:                                                
                   101995:                </div>
                   101996:                <div class="info-box-body">
                   101997:                        <A NAME='method_detail'></A>
                   101998: <a name="methodisAcyclic" id="isAcyclic"><!-- --></a>
                   101999: <div class="evenrow">
                   102000:        
                   102001:        <div class="method-header">
                   102002:                <span class="method-title">isAcyclic</span> (line <span class="line-number">126</span>)
                   102003:        </div> 
                   102004:        
                   102005:        <!-- ========== Info from phpDoc block ========= -->
                   102006: <p class="short-description">isAcyclic returns true if a graph contains no cycles, false otherwise.</p>
                   102007:        <ul class="tags">
                   102008:                                <li><span class="field">return:</span> true iff graph is acyclic</li>
                   102009:                                <li><span class="field">access:</span> public</li>
                   102010:                        </ul>
                   102011:        
                   102012:        <div class="method-signature">
                   102013:                <span class="method-result">boolean</span>
                   102014:                <span class="method-name">
                   102015:                        isAcyclic
                   102016:                </span>
                   102017:                                        (<span class="var-type">mixed</span>&nbsp;<span class="var-name">&$graph</span>)
                   102018:                        </div>
                   102019:        
                   102020:                
                   102021:                
                   102022:        </div>
                   102023:                                                
                   102024:                </div>
                   102025:        </div>
                   102026:        
                   102027:        <p class="notes" id="credit">
                   102028:                Documentation generated on Fri, 30 Jan 2004 16:37:28 +0000 by <a href="http://www.phpdoc.org" target="_blank">phpDocumentor 1.2.3</a>
                   102029:        </p>
                   102030:        </div></body>
                   102031: </html>././@LongLink000        145 0003736 LStructures_Graph-1.0.4/docs/html/Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.htmlStructures_Graph-1.0.4/docs/html/Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.htm0000644000076600000240000001014111461440275033623 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   102032: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   102033:   <html xmlns="http://www.w3.org/1999/xhtml">
                   102034:                <head>
                   102035:                        <!-- template designed by Marco Von Ballmoos -->
                   102036:                        <title>Docs For Class Structures_Graph_Manipulator_TopologicalSorter</title>
                   102037:                        <link rel="stylesheet" href="../media/stylesheet.css" />
                   102038:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   102039:                </head>
                   102040:                <body>
                   102041:                        <div class="page-body">                 
                   102042: <h2 class="class-name">Class Structures_Graph_Manipulator_TopologicalSorter</h2>
                   102043: 
                   102044: <a name="sec-description"></a>
                   102045: <div class="info-box">
                   102046:        <div class="info-box-title">Description</div>
                   102047:        <div class="nav-bar">
                   102048:                                        <span class="disabled">Description</span> |
                   102049:                                                                                                                        <a href="#sec-method-summary">Methods</a> (<a href="#sec-methods">details</a>)
                   102050:                                                
                   102051:                        </div>
                   102052:        <div class="info-box-body">
                   102053:                <!-- ========== Info from phpDoc block ========= -->
                   102054: <p class="short-description">The Structures_Graph_Manipulator_TopologicalSorter is a manipulator  which is able to return the set of nodes in a graph, sorted by topological  order.</p>
                   102055: <p class="description"><p>A graph may only be sorted topologically iff it's a DAG. You can test it  with the Structures_Graph_Manipulator_AcyclicTest.</p></p>
                   102056:        <ul class="tags">
                   102057:                                <li><span class="field">see:</span> <a href="../Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html">Structures_Graph_Manipulator_AcyclicTest</a></li>
                   102058:                                <li><span class="field">copyright:</span> (c) 2004 by Sérgio Carvalho</li>
                   102059:                                <li><span class="field">author:</span> Sérgio Carvalho &lt;<a href="mailto:sergio.carvalho@portugalmail.com">mailto:sergio.carvalho@portugalmail.com</a>&gt;</li>
                   102060:                        </ul>
                   102061:                <p class="notes">
                   102062:                        Located in <a class="field" href="_Structures_Graph_Manipulator_TopologicalSorter_php.html">/Structures/Graph/Manipulator/TopologicalSorter.php</a> (line <span class="field">58</span>)
                   102063:                </p>
                   102064:                
                   102065:                                
                   102066:                <pre></pre>
                   102067:        
                   102068:                        </div>
                   102069: </div>
                   102070: 
                   102071: 
                   102072: 
                   102073:        <a name="sec-method-summary"></a>
                   102074:        <div class="info-box">
                   102075:                <div class="info-box-title">Method Summary</span></div>
                   102076:                <div class="nav-bar">
                   102077:                        <a href="#sec-description">Description</a> |
                   102078:                                                                        <span class="disabled">Methods</span> (<a href="#sec-methods">details</a>)
                   102079:                </div>
                   102080:                <div class="info-box-body">                     
                   102081:                        <div class="method-summary">
                   102082:                                                                
                   102083:                                <div class="method-definition">
                   102084:                                                                                        <span class="method-result">array</span>
                   102085:                                                                                <a href="#sort" title="details" class="method-name">sort</a>
                   102086:                                                                                        (<span class="var-type">mixed</span>&nbsp;<span class="var-name">&$graph</span>)
                   102087:                                                                        </div>
                   102088:                                                        </div>
                   102089:                </div>
                   102090:        </div>          
                   102091: 
                   102092:        
                   102093:        <a name="sec-methods"></a>
                   102094:        <div class="info-box">
                   102095:                <div class="info-box-title">Methods</div>
                   102096:                <div class="nav-bar">
                   102097:                        <a href="#sec-description">Description</a> |
                   102098:                                                                                                        <a href="#sec-method-summary">Methods</a> (<span class="disabled">details</span>)
                   102099:                                                
                   102100:                </div>
                   102101:                <div class="info-box-body">
                   102102:                        <A NAME='method_detail'></A>
                   102103: <a name="methodsort" id="sort"><!-- --></a>
                   102104: <div class="evenrow">
                   102105:        
                   102106:        <div class="method-header">
                   102107:                <span class="method-title">sort</span> (line <span class="line-number">133</span>)
                   102108:        </div> 
                   102109:        
                   102110:        <!-- ========== Info from phpDoc block ========= -->
                   102111: <p class="short-description">sort returns the graph's nodes, sorted by topological order.</p>
                   102112: <p class="description"><p>The result is an array with  as many entries as topological levels. Each entry in this array is an array of nodes within  the given topological level.</p></p>
                   102113:        <ul class="tags">
                   102114:                                <li><span class="field">return:</span> The graph's nodes, sorted by topological order.</li>
                   102115:                                <li><span class="field">access:</span> public</li>
                   102116:                        </ul>
                   102117:        
                   102118:        <div class="method-signature">
                   102119:                <span class="method-result">array</span>
                   102120:                <span class="method-name">
                   102121:                        sort
                   102122:                </span>
                   102123:                                        (<span class="var-type">mixed</span>&nbsp;<span class="var-name">&$graph</span>)
                   102124:                        </div>
                   102125:        
                   102126:                
                   102127:                
                   102128:        </div>
                   102129:                                                
                   102130:                </div>
                   102131:        </div>
                   102132:        
                   102133:        <p class="notes" id="credit">
                   102134:                Documentation generated on Fri, 30 Jan 2004 16:37:29 +0000 by <a href="http://www.phpdoc.org" target="_blank">phpDocumentor 1.2.3</a>
                   102135:        </p>
                   102136:        </div></body>
                   102137: </html>Structures_Graph-1.0.4/docs/html/Structures_Graph/Structures_Graph_Node.html0000644000076600000240000005007111461440275026644 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   102138: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   102139:   <html xmlns="http://www.w3.org/1999/xhtml">
                   102140:                <head>
                   102141:                        <!-- template designed by Marco Von Ballmoos -->
                   102142:                        <title>Docs For Class Structures_Graph_Node</title>
                   102143:                        <link rel="stylesheet" href="../media/stylesheet.css" />
                   102144:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   102145:                </head>
                   102146:                <body>
                   102147:                        <div class="page-body">                 
                   102148: <h2 class="class-name">Class Structures_Graph_Node</h2>
                   102149: 
                   102150: <a name="sec-description"></a>
                   102151: <div class="info-box">
                   102152:        <div class="info-box-title">Description</div>
                   102153:        <div class="nav-bar">
                   102154:                                        <span class="disabled">Description</span> |
                   102155:                                                                                                                        <a href="#sec-method-summary">Methods</a> (<a href="#sec-methods">details</a>)
                   102156:                                                
                   102157:                        </div>
                   102158:        <div class="info-box-body">
                   102159:                <!-- ========== Info from phpDoc block ========= -->
                   102160: <p class="short-description">The Structures_Graph_Node class represents a Node that can be member of a  graph node set.</p>
                   102161: <p class="description"><p>A graph node can contain data. Under this API, the node contains default data,  and key index data. It behaves, thus, both as a regular data node, and as a  dictionary (or associative array) node.</p><p>Regular data is accessed via getData and setData. Key indexed data is accessed  via getMetadata and setMetadata.</p></p>
                   102162:        <ul class="tags">
                   102163:                                <li><span class="field">copyright:</span> (c) 2004 by Sérgio Carvalho</li>
                   102164:                                <li><span class="field">author:</span> Sérgio Carvalho &lt;<a href="mailto:sergio.carvalho@portugalmail.com">mailto:sergio.carvalho@portugalmail.com</a>&gt;</li>
                   102165:                        </ul>
                   102166:                <p class="notes">
                   102167:                        Located in <a class="field" href="_Structures_Graph_Node_php.html">/Structures/Graph/Node.php</a> (line <span class="field">57</span>)
                   102168:                </p>
                   102169:                
                   102170:                                
                   102171:                <pre></pre>
                   102172:        
                   102173:                        </div>
                   102174: </div>
                   102175: 
                   102176: 
                   102177: 
                   102178:        <a name="sec-method-summary"></a>
                   102179:        <div class="info-box">
                   102180:                <div class="info-box-title">Method Summary</span></div>
                   102181:                <div class="nav-bar">
                   102182:                        <a href="#sec-description">Description</a> |
                   102183:                                                                        <span class="disabled">Methods</span> (<a href="#sec-methods">details</a>)
                   102184:                </div>
                   102185:                <div class="info-box-body">                     
                   102186:                        <div class="method-summary">
                   102187:                                                                
                   102188:                                <div class="method-definition">
                   102189:                                                                                        <span class="method-result">Structures_Graph_Node</span>
                   102190:                                                                                <a href="#Structures_Graph_Node" title="details" class="method-name">Structures_Graph_Node</a>
                   102191:                                                                                ()
                   102192:                                                                        </div>
                   102193:                                                                
                   102194:                                <div class="method-definition">
                   102195:                                                                                        <span class="method-result">boolean</span>
                   102196:                                                                                <a href="#connectsTo" title="details" class="method-name">connectsTo</a>
                   102197:                                                                                        (<span class="var-type">mixed</span>&nbsp;<span class="var-name">&$target</span>)
                   102198:                                                                        </div>
                   102199:                                                                
                   102200:                                <div class="method-definition">
                   102201:                                                                                        <span class="method-result">void</span>
                   102202:                                                                                <a href="#connectTo" title="details" class="method-name">connectTo</a>
                   102203:                                                                                        (<span class="var-type"><a href="../Structures_Graph/Structures_Graph.html">Structures_Graph</a></span>&nbsp;<span class="var-name">&$destinationNode</span>)
                   102204:                                                                        </div>
                   102205:                                                                
                   102206:                                <div class="method-definition">
                   102207:                                                                                        <span class="method-result">mixed</span>
                   102208:                                                                                <a href="#getData" title="details" class="method-name">&amp;getData</a>
                   102209:                                                                                ()
                   102210:                                                                        </div>
                   102211:                                                                
                   102212:                                <div class="method-definition">
                   102213:                                                                                        <span class="method-result"><a href="../Structures_Graph/Structures_Graph.html">Structures_Graph</a></span>
                   102214:                                                                                <a href="#getGraph" title="details" class="method-name">&amp;getGraph</a>
                   102215:                                                                                ()
                   102216:                                                                        </div>
                   102217:                                                                
                   102218:                                <div class="method-definition">
                   102219:                                                                                        <span class="method-result">mixed</span>
                   102220:                                                                                <a href="#getMetadata" title="details" class="method-name">&amp;getMetadata</a>
                   102221:                                                                                        (<span class="var-type">string</span>&nbsp;<span class="var-name">$key</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$nullIfNonexistent</span> = <span class="var-default">false</span>])
                   102222:                                                                        </div>
                   102223:                                                                
                   102224:                                <div class="method-definition">
                   102225:                                                                                        <span class="method-result">array</span>
                   102226:                                                                                <a href="#getNeighbours" title="details" class="method-name">getNeighbours</a>
                   102227:                                                                                ()
                   102228:                                                                        </div>
                   102229:                                                                
                   102230:                                <div class="method-definition">
                   102231:                                                                                        <span class="method-result">integer</span>
                   102232:                                                                                <a href="#inDegree" title="details" class="method-name">inDegree</a>
                   102233:                                                                                ()
                   102234:                                                                        </div>
                   102235:                                                                
                   102236:                                <div class="method-definition">
                   102237:                                                                                        <span class="method-result">boolean</span>
                   102238:                                                                                <a href="#metadataKeyExists" title="details" class="method-name">metadataKeyExists</a>
                   102239:                                                                                        (<span class="var-type">string</span>&nbsp;<span class="var-name">$key</span>)
                   102240:                                                                        </div>
                   102241:                                                                
                   102242:                                <div class="method-definition">
                   102243:                                                                                        <span class="method-result">integer</span>
                   102244:                                                                                <a href="#outDegree" title="details" class="method-name">outDegree</a>
                   102245:                                                                                ()
                   102246:                                                                        </div>
                   102247:                                                                
                   102248:                                <div class="method-definition">
                   102249:                                                                                        <span class="method-result">mixed</span>
                   102250:                                                                                <a href="#setData" title="details" class="method-name">setData</a>
                   102251:                                                                                        (<span class="var-type">mixed</span>&nbsp;<span class="var-name">$data</span>)
                   102252:                                                                        </div>
                   102253:                                                                
                   102254:                                <div class="method-definition">
                   102255:                                                                                        <span class="method-result">void</span>
                   102256:                                                                                <a href="#setGraph" title="details" class="method-name">setGraph</a>
                   102257:                                                                                        (<span class="var-type"><a href="../Structures_Graph/Structures_Graph.html">Structures_Graph</a></span>&nbsp;<span class="var-name">&$graph</span>)
                   102258:                                                                        </div>
                   102259:                                                                
                   102260:                                <div class="method-definition">
                   102261:                                                                                        <span class="method-result">void</span>
                   102262:                                                                                <a href="#setMetadata" title="details" class="method-name">setMetadata</a>
                   102263:                                                                                        (<span class="var-type">string</span>&nbsp;<span class="var-name">$key</span>, <span class="var-type">mixed</span>&nbsp;<span class="var-name">$data</span>)
                   102264:                                                                        </div>
                   102265:                                                                
                   102266:                                <div class="method-definition">
                   102267:                                                                                        <span class="method-result">void</span>
                   102268:                                                                                <a href="#unsetMetadata" title="details" class="method-name">unsetMetadata</a>
                   102269:                                                                                        (<span class="var-type">string</span>&nbsp;<span class="var-name">$key</span>)
                   102270:                                                                        </div>
                   102271:                                                        </div>
                   102272:                </div>
                   102273:        </div>          
                   102274: 
                   102275:        
                   102276:        <a name="sec-methods"></a>
                   102277:        <div class="info-box">
                   102278:                <div class="info-box-title">Methods</div>
                   102279:                <div class="nav-bar">
                   102280:                        <a href="#sec-description">Description</a> |
                   102281:                                                                                                        <a href="#sec-method-summary">Methods</a> (<span class="disabled">details</span>)
                   102282:                                                
                   102283:                </div>
                   102284:                <div class="info-box-body">
                   102285:                        <A NAME='method_detail'></A>
                   102286: <a name="methodStructures_Graph_Node" id="Structures_Graph_Node"><!-- --></a>
                   102287: <div class="evenrow">
                   102288:        
                   102289:        <div class="method-header">
                   102290:                <span class="method-title">Constructor Structures_Graph_Node</span> (line <span class="line-number">78</span>)
                   102291:        </div> 
                   102292:        
                   102293:        <!-- ========== Info from phpDoc block ========= -->
                   102294: <p class="short-description">Constructor</p>
                   102295:        <ul class="tags">
                   102296:                                <li><span class="field">access:</span> public</li>
                   102297:                        </ul>
                   102298:        
                   102299:        <div class="method-signature">
                   102300:                <span class="method-result">Structures_Graph_Node</span>
                   102301:                <span class="method-name">
                   102302:                        Structures_Graph_Node
                   102303:                </span>
                   102304:                                ()
                   102305:                        </div>
                   102306:        
                   102307:                
                   102308:                
                   102309:        </div>
                   102310: <a name="methodconnectsTo" id="connectsTo"><!-- --></a>
                   102311: <div class="oddrow">
                   102312:        
                   102313:        <div class="method-header">
                   102314:                <span class="method-title">connectsTo</span> (line <span class="line-number">275</span>)
                   102315:        </div> 
                   102316:        
                   102317:        <!-- ========== Info from phpDoc block ========= -->
                   102318: <p class="short-description">Test wether this node has an arc to the target node</p>
                   102319:        <ul class="tags">
                   102320:                                <li><span class="field">return:</span> True if the two nodes are connected</li>
                   102321:                                <li><span class="field">access:</span> public</li>
                   102322:                        </ul>
                   102323:        
                   102324:        <div class="method-signature">
                   102325:                <span class="method-result">boolean</span>
                   102326:                <span class="method-name">
                   102327:                        connectsTo
                   102328:                </span>
                   102329:                                        (<span class="var-type">mixed</span>&nbsp;<span class="var-name">&$target</span>)
                   102330:                        </div>
                   102331:        
                   102332:                
                   102333:                
                   102334:        </div>
                   102335: <a name="methodconnectTo" id="connectTo"><!-- --></a>
                   102336: <div class="evenrow">
                   102337:        
                   102338:        <div class="method-header">
                   102339:                <span class="method-title">connectTo</span> (line <span class="line-number">236</span>)
                   102340:        </div> 
                   102341:        
                   102342:        <!-- ========== Info from phpDoc block ========= -->
                   102343: <p class="short-description">Connect this node to another one.</p>
                   102344: <p class="description"><p>If the graph is not directed, the reverse arc, connecting $destinationNode to $this is also created.</p></p>
                   102345:        <ul class="tags">
                   102346:                                <li><span class="field">access:</span> public</li>
                   102347:                        </ul>
                   102348:        
                   102349:        <div class="method-signature">
                   102350:                <span class="method-result">void</span>
                   102351:                <span class="method-name">
                   102352:                        connectTo
                   102353:                </span>
                   102354:                                        (<span class="var-type"><a href="../Structures_Graph/Structures_Graph.html">Structures_Graph</a></span>&nbsp;<span class="var-name">&$destinationNode</span>)
                   102355:                        </div>
                   102356:        
                   102357:                        <ul class="parameters">
                   102358:                                        <li>
                   102359:                                <span class="var-type"><a href="../Structures_Graph/Structures_Graph.html">Structures_Graph</a></span>
                   102360:                                <span class="var-name">&$destinationNode</span><span class="var-description">: Node to connect to</span>                        </li>
                   102361:                                </ul>
                   102362:                
                   102363:                
                   102364:        </div>
                   102365: <a name="methodgetData" id="getData"><!-- --></a>
                   102366: <div class="oddrow">
                   102367:        
                   102368:        <div class="method-header">
                   102369:                <span class="method-title">getData</span> (line <span class="line-number">119</span>)
                   102370:        </div> 
                   102371:        
                   102372:        <!-- ========== Info from phpDoc block ========= -->
                   102373: <p class="short-description">Node data getter.</p>
                   102374: <p class="description"><p>Each graph node can contain a reference to one variable. This is the getter for that reference.</p></p>
                   102375:        <ul class="tags">
                   102376:                                <li><span class="field">return:</span> Data stored in node</li>
                   102377:                                <li><span class="field">access:</span> public</li>
                   102378:                        </ul>
                   102379:        
                   102380:        <div class="method-signature">
                   102381:                <span class="method-result">mixed</span>
                   102382:                <span class="method-name">
                   102383:                        &amp;getData
                   102384:                </span>
                   102385:                                ()
                   102386:                        </div>
                   102387:        
                   102388:                
                   102389:                
                   102390:        </div>
                   102391: <a name="methodgetGraph" id="getGraph"><!-- --></a>
                   102392: <div class="evenrow">
                   102393:        
                   102394:        <div class="method-header">
                   102395:                <span class="method-title">getGraph</span> (line <span class="line-number">90</span>)
                   102396:        </div> 
                   102397:        
                   102398:        <!-- ========== Info from phpDoc block ========= -->
                   102399: <p class="short-description">Node graph getter</p>
                   102400:        <ul class="tags">
                   102401:                                <li><span class="field">return:</span> Graph where node is stored</li>
                   102402:                                <li><span class="field">access:</span> public</li>
                   102403:                        </ul>
                   102404:        
                   102405:        <div class="method-signature">
                   102406:                <span class="method-result"><a href="../Structures_Graph/Structures_Graph.html">Structures_Graph</a></span>
                   102407:                <span class="method-name">
                   102408:                        &amp;getGraph
                   102409:                </span>
                   102410:                                ()
                   102411:                        </div>
                   102412:        
                   102413:                
                   102414:                
                   102415:        </div>
                   102416: <a name="methodgetMetadata" id="getMetadata"><!-- --></a>
                   102417: <div class="oddrow">
                   102418:        
                   102419:        <div class="method-header">
                   102420:                <span class="method-title">getMetadata</span> (line <span class="line-number">171</span>)
                   102421:        </div> 
                   102422:        
                   102423:        <!-- ========== Info from phpDoc block ========= -->
                   102424: <p class="short-description">Node metadata getter</p>
                   102425: <p class="description"><p>Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an  associative array or in a dictionary. This method gets the data under the given key. If the key does  not exist, an error will be thrown, so testing using metadataKeyExists might be needed.</p></p>
                   102426:        <ul class="tags">
                   102427:                                <li><span class="field">return:</span> Metadata Data stored in node under given key</li>
                   102428:                                <li><span class="field">access:</span> public</li>
                   102429:                                <li><span class="field">see:</span> <a href="../Structures_Graph/Structures_Graph_Node.html#methodmetadataKeyExists">Structures_Graph_Node::metadataKeyExists()</a></li>
                   102430:                        </ul>
                   102431:        
                   102432:        <div class="method-signature">
                   102433:                <span class="method-result">mixed</span>
                   102434:                <span class="method-name">
                   102435:                        &amp;getMetadata
                   102436:                </span>
                   102437:                                        (<span class="var-type">string</span>&nbsp;<span class="var-name">$key</span>, [<span class="var-type">boolean</span>&nbsp;<span class="var-name">$nullIfNonexistent</span> = <span class="var-default">false</span>])
                   102438:                        </div>
                   102439:        
                   102440:                        <ul class="parameters">
                   102441:                                        <li>
                   102442:                                <span class="var-type">string</span>
                   102443:                                <span class="var-name">$key</span><span class="var-description">: Key</span>                    </li>
                   102444:                                        <li>
                   102445:                                <span class="var-type">boolean</span>
                   102446:                                <span class="var-name">$nullIfNonexistent</span><span class="var-description">: nullIfNonexistent (defaults to false).</span>                   </li>
                   102447:                                </ul>
                   102448:                
                   102449:                
                   102450:        </div>
                   102451: <a name="methodgetNeighbours" id="getNeighbours"><!-- --></a>
                   102452: <div class="evenrow">
                   102453:        
                   102454:        <div class="method-header">
                   102455:                <span class="method-title">getNeighbours</span> (line <span class="line-number">262</span>)
                   102456:        </div> 
                   102457:        
                   102458:        <!-- ========== Info from phpDoc block ========= -->
                   102459: <p class="short-description">Return nodes connected to this one.</p>
                   102460:        <ul class="tags">
                   102461:                                <li><span class="field">return:</span> Array of nodes</li>
                   102462:                                <li><span class="field">access:</span> public</li>
                   102463:                        </ul>
                   102464:        
                   102465:        <div class="method-signature">
                   102466:                <span class="method-result">array</span>
                   102467:                <span class="method-name">
                   102468:                        getNeighbours
                   102469:                </span>
                   102470:                                ()
                   102471:                        </div>
                   102472:        
                   102473:                
                   102474:                
                   102475:        </div>
                   102476: <a name="methodinDegree" id="inDegree"><!-- --></a>
                   102477: <div class="oddrow">
                   102478:        
                   102479:        <div class="method-header">
                   102480:                <span class="method-title">inDegree</span> (line <span class="line-number">309</span>)
                   102481:        </div> 
                   102482:        
                   102483:        <!-- ========== Info from phpDoc block ========= -->
                   102484: <p class="short-description">Calculate the in degree of the node.</p>
                   102485: <p class="description"><p>The indegree for a node is the number of arcs entering the node. For non directed graphs,  the indegree is equal to the outdegree.</p></p>
                   102486:        <ul class="tags">
                   102487:                                <li><span class="field">return:</span> In degree of the node</li>
                   102488:                                <li><span class="field">access:</span> public</li>
                   102489:                        </ul>
                   102490:        
                   102491:        <div class="method-signature">
                   102492:                <span class="method-result">integer</span>
                   102493:                <span class="method-name">
                   102494:                        inDegree
                   102495:                </span>
                   102496:                                ()
                   102497:                        </div>
                   102498:        
                   102499:                
                   102500:                
                   102501:        </div>
                   102502: <a name="methodmetadataKeyExists" id="metadataKeyExists"><!-- --></a>
                   102503: <div class="evenrow">
                   102504:        
                   102505:        <div class="method-header">
                   102506:                <span class="method-title">metadataKeyExists</span> (line <span class="line-number">151</span>)
                   102507:        </div> 
                   102508:        
                   102509:        <!-- ========== Info from phpDoc block ========= -->
                   102510: <p class="short-description">Test for existence of metadata under a given key.</p>
                   102511: <p class="description"><p>Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an  associative array or in a dictionary. This method tests whether a given metadata key exists for this node.</p></p>
                   102512:        <ul class="tags">
                   102513:                                <li><span class="field">access:</span> public</li>
                   102514:                        </ul>
                   102515:        
                   102516:        <div class="method-signature">
                   102517:                <span class="method-result">boolean</span>
                   102518:                <span class="method-name">
                   102519:                        metadataKeyExists
                   102520:                </span>
                   102521:                                        (<span class="var-type">string</span>&nbsp;<span class="var-name">$key</span>)
                   102522:                        </div>
                   102523:        
                   102524:                        <ul class="parameters">
                   102525:                                        <li>
                   102526:                                <span class="var-type">string</span>
                   102527:                                <span class="var-name">$key</span><span class="var-description">: Key to test</span>                    </li>
                   102528:                                </ul>
                   102529:                
                   102530:                
                   102531:        </div>
                   102532: <a name="methodoutDegree" id="outDegree"><!-- --></a>
                   102533: <div class="oddrow">
                   102534:        
                   102535:        <div class="method-header">
                   102536:                <span class="method-title">outDegree</span> (line <span class="line-number">333</span>)
                   102537:        </div> 
                   102538:        
                   102539:        <!-- ========== Info from phpDoc block ========= -->
                   102540: <p class="short-description">Calculate the out degree of the node.</p>
                   102541: <p class="description"><p>The outdegree for a node is the number of arcs exiting the node. For non directed graphs,  the outdegree is always equal to the indegree.</p></p>
                   102542:        <ul class="tags">
                   102543:                                <li><span class="field">return:</span> Out degree of the node</li>
                   102544:                                <li><span class="field">access:</span> public</li>
                   102545:                        </ul>
                   102546:        
                   102547:        <div class="method-signature">
                   102548:                <span class="method-result">integer</span>
                   102549:                <span class="method-name">
                   102550:                        outDegree
                   102551:                </span>
                   102552:                                ()
                   102553:                        </div>
                   102554:        
                   102555:                
                   102556:                
                   102557:        </div>
                   102558: <a name="methodsetData" id="setData"><!-- --></a>
                   102559: <div class="evenrow">
                   102560:        
                   102561:        <div class="method-header">
                   102562:                <span class="method-title">setData</span> (line <span class="line-number">134</span>)
                   102563:        </div> 
                   102564:        
                   102565:        <!-- ========== Info from phpDoc block ========= -->
                   102566: <p class="short-description">Node data setter</p>
                   102567: <p class="description"><p>Each graph node can contain a reference to one variable. This is the setter for that reference.</p></p>
                   102568:        <ul class="tags">
                   102569:                                <li><span class="field">return:</span> Data to store in node</li>
                   102570:                                <li><span class="field">access:</span> public</li>
                   102571:                        </ul>
                   102572:        
                   102573:        <div class="method-signature">
                   102574:                <span class="method-result">mixed</span>
                   102575:                <span class="method-name">
                   102576:                        setData
                   102577:                </span>
                   102578:                                        (<span class="var-type">mixed</span>&nbsp;<span class="var-name">$data</span>)
                   102579:                        </div>
                   102580:        
                   102581:                
                   102582:                
                   102583:        </div>
                   102584: <a name="methodsetGraph" id="setGraph"><!-- --></a>
                   102585: <div class="oddrow">
                   102586:        
                   102587:        <div class="method-header">
                   102588:                <span class="method-title">setGraph</span> (line <span class="line-number">104</span>)
                   102589:        </div> 
                   102590:        
                   102591:        <!-- ========== Info from phpDoc block ========= -->
                   102592: <p class="short-description">Node graph setter. This method should not be called directly. Use Graph::addNode instead.</p>
                   102593:        <ul class="tags">
                   102594:                                <li><span class="field">access:</span> public</li>
                   102595:                                <li><span class="field">see:</span> <a href="../Structures_Graph/Structures_Graph.html#methodaddNode">Structures_Graph::addNode()</a></li>
                   102596:                        </ul>
                   102597:        
                   102598:        <div class="method-signature">
                   102599:                <span class="method-result">void</span>
                   102600:                <span class="method-name">
                   102601:                        setGraph
                   102602:                </span>
                   102603:                                        (<span class="var-type"><a href="../Structures_Graph/Structures_Graph.html">Structures_Graph</a></span>&nbsp;<span class="var-name">&$graph</span>)
                   102604:                        </div>
                   102605:        
                   102606:                        <ul class="parameters">
                   102607:                                        <li>
                   102608:                                <span class="var-type"><a href="../Structures_Graph/Structures_Graph.html">Structures_Graph</a></span>
                   102609:                                <span class="var-name">&$graph</span><span class="var-description">: Set the graph for this node.</span>                        </li>
                   102610:                                </ul>
                   102611:                
                   102612:                
                   102613:        </div>
                   102614: <a name="methodsetMetadata" id="setMetadata"><!-- --></a>
                   102615: <div class="evenrow">
                   102616:        
                   102617:        <div class="method-header">
                   102618:                <span class="method-title">setMetadata</span> (line <span class="line-number">214</span>)
                   102619:        </div> 
                   102620:        
                   102621:        <!-- ========== Info from phpDoc block ========= -->
                   102622: <p class="short-description">Node metadata setter</p>
                   102623: <p class="description"><p>Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an  associative array or in a dictionary. This method stores data under the given key. If the key already exists,  previously stored data is discarded.</p></p>
                   102624:        <ul class="tags">
                   102625:                                <li><span class="field">access:</span> public</li>
                   102626:                        </ul>
                   102627:        
                   102628:        <div class="method-signature">
                   102629:                <span class="method-result">void</span>
                   102630:                <span class="method-name">
                   102631:                        setMetadata
                   102632:                </span>
                   102633:                                        (<span class="var-type">string</span>&nbsp;<span class="var-name">$key</span>, <span class="var-type">mixed</span>&nbsp;<span class="var-name">$data</span>)
                   102634:                        </div>
                   102635:        
                   102636:                        <ul class="parameters">
                   102637:                                        <li>
                   102638:                                <span class="var-type">string</span>
                   102639:                                <span class="var-name">$key</span><span class="var-description">: Key</span>                    </li>
                   102640:                                        <li>
                   102641:                                <span class="var-type">mixed</span>
                   102642:                                <span class="var-name">$data</span><span class="var-description">: Data</span>                  </li>
                   102643:                                </ul>
                   102644:                
                   102645:                
                   102646:        </div>
                   102647: <a name="methodunsetMetadata" id="unsetMetadata"><!-- --></a>
                   102648: <div class="oddrow">
                   102649:        
                   102650:        <div class="method-header">
                   102651:                <span class="method-title">unsetMetadata</span> (line <span class="line-number">196</span>)
                   102652:        </div> 
                   102653:        
                   102654:        <!-- ========== Info from phpDoc block ========= -->
                   102655: <p class="short-description">Delete metadata by key</p>
                   102656: <p class="description"><p>Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an  associative array or in a dictionary. This method removes any data that might be stored under the provided key.  If the key does not exist, no error is thrown, so it is safe using this method without testing for key existence.</p></p>
                   102657:        <ul class="tags">
                   102658:                                <li><span class="field">access:</span> public</li>
                   102659:                        </ul>
                   102660:        
                   102661:        <div class="method-signature">
                   102662:                <span class="method-result">void</span>
                   102663:                <span class="method-name">
                   102664:                        unsetMetadata
                   102665:                </span>
                   102666:                                        (<span class="var-type">string</span>&nbsp;<span class="var-name">$key</span>)
                   102667:                        </div>
                   102668:        
                   102669:                        <ul class="parameters">
                   102670:                                        <li>
                   102671:                                <span class="var-type">string</span>
                   102672:                                <span class="var-name">$key</span><span class="var-description">: Key</span>                    </li>
                   102673:                                </ul>
                   102674:                
                   102675:                
                   102676:        </div>
                   102677:                                                
                   102678:                </div>
                   102679:        </div>
                   102680:        
                   102681:        <p class="notes" id="credit">
                   102682:                Documentation generated on Fri, 30 Jan 2004 16:37:29 +0000 by <a href="http://www.phpdoc.org" target="_blank">phpDocumentor 1.2.3</a>
                   102683:        </p>
                   102684:        </div></body>
                   102685: </html>Structures_Graph-1.0.4/docs/html/Structures_Graph/tutorial_Structures_Graph.pkg.html0000644000076600000240000001110611461440275030376 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   102686: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   102687:   <html xmlns="http://www.w3.org/1999/xhtml">
                   102688:                <head>
                   102689:                        <!-- template designed by Marco Von Ballmoos -->
                   102690:                        <title>Structures_Graph Tutorial</title>
                   102691:                        <link rel="stylesheet" href="../media/stylesheet.css" />
                   102692:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   102693:                </head>
                   102694:                <body>
                   102695:                        <div class="page-body">                 
                   102696: 
                   102697: <div><a name="package.database.structures_graph.tutorial"></a><div class="ref-title-box"><h1 class="ref-title">Structures_Graph Tutorial</h1>
                   102698:   <h2 class="ref-purpose">A first tour of graph datastructure manipulation</h2></div>
                   102699:  <span><a name="package.database.structures_graph.tutorial.intro"></a><h2 class="title">Introduction</h2><p>Structures_Graph is a package for creating and manipulating graph datastructures. A graph is a set of objects, called nodes, connected by arcs. When used as a datastructure, usually nodes contain data, and arcs represent relationships between nodes. When arcs have a direction, and can be travelled only one way, graphs are said to be directed. When arcs have no direction, and can always be travelled both ways, graphs are said to be non directed.</p>
                   102700:   <p>Structures_Graph provides an object oriented API to create and directly query a graph, as well as a set of Manipulator classes to extract information from the graph.</p></span>
                   102701:  <span><a name="package.database.structures_graph.tutorial.creation"></a><h2 class="title">Creating a Graph</h2><p>Creating a graph is done using the simple constructor:
                   102702:    <pre class="listing"><pre>
                   102703: require_once 'Structures/Graph.php';
                   102704: 
                   102705: $directedGraph =&amp; new Structures_Graph(true);
                   102706: $nonDirectedGraph =&amp; new Structures_Graph(false);
                   102707:     </pre></pre>
                   102708:    and passing the constructor a flag telling it whether the graph should be directed. A directed graph will always be directed during its lifetime. It's a permanent characteristic.</p>
                   102709:   <p>To fill out the graph, we'll need to create some nodes, and then call Graph::addNode.
                   102710:    <pre class="listing"><pre>
                   102711: require_once 'Structures/Graph/Node.php';
                   102712: 
                   102713: $nodeOne =&amp; new Structures_Graph_Node();
                   102714: $nodeTwo =&amp; new Structures_Graph_Node();
                   102715: $nodeThree =&amp; new Structures_Graph_Node();
                   102716: 
                   102717: $directedGraph-&gt;addNode(&amp;$nodeOne);
                   102718: $directedGraph-&gt;addNode(&amp;$nodeTwo);
                   102719: $directedGraph-&gt;addNode(&amp;$nodeThree);
                   102720:     </pre></pre>
                   102721:    and then setup the arcs:
                   102722:    <pre class="listing"><pre>
                   102723: $nodeOne-&gt;connectTo($nodeTwo);
                   102724: $nodeOne-&gt;connectTo($nodeThree);
                   102725:     </pre></pre>
                   102726:    Note that arcs can only be created after the nodes have been inserted into the graph.</p></span>
                   102727:  <span><a name="package.database.structures_graph.tutorial.nodesanddata"></a><h2 class="title">Associating Data</h2><p>Graphs are only useful as datastructures if they can hold data. Structure_Graph stores data in nodes. Each node contains a setter and a getter for its data.
                   102728:    <pre class="listing"><pre>
                   102729: $nodeOne-&gt;setData(&quot;Node One's Data is a String&quot;);
                   102730: $nodeTwo-&gt;setData(1976);
                   102731: $nodeThree-&gt;setData('Some other string');
                   102732: 
                   102733: print(&quot;NodeTwo's Data is an integer: &quot; . $nodeTwo-&gt;getData());
                   102734:     </pre></pre></p>
                   102735:   <p>Structure_Graph nodes can also store metadata, alongside with the main data. Metadata differs from regular data just because it is stored under a key, making it possible to store more than one data reference per node. The metadata getter and setter need the key to perform the operation:
                   102736:    <pre class="listing"><pre>
                   102737: $nodeOne-&gt;setMetadata('example key', &quot;Node One's Sample Metadata&quot;);
                   102738: print(&quot;Metadata stored under key 'example key' in node one: &quot; . $nodeOne-&gt;getMetadata('example key'));
                   102739: $nodeOne-&gt;unsetMetadata('example key');
                   102740:     </pre></pre></p></span>
                   102741:  <span><a name="package.database.structures_graph.tutorial.querying"></a><h2 class="title">Querying a Graph</h2><p>Structures_Graph provides for basic querying of the graph:
                   102742:    <pre class="listing"><pre>
                   102743: // Nodes are able to calculate their indegree and outdegree
                   102744: print(&quot;NodeOne's inDegree: &quot; . $nodeOne-&gt;inDegree());
                   102745: print(&quot;NodeOne's outDegree: &quot; . $nodeOne-&gt;outDegree());
                   102746: 
                   102747: // and naturally, nodes can report on their arcs
                   102748: $arcs = $nodeOne-&gt;getNeighbours();
                   102749: for ($i=0;$i&lt;sizeof($arcs);$i++) {
                   102750:     print(&quot;NodeOne has an arc to &quot; . $arcs[$i]-&gt;getData());
                   102751: }
                   102752:     </pre></pre></p></span></div>
                   102753: 
                   102754: 
                   102755:        <p class="notes" id="credit">
                   102756:                Documentation generated on Fri, 30 Jan 2004 16:37:28 +0000 by <a href="http://www.phpdoc.org" target="_blank">phpDocumentor 1.2.3</a>
                   102757:        </p>
                   102758:        </div></body>
                   102759: </html>././@LongLink000        144 0003735 LStructures_Graph-1.0.4/docs/html/Structures_Graph/_Structures_Graph_Manipulator_AcyclicTest_php.htmlStructures_Graph-1.0.4/docs/html/Structures_Graph/_Structures_Graph_Manipulator_AcyclicTest_php.html0000644000076600000240000000746211461440275033555 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   102760: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   102761:   <html xmlns="http://www.w3.org/1999/xhtml">
                   102762:                <head>
                   102763:                        <!-- template designed by Marco Von Ballmoos -->
                   102764:                        <title>Docs for page AcyclicTest.php</title>
                   102765:                        <link rel="stylesheet" href="../media/stylesheet.css" />
                   102766:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   102767:                </head>
                   102768:                <body>
                   102769:                        <div class="page-body">                 
                   102770: <h2 class="file-name">/Structures/Graph/Manipulator/AcyclicTest.php</h2>
                   102771: 
                   102772: <a name="sec-description"></a>
                   102773: <div class="info-box">
                   102774:        <div class="info-box-title">Description</div>
                   102775:        <div class="nav-bar">
                   102776:                                        <span class="disabled">Description</span> |
                   102777:                                                        <a href="#sec-classes">Classes</a>
                   102778:                        |                                                       <a href="#sec-includes">Includes</a>
                   102779:                                                                                                </div>
                   102780:        <div class="info-box-body">     
                   102781:                <!-- ========== Info from phpDoc block ========= -->
                   102782: <p class="short-description">This file contains the definition of the Structures_Graph_Manipulator_AcyclicTest graph manipulator.</p>
                   102783:        <ul class="tags">
                   102784:                                <li><span class="field">see:</span> <a href="../Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html">Structures_Graph_Manipulator_AcyclicTest</a></li>
                   102785:                        </ul>
                   102786:                
                   102787:                        </div>
                   102788: </div>
                   102789:                
                   102790:        <a name="sec-classes"></a>      
                   102791:        <div class="info-box">
                   102792:                <div class="info-box-title">Classes</div>
                   102793:                <div class="nav-bar">
                   102794:                        <a href="#sec-description">Description</a> |
                   102795:                        <span class="disabled">Classes</span>
                   102796:                        |                                                       <a href="#sec-includes">Includes</a>
                   102797:                                                                                                                                                </div>
                   102798:                <div class="info-box-body">     
                   102799:                        <table cellpadding="2" cellspacing="0" class="class-table">
                   102800:                                <tr>
                   102801:                                        <th class="class-table-header">Class</th>
                   102802:                                        <th class="class-table-header">Description</th>
                   102803:                                </tr>
                   102804:                                                                <tr>
                   102805:                                        <td style="padding-right: 2em; vertical-align: top">
                   102806:                                                <a href="../Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html">Structures_Graph_Manipulator_AcyclicTest</a>
                   102807:                                        </td>
                   102808:                                        <td>
                   102809:                                                                                        The Structures_Graph_Manipulator_AcyclicTest is a graph manipulator  which tests whether a graph contains a cycle.
                   102810:                                                                                </td>
                   102811:                                </tr>
                   102812:                                                        </table>
                   102813:                </div>
                   102814:        </div>
                   102815: 
                   102816:        <a name="sec-includes"></a>     
                   102817:        <div class="info-box">
                   102818:                <div class="info-box-title">Includes</div>
                   102819:                <div class="nav-bar">
                   102820:                        <a href="#sec-description">Description</a> |
                   102821:                                                        <a href="#sec-classes">Classes</a>
                   102822:                                |                                               <span class="disabled">Includes</span>
                   102823:                                                                                                                </div>
                   102824:                <div class="info-box-body">     
                   102825:                        <a name="_PEAR_php"><!-- --></a>
                   102826: <div class="oddrow">
                   102827:        
                   102828:        <div>
                   102829:                <span class="include-title">
                   102830:                        <span class="include-type">require_once</span>
                   102831:                        (<span class="include-name">'PEAR.php'</span>)
                   102832:                        (line <span class="line-number">35</span>)
                   102833:                </span>
                   102834:        </div>
                   102835: 
                   102836:        <!-- ========== Info from phpDoc block ========= -->
                   102837:        
                   102838: </div>
                   102839: <a name="_Structures/Graph_php"><!-- --></a>
                   102840: <div class="evenrow">
                   102841:        
                   102842:        <div>
                   102843:                <span class="include-title">
                   102844:                        <span class="include-type">require_once</span>
                   102845:                        (<span class="include-name"><a href="../Structures_Graph/_Structures_Graph_php.html">'Structures/Graph.php'</a></span>)
                   102846:                        (line <span class="line-number">37</span>)
                   102847:                </span>
                   102848:        </div>
                   102849: 
                   102850:        <!-- ========== Info from phpDoc block ========= -->
                   102851:        
                   102852: </div>
                   102853: <a name="_Structures/Graph/Node_php"><!-- --></a>
                   102854: <div class="oddrow">
                   102855:        
                   102856:        <div>
                   102857:                <span class="include-title">
                   102858:                        <span class="include-type">require_once</span>
                   102859:                        (<span class="include-name"><a href="../Structures_Graph/_Structures_Graph_Node_php.html">'Structures/Graph/Node.php'</a></span>)
                   102860:                        (line <span class="line-number">39</span>)
                   102861:                </span>
                   102862:        </div>
                   102863: 
                   102864:        <!-- ========== Info from phpDoc block ========= -->
                   102865:        
                   102866: </div>
                   102867:                </div>
                   102868:        </div>
                   102869:        
                   102870:        
                   102871:        
                   102872:        
                   102873:        <p class="notes" id="credit">
                   102874:                Documentation generated on Fri, 30 Jan 2004 16:37:28 +0000 by <a href="http://www.phpdoc.org" target="_blank">phpDocumentor 1.2.3</a>
                   102875:        </p>
                   102876:        </div></body>
                   102877: </html>././@LongLink000        152 0003734 LStructures_Graph-1.0.4/docs/html/Structures_Graph/_Structures_Graph_Manipulator_TopologicalSorter_php.htmlStructures_Graph-1.0.4/docs/html/Structures_Graph/_Structures_Graph_Manipulator_TopologicalSorter_ph0000644000076600000240000001052511461440275033670 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   102878: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   102879:   <html xmlns="http://www.w3.org/1999/xhtml">
                   102880:                <head>
                   102881:                        <!-- template designed by Marco Von Ballmoos -->
                   102882:                        <title>Docs for page TopologicalSorter.php</title>
                   102883:                        <link rel="stylesheet" href="../media/stylesheet.css" />
                   102884:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   102885:                </head>
                   102886:                <body>
                   102887:                        <div class="page-body">                 
                   102888: <h2 class="file-name">/Structures/Graph/Manipulator/TopologicalSorter.php</h2>
                   102889: 
                   102890: <a name="sec-description"></a>
                   102891: <div class="info-box">
                   102892:        <div class="info-box-title">Description</div>
                   102893:        <div class="nav-bar">
                   102894:                                        <span class="disabled">Description</span> |
                   102895:                                                        <a href="#sec-classes">Classes</a>
                   102896:                        |                                                       <a href="#sec-includes">Includes</a>
                   102897:                                                                                                </div>
                   102898:        <div class="info-box-body">     
                   102899:                <!-- ========== Info from phpDoc block ========= -->
                   102900: <p class="short-description">This file contains the definition of the Structures_Graph_Manipulator_TopologicalSorter class.</p>
                   102901:        <ul class="tags">
                   102902:                                <li><span class="field">see:</span> <a href="../Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html">Structures_Graph_Manipulator_TopologicalSorter</a></li>
                   102903:                        </ul>
                   102904:                
                   102905:                        </div>
                   102906: </div>
                   102907:                
                   102908:        <a name="sec-classes"></a>      
                   102909:        <div class="info-box">
                   102910:                <div class="info-box-title">Classes</div>
                   102911:                <div class="nav-bar">
                   102912:                        <a href="#sec-description">Description</a> |
                   102913:                        <span class="disabled">Classes</span>
                   102914:                        |                                                       <a href="#sec-includes">Includes</a>
                   102915:                                                                                                                                                </div>
                   102916:                <div class="info-box-body">     
                   102917:                        <table cellpadding="2" cellspacing="0" class="class-table">
                   102918:                                <tr>
                   102919:                                        <th class="class-table-header">Class</th>
                   102920:                                        <th class="class-table-header">Description</th>
                   102921:                                </tr>
                   102922:                                                                <tr>
                   102923:                                        <td style="padding-right: 2em; vertical-align: top">
                   102924:                                                <a href="../Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html">Structures_Graph_Manipulator_TopologicalSorter</a>
                   102925:                                        </td>
                   102926:                                        <td>
                   102927:                                                                                        The Structures_Graph_Manipulator_TopologicalSorter is a manipulator  which is able to return the set of nodes in a graph, sorted by topological  order.
                   102928:                                                                                </td>
                   102929:                                </tr>
                   102930:                                                        </table>
                   102931:                </div>
                   102932:        </div>
                   102933: 
                   102934:        <a name="sec-includes"></a>     
                   102935:        <div class="info-box">
                   102936:                <div class="info-box-title">Includes</div>
                   102937:                <div class="nav-bar">
                   102938:                        <a href="#sec-description">Description</a> |
                   102939:                                                        <a href="#sec-classes">Classes</a>
                   102940:                                |                                               <span class="disabled">Includes</span>
                   102941:                                                                                                                </div>
                   102942:                <div class="info-box-body">     
                   102943:                        <a name="_PEAR_php"><!-- --></a>
                   102944: <div class="oddrow">
                   102945:        
                   102946:        <div>
                   102947:                <span class="include-title">
                   102948:                        <span class="include-type">require_once</span>
                   102949:                        (<span class="include-name">'PEAR.php'</span>)
                   102950:                        (line <span class="line-number">35</span>)
                   102951:                </span>
                   102952:        </div>
                   102953: 
                   102954:        <!-- ========== Info from phpDoc block ========= -->
                   102955:        
                   102956: </div>
                   102957: <a name="_Structures/Graph_php"><!-- --></a>
                   102958: <div class="evenrow">
                   102959:        
                   102960:        <div>
                   102961:                <span class="include-title">
                   102962:                        <span class="include-type">require_once</span>
                   102963:                        (<span class="include-name"><a href="../Structures_Graph/_Structures_Graph_php.html">'Structures/Graph.php'</a></span>)
                   102964:                        (line <span class="line-number">37</span>)
                   102965:                </span>
                   102966:        </div>
                   102967: 
                   102968:        <!-- ========== Info from phpDoc block ========= -->
                   102969:        
                   102970: </div>
                   102971: <a name="_Structures/Graph/Node_php"><!-- --></a>
                   102972: <div class="oddrow">
                   102973:        
                   102974:        <div>
                   102975:                <span class="include-title">
                   102976:                        <span class="include-type">require_once</span>
                   102977:                        (<span class="include-name"><a href="../Structures_Graph/_Structures_Graph_Node_php.html">'Structures/Graph/Node.php'</a></span>)
                   102978:                        (line <span class="line-number">39</span>)
                   102979:                </span>
                   102980:        </div>
                   102981: 
                   102982:        <!-- ========== Info from phpDoc block ========= -->
                   102983:        
                   102984: </div>
                   102985: <a name="_Structures/Graph/Manipulator/AcyclicTest_php"><!-- --></a>
                   102986: <div class="evenrow">
                   102987:        
                   102988:        <div>
                   102989:                <span class="include-title">
                   102990:                        <span class="include-type">require_once</span>
                   102991:                        (<span class="include-name"><a href="../Structures_Graph/_Structures_Graph_Manipulator_AcyclicTest_php.html">'Structures/Graph/Manipulator/AcyclicTest.php'</a></span>)
                   102992:                        (line <span class="line-number">41</span>)
                   102993:                </span>
                   102994:        </div>
                   102995: 
                   102996:        <!-- ========== Info from phpDoc block ========= -->
                   102997:        
                   102998: </div>
                   102999:                </div>
                   103000:        </div>
                   103001:        
                   103002:        
                   103003:        
                   103004:        
                   103005:        <p class="notes" id="credit">
                   103006:                Documentation generated on Fri, 30 Jan 2004 16:37:29 +0000 by <a href="http://www.phpdoc.org" target="_blank">phpDocumentor 1.2.3</a>
                   103007:        </p>
                   103008:        </div></body>
                   103009: </html>Structures_Graph-1.0.4/docs/html/Structures_Graph/_Structures_Graph_Node_php.html0000644000076600000240000000635611461440275027661 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   103010: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   103011:   <html xmlns="http://www.w3.org/1999/xhtml">
                   103012:                <head>
                   103013:                        <!-- template designed by Marco Von Ballmoos -->
                   103014:                        <title>Docs for page Node.php</title>
                   103015:                        <link rel="stylesheet" href="../media/stylesheet.css" />
                   103016:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   103017:                </head>
                   103018:                <body>
                   103019:                        <div class="page-body">                 
                   103020: <h2 class="file-name">/Structures/Graph/Node.php</h2>
                   103021: 
                   103022: <a name="sec-description"></a>
                   103023: <div class="info-box">
                   103024:        <div class="info-box-title">Description</div>
                   103025:        <div class="nav-bar">
                   103026:                                        <span class="disabled">Description</span> |
                   103027:                                                        <a href="#sec-classes">Classes</a>
                   103028:                        |                                                       <a href="#sec-includes">Includes</a>
                   103029:                                                                                                </div>
                   103030:        <div class="info-box-body">     
                   103031:                <!-- ========== Info from phpDoc block ========= -->
                   103032: <p class="short-description">This file contains the definition of the Structures_Graph_Node class</p>
                   103033:        <ul class="tags">
                   103034:                                <li><span class="field">see:</span> <a href="../Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a></li>
                   103035:                        </ul>
                   103036:                
                   103037:                        </div>
                   103038: </div>
                   103039:                
                   103040:        <a name="sec-classes"></a>      
                   103041:        <div class="info-box">
                   103042:                <div class="info-box-title">Classes</div>
                   103043:                <div class="nav-bar">
                   103044:                        <a href="#sec-description">Description</a> |
                   103045:                        <span class="disabled">Classes</span>
                   103046:                        |                                                       <a href="#sec-includes">Includes</a>
                   103047:                                                                                                                                                </div>
                   103048:                <div class="info-box-body">     
                   103049:                        <table cellpadding="2" cellspacing="0" class="class-table">
                   103050:                                <tr>
                   103051:                                        <th class="class-table-header">Class</th>
                   103052:                                        <th class="class-table-header">Description</th>
                   103053:                                </tr>
                   103054:                                                                <tr>
                   103055:                                        <td style="padding-right: 2em; vertical-align: top">
                   103056:                                                <a href="../Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a>
                   103057:                                        </td>
                   103058:                                        <td>
                   103059:                                                                                        The Structures_Graph_Node class represents a Node that can be member of a  graph node set.
                   103060:                                                                                </td>
                   103061:                                </tr>
                   103062:                                                        </table>
                   103063:                </div>
                   103064:        </div>
                   103065: 
                   103066:        <a name="sec-includes"></a>     
                   103067:        <div class="info-box">
                   103068:                <div class="info-box-title">Includes</div>
                   103069:                <div class="nav-bar">
                   103070:                        <a href="#sec-description">Description</a> |
                   103071:                                                        <a href="#sec-classes">Classes</a>
                   103072:                                |                                               <span class="disabled">Includes</span>
                   103073:                                                                                                                </div>
                   103074:                <div class="info-box-body">     
                   103075:                        <a name="_PEAR_php"><!-- --></a>
                   103076: <div class="evenrow">
                   103077:        
                   103078:        <div>
                   103079:                <span class="include-title">
                   103080:                        <span class="include-type">require_once</span>
                   103081:                        (<span class="include-name">'PEAR.php'</span>)
                   103082:                        (line <span class="line-number">35</span>)
                   103083:                </span>
                   103084:        </div>
                   103085: 
                   103086:        <!-- ========== Info from phpDoc block ========= -->
                   103087:        
                   103088: </div>
                   103089: <a name="_Structures/Graph_php"><!-- --></a>
                   103090: <div class="oddrow">
                   103091:        
                   103092:        <div>
                   103093:                <span class="include-title">
                   103094:                        <span class="include-type">require_once</span>
                   103095:                        (<span class="include-name"><a href="../Structures_Graph/_Structures_Graph_php.html">'Structures/Graph.php'</a></span>)
                   103096:                        (line <span class="line-number">37</span>)
                   103097:                </span>
                   103098:        </div>
                   103099: 
                   103100:        <!-- ========== Info from phpDoc block ========= -->
                   103101:        
                   103102: </div>
                   103103:                </div>
                   103104:        </div>
                   103105:        
                   103106:        
                   103107:        
                   103108:        
                   103109:        <p class="notes" id="credit">
                   103110:                Documentation generated on Fri, 30 Jan 2004 16:37:29 +0000 by <a href="http://www.phpdoc.org" target="_blank">phpDocumentor 1.2.3</a>
                   103111:        </p>
                   103112:        </div></body>
                   103113: </html>Structures_Graph-1.0.4/docs/html/Structures_Graph/_Structures_Graph_php.html0000644000076600000240000001020711461440275026702 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   103114: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   103115:   <html xmlns="http://www.w3.org/1999/xhtml">
                   103116:                <head>
                   103117:                        <!-- template designed by Marco Von Ballmoos -->
                   103118:                        <title>Docs for page Graph.php</title>
                   103119:                        <link rel="stylesheet" href="../media/stylesheet.css" />
                   103120:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   103121:                </head>
                   103122:                <body>
                   103123:                        <div class="page-body">                 
                   103124: <h2 class="file-name">/Structures/Graph.php</h2>
                   103125: 
                   103126: <a name="sec-description"></a>
                   103127: <div class="info-box">
                   103128:        <div class="info-box-title">Description</div>
                   103129:        <div class="nav-bar">
                   103130:                                        <span class="disabled">Description</span> |
                   103131:                                                        <a href="#sec-classes">Classes</a>
                   103132:                        |                                                       <a href="#sec-includes">Includes</a>
                   103133:                        |                                                       <a href="#sec-constants">Constants</a>
                   103134:                                                                                </div>
                   103135:        <div class="info-box-body">     
                   103136:                <!-- ========== Info from phpDoc block ========= -->
                   103137: <p class="short-description">The Graph.php file contains the definition of the Structures_Graph class</p>
                   103138:        <ul class="tags">
                   103139:                                <li><span class="field">see:</span> <a href="../Structures_Graph/Structures_Graph.html">Structures_Graph</a></li>
                   103140:                        </ul>
                   103141:                
                   103142:                        </div>
                   103143: </div>
                   103144:                
                   103145:        <a name="sec-classes"></a>      
                   103146:        <div class="info-box">
                   103147:                <div class="info-box-title">Classes</div>
                   103148:                <div class="nav-bar">
                   103149:                        <a href="#sec-description">Description</a> |
                   103150:                        <span class="disabled">Classes</span>
                   103151:                        |                                                       <a href="#sec-includes">Includes</a>
                   103152:                                |                                                                               <a href="#sec-constants">Constants</a>
                   103153:                                                                                                                        </div>
                   103154:                <div class="info-box-body">     
                   103155:                        <table cellpadding="2" cellspacing="0" class="class-table">
                   103156:                                <tr>
                   103157:                                        <th class="class-table-header">Class</th>
                   103158:                                        <th class="class-table-header">Description</th>
                   103159:                                </tr>
                   103160:                                                                <tr>
                   103161:                                        <td style="padding-right: 2em; vertical-align: top">
                   103162:                                                <a href="../Structures_Graph/Structures_Graph.html">Structures_Graph</a>
                   103163:                                        </td>
                   103164:                                        <td>
                   103165:                                                                                        The Structures_Graph class represents a graph data structure.
                   103166:                                                                                </td>
                   103167:                                </tr>
                   103168:                                                        </table>
                   103169:                </div>
                   103170:        </div>
                   103171: 
                   103172:        <a name="sec-includes"></a>     
                   103173:        <div class="info-box">
                   103174:                <div class="info-box-title">Includes</div>
                   103175:                <div class="nav-bar">
                   103176:                        <a href="#sec-description">Description</a> |
                   103177:                                                        <a href="#sec-classes">Classes</a>
                   103178:                                |                                               <span class="disabled">Includes</span>
                   103179:                        |                                                       <a href="#sec-constants">Constants</a>
                   103180:                                                                                                                        </div>
                   103181:                <div class="info-box-body">     
                   103182:                        <a name="_Structures/Graph/Node_php"><!-- --></a>
                   103183: <div class="oddrow">
                   103184:        
                   103185:        <div>
                   103186:                <span class="include-title">
                   103187:                        <span class="include-type">require_once</span>
                   103188:                        (<span class="include-name"><a href="../Structures_Graph/_Structures_Graph_Node_php.html">'Structures/Graph/Node.php'</a></span>)
                   103189:                        (line <span class="line-number">37</span>)
                   103190:                </span>
                   103191:        </div>
                   103192: 
                   103193:        <!-- ========== Info from phpDoc block ========= -->
                   103194: <p class="short-description">Graph Node</p>
                   103195:        
                   103196: </div>
                   103197: <a name="_PEAR_php"><!-- --></a>
                   103198: <div class="evenrow">
                   103199:        
                   103200:        <div>
                   103201:                <span class="include-title">
                   103202:                        <span class="include-type">require_once</span>
                   103203:                        (<span class="include-name">'PEAR.php'</span>)
                   103204:                        (line <span class="line-number">35</span>)
                   103205:                </span>
                   103206:        </div>
                   103207: 
                   103208:        <!-- ========== Info from phpDoc block ========= -->
                   103209: <p class="short-description">PEAR base classes</p>
                   103210:        
                   103211: </div>
                   103212:                </div>
                   103213:        </div>
                   103214:        
                   103215:        <a name="sec-constants"></a>    
                   103216:        <div class="info-box">
                   103217:                <div class="info-box-title">Constants</div>
                   103218:                <div class="nav-bar">
                   103219:                        <a href="#sec-description">Description</a> |
                   103220:                                                        <a href="#sec-classes">Classes</a>
                   103221:                                |                                                                               <a href="#sec-includes">Includes</a>
                   103222:                                |                                               <span class="disabled">Constants</span>
                   103223:                                                                                        </div>
                   103224:                <div class="info-box-body">     
                   103225:                        <a name="defineSTRUCTURES_GRAPH_ERROR_GENERIC"><!-- --></a>
                   103226: <div class="oddrow">
                   103227:        
                   103228:        <div>
                   103229:                <span class="const-title">
                   103230:                        <span class="const-name">STRUCTURES_GRAPH_ERROR_GENERIC</span> = 100
                   103231:                        (line <span class="line-number">40</span>)
                   103232:                </span>
                   103233:        </div>
                   103234:        
                   103235:        <!-- ========== Info from phpDoc block ========= -->
                   103236:        
                   103237:                
                   103238: </div>
                   103239:                </div>
                   103240:        </div>
                   103241:        
                   103242:        
                   103243:        
                   103244:        <p class="notes" id="credit">
                   103245:                Documentation generated on Fri, 30 Jan 2004 16:37:28 +0000 by <a href="http://www.phpdoc.org" target="_blank">phpDocumentor 1.2.3</a>
                   103246:        </p>
                   103247:        </div></body>
                   103248: </html>Structures_Graph-1.0.4/docs/html/classtrees_Structures_Graph.html0000644000076600000240000000253011461440275024620 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   103249: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   103250:   <html xmlns="http://www.w3.org/1999/xhtml">
                   103251:                <head>
                   103252:                        <!-- template designed by Marco Von Ballmoos -->
                   103253:                        <title></title>
                   103254:                        <link rel="stylesheet" href="media/stylesheet.css" />
                   103255:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   103256:                </head>
                   103257:                <body>
                   103258:                                                
                   103259: <!-- Start of Class Data -->
                   103260: <H2>
                   103261:        
                   103262: </H2>
                   103263: <h2>Root class Structures_Graph</h2>
                   103264: <ul>
                   103265: <li><a href="Structures_Graph/Structures_Graph.html">Structures_Graph</a></li></ul>
                   103266: 
                   103267: <h2>Root class Structures_Graph_Manipulator_AcyclicTest</h2>
                   103268: <ul>
                   103269: <li><a href="Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html">Structures_Graph_Manipulator_AcyclicTest</a></li></ul>
                   103270: 
                   103271: <h2>Root class Structures_Graph_Manipulator_TopologicalSorter</h2>
                   103272: <ul>
                   103273: <li><a href="Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html">Structures_Graph_Manipulator_TopologicalSorter</a></li></ul>
                   103274: 
                   103275: <h2>Root class Structures_Graph_Node</h2>
                   103276: <ul>
                   103277: <li><a href="Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a></li></ul>
                   103278: 
                   103279:        <p class="notes" id="credit">
                   103280:                Documentation generated on Fri, 30 Jan 2004 16:37:28 +0000 by <a href="http://www.phpdoc.org" target="_blank">phpDocumentor 1.2.3</a>
                   103281:        </p>
                   103282:        </body>
                   103283: </html>Structures_Graph-1.0.4/docs/html/elementindex.html0000644000076600000240000003640711461440275021557 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   103284: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   103285:   <html xmlns="http://www.w3.org/1999/xhtml">
                   103286:                <head>
                   103287:                        <!-- template designed by Marco Von Ballmoos -->
                   103288:                        <title></title>
                   103289:                        <link rel="stylesheet" href="media/stylesheet.css" />
                   103290:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   103291:                </head>
                   103292:                <body>
                   103293:                                                <a name="top"></a>
                   103294: <h2>Full index</h2>
                   103295: <h3>Package indexes</h3>
                   103296: <ul>
                   103297:        <li><a href="elementindex_Structures_Graph.html">Structures_Graph</a></li>
                   103298: </ul>
                   103299: <br />
                   103300: <div class="index-letter-menu">
                   103301:        <a class="index-letter" href="elementindex.html#a">a</a>
                   103302:        <a class="index-letter" href="elementindex.html#c">c</a>
                   103303:        <a class="index-letter" href="elementindex.html#g">g</a>
                   103304:        <a class="index-letter" href="elementindex.html#i">i</a>
                   103305:        <a class="index-letter" href="elementindex.html#m">m</a>
                   103306:        <a class="index-letter" href="elementindex.html#n">n</a>
                   103307:        <a class="index-letter" href="elementindex.html#o">o</a>
                   103308:        <a class="index-letter" href="elementindex.html#r">r</a>
                   103309:        <a class="index-letter" href="elementindex.html#s">s</a>
                   103310:        <a class="index-letter" href="elementindex.html#t">t</a>
                   103311:        <a class="index-letter" href="elementindex.html#u">u</a>
                   103312: </div>
                   103313: 
                   103314:        <a name="a"></a>
                   103315:        <div class="index-letter-section">
                   103316:                <div style="float: left" class="index-letter-title">a</div>
                   103317:                <div style="float: right"><a href="#top">top</a></div>
                   103318:                <div style="clear: both"></div>
                   103319:        </div>
                   103320:        <dl>
                   103321:                        <dt class="field">
                   103322:                                                <span class="method-title">addNode</span>
                   103323:                                        </dt>
                   103324:                <dd class="index-item-body">
                   103325:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html#methodaddNode">Structures_Graph::addNode()</a> in Graph.php</div>
                   103326:                                                        <div class="index-item-description">Add a Node to the Graph</div>
                   103327:                                        </dd>
                   103328:                        <dt class="field">
                   103329:                                                <span class="include-title">AcyclicTest.php</span>
                   103330:                                        </dt>
                   103331:                <dd class="index-item-body">
                   103332:                        <div class="index-item-details"><a href="Structures_Graph/_Structures_Graph_Manipulator_AcyclicTest_php.html">AcyclicTest.php</a> in AcyclicTest.php</div>
                   103333:                                        </dd>
                   103334:                </dl>
                   103335:        <a name="c"></a>
                   103336:        <div class="index-letter-section">
                   103337:                <div style="float: left" class="index-letter-title">c</div>
                   103338:                <div style="float: right"><a href="#top">top</a></div>
                   103339:                <div style="clear: both"></div>
                   103340:        </div>
                   103341:        <dl>
                   103342:                        <dt class="field">
                   103343:                                                <span class="method-title">connectsTo</span>
                   103344:                                        </dt>
                   103345:                <dd class="index-item-body">
                   103346:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodconnectsTo">Structures_Graph_Node::connectsTo()</a> in Node.php</div>
                   103347:                                                        <div class="index-item-description">Test wether this node has an arc to the target node</div>
                   103348:                                        </dd>
                   103349:                        <dt class="field">
                   103350:                                                <span class="method-title">connectTo</span>
                   103351:                                        </dt>
                   103352:                <dd class="index-item-body">
                   103353:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodconnectTo">Structures_Graph_Node::connectTo()</a> in Node.php</div>
                   103354:                                                        <div class="index-item-description">Connect this node to another one.</div>
                   103355:                                        </dd>
                   103356:                </dl>
                   103357:        <a name="g"></a>
                   103358:        <div class="index-letter-section">
                   103359:                <div style="float: left" class="index-letter-title">g</div>
                   103360:                <div style="float: right"><a href="#top">top</a></div>
                   103361:                <div style="clear: both"></div>
                   103362:        </div>
                   103363:        <dl>
                   103364:                        <dt class="field">
                   103365:                                                <span class="method-title">getData</span>
                   103366:                                        </dt>
                   103367:                <dd class="index-item-body">
                   103368:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodgetData">Structures_Graph_Node::getData()</a> in Node.php</div>
                   103369:                                                        <div class="index-item-description">Node data getter.</div>
                   103370:                                        </dd>
                   103371:                        <dt class="field">
                   103372:                                                <span class="method-title">getGraph</span>
                   103373:                                        </dt>
                   103374:                <dd class="index-item-body">
                   103375:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodgetGraph">Structures_Graph_Node::getGraph()</a> in Node.php</div>
                   103376:                                                        <div class="index-item-description">Node graph getter</div>
                   103377:                                        </dd>
                   103378:                        <dt class="field">
                   103379:                                                <span class="method-title">getMetadata</span>
                   103380:                                        </dt>
                   103381:                <dd class="index-item-body">
                   103382:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodgetMetadata">Structures_Graph_Node::getMetadata()</a> in Node.php</div>
                   103383:                                                        <div class="index-item-description">Node metadata getter</div>
                   103384:                                        </dd>
                   103385:                        <dt class="field">
                   103386:                                                <span class="method-title">getNeighbours</span>
                   103387:                                        </dt>
                   103388:                <dd class="index-item-body">
                   103389:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodgetNeighbours">Structures_Graph_Node::getNeighbours()</a> in Node.php</div>
                   103390:                                                        <div class="index-item-description">Return nodes connected to this one.</div>
                   103391:                                        </dd>
                   103392:                        <dt class="field">
                   103393:                                                <span class="method-title">getNodes</span>
                   103394:                                        </dt>
                   103395:                <dd class="index-item-body">
                   103396:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html#methodgetNodes">Structures_Graph::getNodes()</a> in Graph.php</div>
                   103397:                                                        <div class="index-item-description">Return the node set, in no particular order. For ordered node sets, use a Graph Manipulator insted.</div>
                   103398:                                        </dd>
                   103399:                        <dt class="field">
                   103400:                                                <span class="include-title">Graph.php</span>
                   103401:                                        </dt>
                   103402:                <dd class="index-item-body">
                   103403:                        <div class="index-item-details"><a href="Structures_Graph/_Structures_Graph_php.html">Graph.php</a> in Graph.php</div>
                   103404:                                        </dd>
                   103405:                </dl>
                   103406:        <a name="i"></a>
                   103407:        <div class="index-letter-section">
                   103408:                <div style="float: left" class="index-letter-title">i</div>
                   103409:                <div style="float: right"><a href="#top">top</a></div>
                   103410:                <div style="clear: both"></div>
                   103411:        </div>
                   103412:        <dl>
                   103413:                        <dt class="field">
                   103414:                                                <span class="method-title">inDegree</span>
                   103415:                                        </dt>
                   103416:                <dd class="index-item-body">
                   103417:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodinDegree">Structures_Graph_Node::inDegree()</a> in Node.php</div>
                   103418:                                                        <div class="index-item-description">Calculate the in degree of the node.</div>
                   103419:                                        </dd>
                   103420:                        <dt class="field">
                   103421:                                                <span class="method-title">isAcyclic</span>
                   103422:                                        </dt>
                   103423:                <dd class="index-item-body">
                   103424:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html#methodisAcyclic">Structures_Graph_Manipulator_AcyclicTest::isAcyclic()</a> in AcyclicTest.php</div>
                   103425:                                                        <div class="index-item-description">isAcyclic returns true if a graph contains no cycles, false otherwise.</div>
                   103426:                                        </dd>
                   103427:                        <dt class="field">
                   103428:                                                <span class="method-title">isDirected</span>
                   103429:                                        </dt>
                   103430:                <dd class="index-item-body">
                   103431:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html#methodisDirected">Structures_Graph::isDirected()</a> in Graph.php</div>
                   103432:                                                        <div class="index-item-description">Return true if a graph is directed</div>
                   103433:                                        </dd>
                   103434:                </dl>
                   103435:        <a name="m"></a>
                   103436:        <div class="index-letter-section">
                   103437:                <div style="float: left" class="index-letter-title">m</div>
                   103438:                <div style="float: right"><a href="#top">top</a></div>
                   103439:                <div style="clear: both"></div>
                   103440:        </div>
                   103441:        <dl>
                   103442:                        <dt class="field">
                   103443:                                                <span class="method-title">metadataKeyExists</span>
                   103444:                                        </dt>
                   103445:                <dd class="index-item-body">
                   103446:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodmetadataKeyExists">Structures_Graph_Node::metadataKeyExists()</a> in Node.php</div>
                   103447:                                                        <div class="index-item-description">Test for existence of metadata under a given key.</div>
                   103448:                                        </dd>
                   103449:                </dl>
                   103450:        <a name="n"></a>
                   103451:        <div class="index-letter-section">
                   103452:                <div style="float: left" class="index-letter-title">n</div>
                   103453:                <div style="float: right"><a href="#top">top</a></div>
                   103454:                <div style="clear: both"></div>
                   103455:        </div>
                   103456:        <dl>
                   103457:                        <dt class="field">
                   103458:                                                <span class="include-title">Node.php</span>
                   103459:                                        </dt>
                   103460:                <dd class="index-item-body">
                   103461:                        <div class="index-item-details"><a href="Structures_Graph/_Structures_Graph_Node_php.html">Node.php</a> in Node.php</div>
                   103462:                                        </dd>
                   103463:                </dl>
                   103464:        <a name="o"></a>
                   103465:        <div class="index-letter-section">
                   103466:                <div style="float: left" class="index-letter-title">o</div>
                   103467:                <div style="float: right"><a href="#top">top</a></div>
                   103468:                <div style="clear: both"></div>
                   103469:        </div>
                   103470:        <dl>
                   103471:                        <dt class="field">
                   103472:                                                <span class="method-title">outDegree</span>
                   103473:                                        </dt>
                   103474:                <dd class="index-item-body">
                   103475:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodoutDegree">Structures_Graph_Node::outDegree()</a> in Node.php</div>
                   103476:                                                        <div class="index-item-description">Calculate the out degree of the node.</div>
                   103477:                                        </dd>
                   103478:                </dl>
                   103479:        <a name="r"></a>
                   103480:        <div class="index-letter-section">
                   103481:                <div style="float: left" class="index-letter-title">r</div>
                   103482:                <div style="float: right"><a href="#top">top</a></div>
                   103483:                <div style="clear: both"></div>
                   103484:        </div>
                   103485:        <dl>
                   103486:                        <dt class="field">
                   103487:                                                <span class="method-title">removeNode</span>
                   103488:                                        </dt>
                   103489:                <dd class="index-item-body">
                   103490:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html#methodremoveNode">Structures_Graph::removeNode()</a> in Graph.php</div>
                   103491:                                                        <div class="index-item-description">Remove a Node from the Graph</div>
                   103492:                                        </dd>
                   103493:                </dl>
                   103494:        <a name="s"></a>
                   103495:        <div class="index-letter-section">
                   103496:                <div style="float: left" class="index-letter-title">s</div>
                   103497:                <div style="float: right"><a href="#top">top</a></div>
                   103498:                <div style="clear: both"></div>
                   103499:        </div>
                   103500:        <dl>
                   103501:                        <dt class="field">
                   103502:                                                <span class="method-title">setData</span>
                   103503:                                        </dt>
                   103504:                <dd class="index-item-body">
                   103505:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodsetData">Structures_Graph_Node::setData()</a> in Node.php</div>
                   103506:                                                        <div class="index-item-description">Node data setter</div>
                   103507:                                        </dd>
                   103508:                        <dt class="field">
                   103509:                                                <span class="method-title">setGraph</span>
                   103510:                                        </dt>
                   103511:                <dd class="index-item-body">
                   103512:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodsetGraph">Structures_Graph_Node::setGraph()</a> in Node.php</div>
                   103513:                                                        <div class="index-item-description">Node graph setter. This method should not be called directly. Use Graph::addNode instead.</div>
                   103514:                                        </dd>
                   103515:                        <dt class="field">
                   103516:                                                <span class="method-title">setMetadata</span>
                   103517:                                        </dt>
                   103518:                <dd class="index-item-body">
                   103519:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodsetMetadata">Structures_Graph_Node::setMetadata()</a> in Node.php</div>
                   103520:                                                        <div class="index-item-description">Node metadata setter</div>
                   103521:                                        </dd>
                   103522:                        <dt class="field">
                   103523:                                                <span class="method-title">sort</span>
                   103524:                                        </dt>
                   103525:                <dd class="index-item-body">
                   103526:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html#methodsort">Structures_Graph_Manipulator_TopologicalSorter::sort()</a> in TopologicalSorter.php</div>
                   103527:                                                        <div class="index-item-description">sort returns the graph's nodes, sorted by topological order.</div>
                   103528:                                        </dd>
                   103529:                        <dt class="field">
                   103530:                                                Structures_Graph
                   103531:                                        </dt>
                   103532:                <dd class="index-item-body">
                   103533:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html">Structures_Graph</a> in Graph.php</div>
                   103534:                                                        <div class="index-item-description">The Structures_Graph class represents a graph data structure.</div>
                   103535:                                        </dd>
                   103536:                        <dt class="field">
                   103537:                                                <span class="method-title">Structures_Graph</span>
                   103538:                                        </dt>
                   103539:                <dd class="index-item-body">
                   103540:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html#methodStructures_Graph">Structures_Graph::Structures_Graph()</a> in Graph.php</div>
                   103541:                                                        <div class="index-item-description">Constructor</div>
                   103542:                                        </dd>
                   103543:                        <dt class="field">
                   103544:                                                <span class="const-title">STRUCTURES_GRAPH_ERROR_GENERIC</span>
                   103545:                                        </dt>
                   103546:                <dd class="index-item-body">
                   103547:                        <div class="index-item-details"><a href="Structures_Graph/_Structures_Graph_php.html#defineSTRUCTURES_GRAPH_ERROR_GENERIC">STRUCTURES_GRAPH_ERROR_GENERIC</a> in Graph.php</div>
                   103548:                                        </dd>
                   103549:                        <dt class="field">
                   103550:                                                Structures_Graph_Manipulator_AcyclicTest
                   103551:                                        </dt>
                   103552:                <dd class="index-item-body">
                   103553:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html">Structures_Graph_Manipulator_AcyclicTest</a> in AcyclicTest.php</div>
                   103554:                                                        <div class="index-item-description">The Structures_Graph_Manipulator_AcyclicTest is a graph manipulator  which tests whether a graph contains a cycle.</div>
                   103555:                                        </dd>
                   103556:                        <dt class="field">
                   103557:                                                Structures_Graph_Manipulator_TopologicalSorter
                   103558:                                        </dt>
                   103559:                <dd class="index-item-body">
                   103560:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html">Structures_Graph_Manipulator_TopologicalSorter</a> in TopologicalSorter.php</div>
                   103561:                                                        <div class="index-item-description">The Structures_Graph_Manipulator_TopologicalSorter is a manipulator  which is able to return the set of nodes in a graph, sorted by topological  order.</div>
                   103562:                                        </dd>
                   103563:                        <dt class="field">
                   103564:                                                <span class="method-title">Structures_Graph_Node</span>
                   103565:                                        </dt>
                   103566:                <dd class="index-item-body">
                   103567:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodStructures_Graph_Node">Structures_Graph_Node::Structures_Graph_Node()</a> in Node.php</div>
                   103568:                                                        <div class="index-item-description">Constructor</div>
                   103569:                                        </dd>
                   103570:                        <dt class="field">
                   103571:                                                Structures_Graph_Node
                   103572:                                        </dt>
                   103573:                <dd class="index-item-body">
                   103574:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a> in Node.php</div>
                   103575:                                                        <div class="index-item-description">The Structures_Graph_Node class represents a Node that can be member of a  graph node set.</div>
                   103576:                                        </dd>
                   103577:                </dl>
                   103578:        <a name="t"></a>
                   103579:        <div class="index-letter-section">
                   103580:                <div style="float: left" class="index-letter-title">t</div>
                   103581:                <div style="float: right"><a href="#top">top</a></div>
                   103582:                <div style="clear: both"></div>
                   103583:        </div>
                   103584:        <dl>
                   103585:                        <dt class="field">
                   103586:                                                <span class="include-title">TopologicalSorter.php</span>
                   103587:                                        </dt>
                   103588:                <dd class="index-item-body">
                   103589:                        <div class="index-item-details"><a href="Structures_Graph/_Structures_Graph_Manipulator_TopologicalSorter_php.html">TopologicalSorter.php</a> in TopologicalSorter.php</div>
                   103590:                                        </dd>
                   103591:                </dl>
                   103592:        <a name="u"></a>
                   103593:        <div class="index-letter-section">
                   103594:                <div style="float: left" class="index-letter-title">u</div>
                   103595:                <div style="float: right"><a href="#top">top</a></div>
                   103596:                <div style="clear: both"></div>
                   103597:        </div>
                   103598:        <dl>
                   103599:                        <dt class="field">
                   103600:                                                <span class="method-title">unsetMetadata</span>
                   103601:                                        </dt>
                   103602:                <dd class="index-item-body">
                   103603:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodunsetMetadata">Structures_Graph_Node::unsetMetadata()</a> in Node.php</div>
                   103604:                                                        <div class="index-item-description">Delete metadata by key</div>
                   103605:                                        </dd>
                   103606:                </dl>
                   103607: 
                   103608: <div class="index-letter-menu">
                   103609:        <a class="index-letter" href="elementindex.html#a">a</a>
                   103610:        <a class="index-letter" href="elementindex.html#c">c</a>
                   103611:        <a class="index-letter" href="elementindex.html#g">g</a>
                   103612:        <a class="index-letter" href="elementindex.html#i">i</a>
                   103613:        <a class="index-letter" href="elementindex.html#m">m</a>
                   103614:        <a class="index-letter" href="elementindex.html#n">n</a>
                   103615:        <a class="index-letter" href="elementindex.html#o">o</a>
                   103616:        <a class="index-letter" href="elementindex.html#r">r</a>
                   103617:        <a class="index-letter" href="elementindex.html#s">s</a>
                   103618:        <a class="index-letter" href="elementindex.html#t">t</a>
                   103619:        <a class="index-letter" href="elementindex.html#u">u</a>
                   103620: </div> </body>
                   103621: </html>Structures_Graph-1.0.4/docs/html/elementindex_Structures_Graph.html0000644000076600000240000003712011461440275025134 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   103622: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   103623:   <html xmlns="http://www.w3.org/1999/xhtml">
                   103624:                <head>
                   103625:                        <!-- template designed by Marco Von Ballmoos -->
                   103626:                        <title></title>
                   103627:                        <link rel="stylesheet" href="media/stylesheet.css" />
                   103628:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   103629:                </head>
                   103630:                <body>
                   103631:                                                <a name="top"></a>
                   103632: <h2>[Structures_Graph] element index</h2>
                   103633: <a href="elementindex.html">All elements</a>
                   103634: <br />
                   103635: <div class="index-letter-menu">
                   103636:        <a class="index-letter" href="elementindex_Structures_Graph.html#a">a</a>
                   103637:        <a class="index-letter" href="elementindex_Structures_Graph.html#c">c</a>
                   103638:        <a class="index-letter" href="elementindex_Structures_Graph.html#g">g</a>
                   103639:        <a class="index-letter" href="elementindex_Structures_Graph.html#i">i</a>
                   103640:        <a class="index-letter" href="elementindex_Structures_Graph.html#m">m</a>
                   103641:        <a class="index-letter" href="elementindex_Structures_Graph.html#n">n</a>
                   103642:        <a class="index-letter" href="elementindex_Structures_Graph.html#o">o</a>
                   103643:        <a class="index-letter" href="elementindex_Structures_Graph.html#r">r</a>
                   103644:        <a class="index-letter" href="elementindex_Structures_Graph.html#s">s</a>
                   103645:        <a class="index-letter" href="elementindex_Structures_Graph.html#t">t</a>
                   103646:        <a class="index-letter" href="elementindex_Structures_Graph.html#u">u</a>
                   103647: </div>
                   103648: 
                   103649:        <a name="a"></a>
                   103650:        <div class="index-letter-section">
                   103651:                <div style="float: left" class="index-letter-title">a</div>
                   103652:                <div style="float: right"><a href="#top">top</a></div>
                   103653:                <div style="clear: both"></div>
                   103654:        </div>
                   103655:        <dl>
                   103656:                        <dt class="field">
                   103657:                                                <span class="method-title">addNode</span>
                   103658:                                        </dt>
                   103659:                <dd class="index-item-body">
                   103660:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html#methodaddNode">Structures_Graph::addNode()</a> in Graph.php</div>
                   103661:                                                        <div class="index-item-description">Add a Node to the Graph</div>
                   103662:                                        </dd>
                   103663:                        <dt class="field">
                   103664:                                                <span class="include-title">AcyclicTest.php</span>
                   103665:                                        </dt>
                   103666:                <dd class="index-item-body">
                   103667:                        <div class="index-item-details"><a href="Structures_Graph/_Structures_Graph_Manipulator_AcyclicTest_php.html">AcyclicTest.php</a> in AcyclicTest.php</div>
                   103668:                                        </dd>
                   103669:                </dl>
                   103670:        <a name="c"></a>
                   103671:        <div class="index-letter-section">
                   103672:                <div style="float: left" class="index-letter-title">c</div>
                   103673:                <div style="float: right"><a href="#top">top</a></div>
                   103674:                <div style="clear: both"></div>
                   103675:        </div>
                   103676:        <dl>
                   103677:                        <dt class="field">
                   103678:                                                <span class="method-title">connectsTo</span>
                   103679:                                        </dt>
                   103680:                <dd class="index-item-body">
                   103681:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodconnectsTo">Structures_Graph_Node::connectsTo()</a> in Node.php</div>
                   103682:                                                        <div class="index-item-description">Test wether this node has an arc to the target node</div>
                   103683:                                        </dd>
                   103684:                        <dt class="field">
                   103685:                                                <span class="method-title">connectTo</span>
                   103686:                                        </dt>
                   103687:                <dd class="index-item-body">
                   103688:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodconnectTo">Structures_Graph_Node::connectTo()</a> in Node.php</div>
                   103689:                                                        <div class="index-item-description">Connect this node to another one.</div>
                   103690:                                        </dd>
                   103691:                </dl>
                   103692:        <a name="g"></a>
                   103693:        <div class="index-letter-section">
                   103694:                <div style="float: left" class="index-letter-title">g</div>
                   103695:                <div style="float: right"><a href="#top">top</a></div>
                   103696:                <div style="clear: both"></div>
                   103697:        </div>
                   103698:        <dl>
                   103699:                        <dt class="field">
                   103700:                                                <span class="method-title">getData</span>
                   103701:                                        </dt>
                   103702:                <dd class="index-item-body">
                   103703:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodgetData">Structures_Graph_Node::getData()</a> in Node.php</div>
                   103704:                                                        <div class="index-item-description">Node data getter.</div>
                   103705:                                        </dd>
                   103706:                        <dt class="field">
                   103707:                                                <span class="method-title">getGraph</span>
                   103708:                                        </dt>
                   103709:                <dd class="index-item-body">
                   103710:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodgetGraph">Structures_Graph_Node::getGraph()</a> in Node.php</div>
                   103711:                                                        <div class="index-item-description">Node graph getter</div>
                   103712:                                        </dd>
                   103713:                        <dt class="field">
                   103714:                                                <span class="method-title">getMetadata</span>
                   103715:                                        </dt>
                   103716:                <dd class="index-item-body">
                   103717:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodgetMetadata">Structures_Graph_Node::getMetadata()</a> in Node.php</div>
                   103718:                                                        <div class="index-item-description">Node metadata getter</div>
                   103719:                                        </dd>
                   103720:                        <dt class="field">
                   103721:                                                <span class="method-title">getNeighbours</span>
                   103722:                                        </dt>
                   103723:                <dd class="index-item-body">
                   103724:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodgetNeighbours">Structures_Graph_Node::getNeighbours()</a> in Node.php</div>
                   103725:                                                        <div class="index-item-description">Return nodes connected to this one.</div>
                   103726:                                        </dd>
                   103727:                        <dt class="field">
                   103728:                                                <span class="method-title">getNodes</span>
                   103729:                                        </dt>
                   103730:                <dd class="index-item-body">
                   103731:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html#methodgetNodes">Structures_Graph::getNodes()</a> in Graph.php</div>
                   103732:                                                        <div class="index-item-description">Return the node set, in no particular order. For ordered node sets, use a Graph Manipulator insted.</div>
                   103733:                                        </dd>
                   103734:                        <dt class="field">
                   103735:                                                <span class="include-title">Graph.php</span>
                   103736:                                        </dt>
                   103737:                <dd class="index-item-body">
                   103738:                        <div class="index-item-details"><a href="Structures_Graph/_Structures_Graph_php.html">Graph.php</a> in Graph.php</div>
                   103739:                                        </dd>
                   103740:                </dl>
                   103741:        <a name="i"></a>
                   103742:        <div class="index-letter-section">
                   103743:                <div style="float: left" class="index-letter-title">i</div>
                   103744:                <div style="float: right"><a href="#top">top</a></div>
                   103745:                <div style="clear: both"></div>
                   103746:        </div>
                   103747:        <dl>
                   103748:                        <dt class="field">
                   103749:                                                <span class="method-title">inDegree</span>
                   103750:                                        </dt>
                   103751:                <dd class="index-item-body">
                   103752:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodinDegree">Structures_Graph_Node::inDegree()</a> in Node.php</div>
                   103753:                                                        <div class="index-item-description">Calculate the in degree of the node.</div>
                   103754:                                        </dd>
                   103755:                        <dt class="field">
                   103756:                                                <span class="method-title">isAcyclic</span>
                   103757:                                        </dt>
                   103758:                <dd class="index-item-body">
                   103759:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html#methodisAcyclic">Structures_Graph_Manipulator_AcyclicTest::isAcyclic()</a> in AcyclicTest.php</div>
                   103760:                                                        <div class="index-item-description">isAcyclic returns true if a graph contains no cycles, false otherwise.</div>
                   103761:                                        </dd>
                   103762:                        <dt class="field">
                   103763:                                                <span class="method-title">isDirected</span>
                   103764:                                        </dt>
                   103765:                <dd class="index-item-body">
                   103766:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html#methodisDirected">Structures_Graph::isDirected()</a> in Graph.php</div>
                   103767:                                                        <div class="index-item-description">Return true if a graph is directed</div>
                   103768:                                        </dd>
                   103769:                </dl>
                   103770:        <a name="m"></a>
                   103771:        <div class="index-letter-section">
                   103772:                <div style="float: left" class="index-letter-title">m</div>
                   103773:                <div style="float: right"><a href="#top">top</a></div>
                   103774:                <div style="clear: both"></div>
                   103775:        </div>
                   103776:        <dl>
                   103777:                        <dt class="field">
                   103778:                                                <span class="method-title">metadataKeyExists</span>
                   103779:                                        </dt>
                   103780:                <dd class="index-item-body">
                   103781:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodmetadataKeyExists">Structures_Graph_Node::metadataKeyExists()</a> in Node.php</div>
                   103782:                                                        <div class="index-item-description">Test for existence of metadata under a given key.</div>
                   103783:                                        </dd>
                   103784:                </dl>
                   103785:        <a name="n"></a>
                   103786:        <div class="index-letter-section">
                   103787:                <div style="float: left" class="index-letter-title">n</div>
                   103788:                <div style="float: right"><a href="#top">top</a></div>
                   103789:                <div style="clear: both"></div>
                   103790:        </div>
                   103791:        <dl>
                   103792:                        <dt class="field">
                   103793:                                                <span class="include-title">Node.php</span>
                   103794:                                        </dt>
                   103795:                <dd class="index-item-body">
                   103796:                        <div class="index-item-details"><a href="Structures_Graph/_Structures_Graph_Node_php.html">Node.php</a> in Node.php</div>
                   103797:                                        </dd>
                   103798:                </dl>
                   103799:        <a name="o"></a>
                   103800:        <div class="index-letter-section">
                   103801:                <div style="float: left" class="index-letter-title">o</div>
                   103802:                <div style="float: right"><a href="#top">top</a></div>
                   103803:                <div style="clear: both"></div>
                   103804:        </div>
                   103805:        <dl>
                   103806:                        <dt class="field">
                   103807:                                                <span class="method-title">outDegree</span>
                   103808:                                        </dt>
                   103809:                <dd class="index-item-body">
                   103810:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodoutDegree">Structures_Graph_Node::outDegree()</a> in Node.php</div>
                   103811:                                                        <div class="index-item-description">Calculate the out degree of the node.</div>
                   103812:                                        </dd>
                   103813:                </dl>
                   103814:        <a name="r"></a>
                   103815:        <div class="index-letter-section">
                   103816:                <div style="float: left" class="index-letter-title">r</div>
                   103817:                <div style="float: right"><a href="#top">top</a></div>
                   103818:                <div style="clear: both"></div>
                   103819:        </div>
                   103820:        <dl>
                   103821:                        <dt class="field">
                   103822:                                                <span class="method-title">removeNode</span>
                   103823:                                        </dt>
                   103824:                <dd class="index-item-body">
                   103825:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html#methodremoveNode">Structures_Graph::removeNode()</a> in Graph.php</div>
                   103826:                                                        <div class="index-item-description">Remove a Node from the Graph</div>
                   103827:                                        </dd>
                   103828:                </dl>
                   103829:        <a name="s"></a>
                   103830:        <div class="index-letter-section">
                   103831:                <div style="float: left" class="index-letter-title">s</div>
                   103832:                <div style="float: right"><a href="#top">top</a></div>
                   103833:                <div style="clear: both"></div>
                   103834:        </div>
                   103835:        <dl>
                   103836:                        <dt class="field">
                   103837:                                                <span class="method-title">setData</span>
                   103838:                                        </dt>
                   103839:                <dd class="index-item-body">
                   103840:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodsetData">Structures_Graph_Node::setData()</a> in Node.php</div>
                   103841:                                                        <div class="index-item-description">Node data setter</div>
                   103842:                                        </dd>
                   103843:                        <dt class="field">
                   103844:                                                <span class="method-title">setGraph</span>
                   103845:                                        </dt>
                   103846:                <dd class="index-item-body">
                   103847:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodsetGraph">Structures_Graph_Node::setGraph()</a> in Node.php</div>
                   103848:                                                        <div class="index-item-description">Node graph setter. This method should not be called directly. Use Graph::addNode instead.</div>
                   103849:                                        </dd>
                   103850:                        <dt class="field">
                   103851:                                                <span class="method-title">setMetadata</span>
                   103852:                                        </dt>
                   103853:                <dd class="index-item-body">
                   103854:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodsetMetadata">Structures_Graph_Node::setMetadata()</a> in Node.php</div>
                   103855:                                                        <div class="index-item-description">Node metadata setter</div>
                   103856:                                        </dd>
                   103857:                        <dt class="field">
                   103858:                                                <span class="method-title">sort</span>
                   103859:                                        </dt>
                   103860:                <dd class="index-item-body">
                   103861:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html#methodsort">Structures_Graph_Manipulator_TopologicalSorter::sort()</a> in TopologicalSorter.php</div>
                   103862:                                                        <div class="index-item-description">sort returns the graph's nodes, sorted by topological order.</div>
                   103863:                                        </dd>
                   103864:                        <dt class="field">
                   103865:                                                Structures_Graph
                   103866:                                        </dt>
                   103867:                <dd class="index-item-body">
                   103868:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html">Structures_Graph</a> in Graph.php</div>
                   103869:                                                        <div class="index-item-description">The Structures_Graph class represents a graph data structure.</div>
                   103870:                                        </dd>
                   103871:                        <dt class="field">
                   103872:                                                <span class="method-title">Structures_Graph</span>
                   103873:                                        </dt>
                   103874:                <dd class="index-item-body">
                   103875:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph.html#methodStructures_Graph">Structures_Graph::Structures_Graph()</a> in Graph.php</div>
                   103876:                                                        <div class="index-item-description">Constructor</div>
                   103877:                                        </dd>
                   103878:                        <dt class="field">
                   103879:                                                <span class="const-title">STRUCTURES_GRAPH_ERROR_GENERIC</span>
                   103880:                                        </dt>
                   103881:                <dd class="index-item-body">
                   103882:                        <div class="index-item-details"><a href="Structures_Graph/_Structures_Graph_php.html#defineSTRUCTURES_GRAPH_ERROR_GENERIC">STRUCTURES_GRAPH_ERROR_GENERIC</a> in Graph.php</div>
                   103883:                                        </dd>
                   103884:                        <dt class="field">
                   103885:                                                Structures_Graph_Manipulator_AcyclicTest
                   103886:                                        </dt>
                   103887:                <dd class="index-item-body">
                   103888:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html">Structures_Graph_Manipulator_AcyclicTest</a> in AcyclicTest.php</div>
                   103889:                                                        <div class="index-item-description">The Structures_Graph_Manipulator_AcyclicTest is a graph manipulator  which tests whether a graph contains a cycle.</div>
                   103890:                                        </dd>
                   103891:                        <dt class="field">
                   103892:                                                Structures_Graph_Manipulator_TopologicalSorter
                   103893:                                        </dt>
                   103894:                <dd class="index-item-body">
                   103895:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html">Structures_Graph_Manipulator_TopologicalSorter</a> in TopologicalSorter.php</div>
                   103896:                                                        <div class="index-item-description">The Structures_Graph_Manipulator_TopologicalSorter is a manipulator  which is able to return the set of nodes in a graph, sorted by topological  order.</div>
                   103897:                                        </dd>
                   103898:                        <dt class="field">
                   103899:                                                <span class="method-title">Structures_Graph_Node</span>
                   103900:                                        </dt>
                   103901:                <dd class="index-item-body">
                   103902:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodStructures_Graph_Node">Structures_Graph_Node::Structures_Graph_Node()</a> in Node.php</div>
                   103903:                                                        <div class="index-item-description">Constructor</div>
                   103904:                                        </dd>
                   103905:                        <dt class="field">
                   103906:                                                Structures_Graph_Node
                   103907:                                        </dt>
                   103908:                <dd class="index-item-body">
                   103909:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html">Structures_Graph_Node</a> in Node.php</div>
                   103910:                                                        <div class="index-item-description">The Structures_Graph_Node class represents a Node that can be member of a  graph node set.</div>
                   103911:                                        </dd>
                   103912:                </dl>
                   103913:        <a name="t"></a>
                   103914:        <div class="index-letter-section">
                   103915:                <div style="float: left" class="index-letter-title">t</div>
                   103916:                <div style="float: right"><a href="#top">top</a></div>
                   103917:                <div style="clear: both"></div>
                   103918:        </div>
                   103919:        <dl>
                   103920:                        <dt class="field">
                   103921:                                                <span class="include-title">TopologicalSorter.php</span>
                   103922:                                        </dt>
                   103923:                <dd class="index-item-body">
                   103924:                        <div class="index-item-details"><a href="Structures_Graph/_Structures_Graph_Manipulator_TopologicalSorter_php.html">TopologicalSorter.php</a> in TopologicalSorter.php</div>
                   103925:                                        </dd>
                   103926:                </dl>
                   103927:        <a name="u"></a>
                   103928:        <div class="index-letter-section">
                   103929:                <div style="float: left" class="index-letter-title">u</div>
                   103930:                <div style="float: right"><a href="#top">top</a></div>
                   103931:                <div style="clear: both"></div>
                   103932:        </div>
                   103933:        <dl>
                   103934:                        <dt class="field">
                   103935:                                                <span class="method-title">unsetMetadata</span>
                   103936:                                        </dt>
                   103937:                <dd class="index-item-body">
                   103938:                        <div class="index-item-details"><a href="Structures_Graph/Structures_Graph_Node.html#methodunsetMetadata">Structures_Graph_Node::unsetMetadata()</a> in Node.php</div>
                   103939:                                                        <div class="index-item-description">Delete metadata by key</div>
                   103940:                                        </dd>
                   103941:                </dl>
                   103942: 
                   103943: <div class="index-letter-menu">
                   103944:        <a class="index-letter" href="elementindex_Structures_Graph.html#a">a</a>
                   103945:        <a class="index-letter" href="elementindex_Structures_Graph.html#c">c</a>
                   103946:        <a class="index-letter" href="elementindex_Structures_Graph.html#g">g</a>
                   103947:        <a class="index-letter" href="elementindex_Structures_Graph.html#i">i</a>
                   103948:        <a class="index-letter" href="elementindex_Structures_Graph.html#m">m</a>
                   103949:        <a class="index-letter" href="elementindex_Structures_Graph.html#n">n</a>
                   103950:        <a class="index-letter" href="elementindex_Structures_Graph.html#o">o</a>
                   103951:        <a class="index-letter" href="elementindex_Structures_Graph.html#r">r</a>
                   103952:        <a class="index-letter" href="elementindex_Structures_Graph.html#s">s</a>
                   103953:        <a class="index-letter" href="elementindex_Structures_Graph.html#t">t</a>
                   103954:        <a class="index-letter" href="elementindex_Structures_Graph.html#u">u</a>
                   103955: </div> </body>
                   103956: </html>Structures_Graph-1.0.4/docs/html/errors.html0000644000076600000240000000132511461440275020401 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   103957: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   103958:   <html xmlns="http://www.w3.org/1999/xhtml">
                   103959:                <head>
                   103960:                        <!-- template designed by Marco Von Ballmoos -->
                   103961:                        <title>phpDocumentor Parser Errors and Warnings</title>
                   103962:                        <link rel="stylesheet" href="media/stylesheet.css" />
                   103963:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   103964:                </head>
                   103965:                <body>
                   103966:                                                <a href="#Post-parsing">Post-parsing</a><br>
                   103967:        <p class="notes" id="credit">
                   103968:                Documentation generated on Fri, 30 Jan 2004 16:37:29 +0000 by <a href="http://www.phpdoc.org" target="_blank">phpDocumentor 1.2.3</a>
                   103969:        </p>
                   103970:        </body>
                   103971: </html>Structures_Graph-1.0.4/docs/html/index.html0000644000076600000240000000176111461440275020200 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   103972: <!DOCTYPE html 
                   103973:      PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//FR"
                   103974:      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
                   103975:    <html xmlns="http://www.w3.org/1999/xhtml">
                   103976: <head>
                   103977:        <!-- Generated by phpDocumentor on Fri, 30 Jan 2004 16:37:28 +0000  -->
                   103978:   <title>Structures_Graph Documentation</title>
                   103979:   <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   103980: </head>
                   103981: 
                   103982: <FRAMESET rows='100,*'>
                   103983:        <FRAME src='packages.html' name='left_top' frameborder="1" bordercolor="#999999">
                   103984:        <FRAMESET cols='25%,*'>
                   103985:                <FRAME src='li_Structures_Graph.html' name='left_bottom' frameborder="1" bordercolor="#999999">
                   103986:                <FRAME src='Structures_Graph/tutorial_Structures_Graph.pkg.html' name='right' frameborder="1" bordercolor="#999999">
                   103987:        </FRAMESET>
                   103988:        <NOFRAMES>
                   103989:                <H2>Frame Alert</H2>
                   103990:                <P>This document is designed to be viewed using the frames feature.
                   103991:                If you see this message, you are using a non-frame-capable web client.</P>
                   103992:        </NOFRAMES>
                   103993: </FRAMESET>
                   103994: </HTML>Structures_Graph-1.0.4/docs/html/li_Structures_Graph.html0000644000076600000240000000476011461440275023063 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   103995: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   103996:   <html xmlns="http://www.w3.org/1999/xhtml">
                   103997:                <head>
                   103998:                        <!-- template designed by Marco Von Ballmoos -->
                   103999:                        <title></title>
                   104000:                        <link rel="stylesheet" href="media/stylesheet.css" />
                   104001:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   104002:                </head>
                   104003:                <body>
                   104004:                                                <div class="package-title">Structures_Graph</div>
                   104005: <div class="package-details">
                   104006: 
                   104007:        <dl class="tree">
                   104008:                
                   104009:                <dt class="folder-title">Description</dt>
                   104010:                <dd>
                   104011:                        <a href='classtrees_Structures_Graph.html' target='right'>Class trees</a><br />
                   104012:                        <a href='elementindex_Structures_Graph.html' target='right'>Index of elements</a><br />
                   104013:                                                        <a href="todolist.html" target="right">Todo List</a><br />
                   104014:                                        </dd>
                   104015:        
                   104016:                                                        
                   104017:                                                        
                   104018:                                                                        <dt class="folder-title">Tutorials/Manuals</dt>
                   104019:                                        <dd>
                   104020:                                                                                        <dl class="tree">
                   104021:                                                <dt class="folder-title">Package-level</dt>
                   104022:                                                <dd>
                   104023:                                                                                                        <div><a href="Structures_Graph/tutorial_Structures_Graph.pkg.html" target="right">Structures_Graph Tutorial</a></div>
                   104024: 
                   104025:                                                                                                </dd>
                   104026:                                                </dl>
                   104027:                                                                                
                   104028:                                                                                
                   104029:                                                                                </dd>
                   104030:                                                                                                        <dt class="folder-title">Classes</dt>
                   104031:                                                                                        <dd><a href='Structures_Graph/Structures_Graph.html' target='right'>Structures_Graph</a></dd>
                   104032:                                                                                        <dd><a href='Structures_Graph/Structures_Graph_Manipulator_AcyclicTest.html' target='right'>Structures_Graph_Manipulator_AcyclicTest</a></dd>
                   104033:                                                                                        <dd><a href='Structures_Graph/Structures_Graph_Manipulator_TopologicalSorter.html' target='right'>Structures_Graph_Manipulator_TopologicalSorter</a></dd>
                   104034:                                                                                        <dd><a href='Structures_Graph/Structures_Graph_Node.html' target='right'>Structures_Graph_Node</a></dd>
                   104035:                                                                                                                                                                                <dt class="folder-title">Files</dt>
                   104036:                                                                                        <dd><a href='Structures_Graph/_Structures_Graph_Manipulator_AcyclicTest_php.html' target='right'>AcyclicTest.php</a></dd>
                   104037:                                                                                        <dd><a href='Structures_Graph/_Structures_Graph_php.html' target='right'>Graph.php</a></dd>
                   104038:                                                                                        <dd><a href='Structures_Graph/_Structures_Graph_Node_php.html' target='right'>Node.php</a></dd>
                   104039:                                                                                        <dd><a href='Structures_Graph/_Structures_Graph_Manipulator_TopologicalSorter_php.html' target='right'>TopologicalSorter.php</a></dd>
                   104040:                                                                                                                                        
                   104041:                                                
                   104042:                        </dl>
                   104043: </div>
                   104044: <p class="notes"><a href="http://www.phpdoc.org" target="_blank">phpDocumentor v <span class="field">1.2.3</span></a></p>
                   104045: </BODY>
                   104046: </HTML>Structures_Graph-1.0.4/docs/html/packages.html0000644000076600000240000000164111461440275020644 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   104047: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   104048:   <html xmlns="http://www.w3.org/1999/xhtml">
                   104049:                <head>
                   104050:                        <!-- template designed by Marco Von Ballmoos -->
                   104051:                        <title></title>
                   104052:                        <link rel="stylesheet" href="media/stylesheet.css" />
                   104053:                        <link rel="stylesheet" href="media/banner.css" />
                   104054:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   104055:                </head>
                   104056:                <body>
                   104057:                        <div class="banner">
                   104058:                                <div class="banner-title">Structures_Graph</div>
                   104059:                                <div class="banner-menu">
                   104060:                <table cellpadding="0" cellspacing="0" style="width: 100%">
                   104061:                  <tr>
                   104062:               <td>
                   104063:                                                                              </td>
                   104064:               <td style="width: 2em">&nbsp;</td>
                   104065:               <td style="text-align: right">
                   104066:                                                                              </td>
                   104067:                                                </tr>
                   104068:           </table>
                   104069:                                </div>
                   104070:                        </div>
                   104071:                </body>
                   104072:        </html>Structures_Graph-1.0.4/docs/html/todolist.html0000644000076600000240000000155411461440275020732 0ustar  bbieberstaff<?xml version="1.0" encoding="iso-8859-1"?>
                   104073: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                   104074:   <html xmlns="http://www.w3.org/1999/xhtml">
                   104075:                <head>
                   104076:                        <!-- template designed by Marco Von Ballmoos -->
                   104077:                        <title>Todo List</title>
                   104078:                        <link rel="stylesheet" href="media/stylesheet.css" />
                   104079:                        <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
                   104080:                </head>
                   104081:                <body>
                   104082:                                                <div align="center"><h1>Todo List</h1></div>
                   104083: <h2>Structures_Graph</h2>
                   104084: <h3><a href="Structures_Graph/Structures_Graph.html#methodremoveNode">Structures_Graph::removeNode()</a></h3>
                   104085: <ul>
                   104086:     <li>This is unimplemented</li>
                   104087: </ul>
                   104088:        <p class="notes" id="credit">
                   104089:                Documentation generated on Fri, 30 Jan 2004 16:37:29 +0000 by <a href="http://www.phpdoc.org" target="_blank">phpDocumentor 1.2.3</a>
                   104090:        </p>
                   104091:        </body>
                   104092: </html>Structures_Graph-1.0.4/docs/tutorials/Structures_Graph/Structures_Graph.pkg0000644000076600000240000000771411461440275026604 0ustar  bbieberstaff<refentry id="{@id package.database.structures_graph.tutorial}">
                   104093:  <refnamediv>
                   104094:   <refname><classname>Structures_Graph</classname> Tutorial</refname>
                   104095:   <refpurpose>A first tour of graph datastructure manipulation</refpurpose>
                   104096:  </refnamediv>
                   104097:  <refsect1 id="{@id package.database.structures_graph.tutorial.intro}">
                   104098:   <title>Introduction</title>
                   104099:   <para>
                   104100:   Structures_Graph is a package for creating and manipulating graph datastructures. A graph is a set of objects, called nodes, connected by arcs. When used as a datastructure, usually nodes contain data, and arcs represent relationships between nodes. When arcs have a direction, and can be travelled only one way, graphs are said to be directed. When arcs have no direction, and can always be travelled both ways, graphs are said to be non directed.
                   104101:   </para>
                   104102:   <para>
                   104103:   Structures_Graph provides an object oriented API to create and directly query a graph, as well as a set of Manipulator classes to extract information from the graph.
                   104104:   </para>
                   104105:  </refsect1>
                   104106:  <refsect1 id="{@id package.database.structures_graph.tutorial.creation}">
                   104107:   <title>Creating a Graph</title>
                   104108:   <para>
                   104109:    Creating a graph is done using the simple constructor:
                   104110:    <programlisting>
                   104111:     <![CDATA[
                   104112: require_once 'Structures/Graph.php';
                   104113: 
                   104114: $directedGraph =& new Structures_Graph(true);
                   104115: $nonDirectedGraph =& new Structures_Graph(false);
                   104116:     ]]>
                   104117:    </programlisting>
                   104118:    and passing the constructor a flag telling it whether the graph should be directed. A directed graph will always be directed during its lifetime. It's a permanent characteristic.
                   104119:   </para>
                   104120:   <para>
                   104121:   To fill out the graph, we'll need to create some nodes, and then call Graph::addNode.
                   104122:    <programlisting>
                   104123:     <![CDATA[
                   104124: require_once 'Structures/Graph/Node.php';
                   104125: 
                   104126: $nodeOne =& new Structures_Graph_Node();
                   104127: $nodeTwo =& new Structures_Graph_Node();
                   104128: $nodeThree =& new Structures_Graph_Node();
                   104129: 
                   104130: $directedGraph->addNode(&$nodeOne);
                   104131: $directedGraph->addNode(&$nodeTwo);
                   104132: $directedGraph->addNode(&$nodeThree);
                   104133:     ]]>
                   104134:    </programlisting>
                   104135:    and then setup the arcs:
                   104136:    <programlisting>
                   104137:     <![CDATA[
                   104138: $nodeOne->connectTo($nodeTwo);
                   104139: $nodeOne->connectTo($nodeThree);
                   104140:     ]]>
                   104141:    </programlisting>
                   104142:    Note that arcs can only be created after the nodes have been inserted into the graph. 
                   104143:   </para>
                   104144:  </refsect1>
                   104145:  <refsect1 id="{@id package.database.structures_graph.tutorial.nodesanddata}">
                   104146:   <title>Associating Data</title>
                   104147:   <para>
                   104148:   Graphs are only useful as datastructures if they can hold data. Structure_Graph stores data in nodes. Each node contains a setter and a getter for its data.
                   104149:    <programlisting>
                   104150:     <![CDATA[
                   104151: $nodeOne->setData("Node One's Data is a String");
                   104152: $nodeTwo->setData(1976);
                   104153: $nodeThree->setData('Some other string');
                   104154: 
                   104155: print("NodeTwo's Data is an integer: " . $nodeTwo->getData());
                   104156:     ]]>
                   104157:    </programlisting>
                   104158:   </para>
                   104159:   <para>
                   104160:   Structure_Graph nodes can also store metadata, alongside with the main data. Metadata differs from regular data just because it is stored under a key, making it possible to store more than one data reference per node. The metadata getter and setter need the key to perform the operation:
                   104161:    <programlisting>
                   104162:     <![CDATA[
                   104163: $nodeOne->setMetadata('example key', "Node One's Sample Metadata");
                   104164: print("Metadata stored under key 'example key' in node one: " . $nodeOne->getMetadata('example key'));
                   104165: $nodeOne->unsetMetadata('example key');
                   104166:     ]]>
                   104167:    </programlisting>
                   104168:   </para>
                   104169:  </refsect1>
                   104170:  <refsect1 id="{@id package.database.structures_graph.tutorial.querying}">
                   104171:   <title>Querying a Graph</title>
                   104172:   <para>
                   104173:   Structures_Graph provides for basic querying of the graph:
                   104174:    <programlisting>
                   104175:     <![CDATA[
                   104176: // Nodes are able to calculate their indegree and outdegree
                   104177: print("NodeOne's inDegree: " . $nodeOne->inDegree());
                   104178: print("NodeOne's outDegree: " . $nodeOne->outDegree());
                   104179: 
                   104180: // and naturally, nodes can report on their arcs
                   104181: $arcs = $nodeOne->getNeighbours();
                   104182: for ($i=0;$i<sizeof($arcs);$i++) {
                   104183:     print("NodeOne has an arc to " . $arcs[$i]->getData());
                   104184: }
                   104185:     ]]>
                   104186:    </programlisting>
                   104187:   </para>
                   104188:  </refsect1>
                   104189: </refentry>
                   104190: Structures_Graph-1.0.4/docs/generate.sh0000755000076600000240000000055511461440275017370 0ustar  bbieberstaff#!/bin/sh
                   104191: (cd ..; tar czf docs/arch.tgz "{arch}")
                   104192: rm -Rf "../{arch}"
                   104193: rm -Rf ./html
                   104194: mkdir -p ./html
                   104195: phpdoc --directory ../Structures,./tutorials --target ./html --title "Structures_Graph Documentation" --output "HTML:frames" --defaultpackagename structures_graph --defaultcategoryname structures --pear 
                   104196: (cd ..; tar --absolute-names -xzf docs/arch.tgz)
                   104197: #rm arch.tgz
                   104198: Structures_Graph-1.0.4/Structures/Graph/Manipulator/AcyclicTest.php0000644000076600000240000001316011461440275024742 0ustar  bbieberstaff<?php
                   104199: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
                   104200: // +-----------------------------------------------------------------------------+
                   104201: // | Copyright (c) 2003 Sérgio Gonçalves Carvalho                                |
                   104202: // +-----------------------------------------------------------------------------+
                   104203: // | This file is part of Structures_Graph.                                      |
                   104204: // |                                                                             |
                   104205: // | Structures_Graph is free software; you can redistribute it and/or modify    |
                   104206: // | it under the terms of the GNU Lesser General Public License as published by |
                   104207: // | the Free Software Foundation; either version 2.1 of the License, or         |
                   104208: // | (at your option) any later version.                                         |
                   104209: // |                                                                             |
                   104210: // | Structures_Graph is distributed in the hope that it will be useful,         |
                   104211: // | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
                   104212: // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
                   104213: // | GNU Lesser General Public License for more details.                         |
                   104214: // |                                                                             |
                   104215: // | You should have received a copy of the GNU Lesser General Public License    |
                   104216: // | along with Structures_Graph; if not, write to the Free Software             |
                   104217: // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
                   104218: // | 02111-1307 USA                                                              |
                   104219: // +-----------------------------------------------------------------------------+
                   104220: // | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com>                  |
                   104221: // +-----------------------------------------------------------------------------+
                   104222: //
                   104223: /**
                   104224:  * This file contains the definition of the Structures_Graph_Manipulator_AcyclicTest graph manipulator.
                   104225:  * 
                   104226:  * @see Structures_Graph_Manipulator_AcyclicTest
                   104227:  * @package Structures_Graph
                   104228:  */
                   104229: 
                   104230: /* dependencies {{{ */
                   104231: /** */
                   104232: require_once 'PEAR.php';
                   104233: /** */
                   104234: require_once 'Structures/Graph.php';
                   104235: /** */
                   104236: require_once 'Structures/Graph/Node.php';
                   104237: /* }}} */
                   104238: 
                   104239: /* class Structures_Graph_Manipulator_AcyclicTest {{{ */
                   104240: /**
                   104241:  * The Structures_Graph_Manipulator_AcyclicTest is a graph manipulator
                   104242:  * which tests whether a graph contains a cycle. 
                   104243:  * 
                   104244:  * The definition of an acyclic graph used in this manipulator is that of a 
                   104245:  * DAG. The graph must be directed, or else it is considered cyclic, even when 
                   104246:  * there are no arcs.
                   104247:  *
                   104248:  * @author             Sérgio Carvalho <sergio.carvalho@portugalmail.com> 
                   104249:  * @copyright  (c) 2004 by Sérgio Carvalho
                   104250:  * @package Structures_Graph
                   104251:  */
                   104252: class Structures_Graph_Manipulator_AcyclicTest {
                   104253:     /* _nonVisitedInDegree {{{ */
                   104254:     /**
                   104255:     *
                   104256:     * This is a variant of Structures_Graph::inDegree which does 
                   104257:     * not count nodes marked as visited.
                   104258:     *
                   104259:     * @access   private
                   104260:     * @return  integer  Number of non-visited nodes that link to this one
                   104261:     */
                   104262:     function _nonVisitedInDegree(&$node) {
                   104263:         $result = 0;
                   104264:         $graphNodes =& $node->_graph->getNodes();
                   104265:         foreach (array_keys($graphNodes) as $key) {
                   104266:             if ((!$graphNodes[$key]->getMetadata('acyclic-test-visited')) && $graphNodes[$key]->connectsTo($node)) $result++;
                   104267:         }
                   104268:         return $result;
                   104269:         
                   104270:     }
                   104271:     /* }}} */
                   104272: 
                   104273:     /* _isAcyclic {{{ */
                   104274:     /**
                   104275:     * @access   private
                   104276:     */
                   104277:     function _isAcyclic(&$graph) {
                   104278:         // Mark every node as not visited
                   104279:         $nodes =& $graph->getNodes();
                   104280:         $nodeKeys = array_keys($nodes);
                   104281:         $refGenerator = array();
                   104282:         foreach($nodeKeys as $key) {
                   104283:             $refGenerator[] = false;
                   104284:             $nodes[$key]->setMetadata('acyclic-test-visited', $refGenerator[sizeof($refGenerator) - 1]);
                   104285:         }
                   104286: 
                   104287:         // Iteratively peel off leaf nodes
                   104288:         do {
                   104289:             // Find out which nodes are leafs (excluding visited nodes)
                   104290:             $leafNodes = array();
                   104291:             foreach($nodeKeys as $key) {
                   104292:                 if ((!$nodes[$key]->getMetadata('acyclic-test-visited')) && Structures_Graph_Manipulator_AcyclicTest::_nonVisitedInDegree($nodes[$key]) == 0) {
                   104293:                     $leafNodes[] =& $nodes[$key];
                   104294:                 }
                   104295:             }
                   104296:             // Mark leafs as visited
                   104297:             for ($i=sizeof($leafNodes) - 1; $i>=0; $i--) {
                   104298:                 $visited =& $leafNodes[$i]->getMetadata('acyclic-test-visited');
                   104299:                 $visited = true;
                   104300:                 $leafNodes[$i]->setMetadata('acyclic-test-visited', $visited);
                   104301:             }
                   104302:         } while (sizeof($leafNodes) > 0);
                   104303: 
                   104304:         // If graph is a DAG, there should be no non-visited nodes. Let's try to prove otherwise
                   104305:         $result = true;
                   104306:         foreach($nodeKeys as $key) if (!$nodes[$key]->getMetadata('acyclic-test-visited')) $result = false;
                   104307:         
                   104308:         // Cleanup visited marks
                   104309:         foreach($nodeKeys as $key) $nodes[$key]->unsetMetadata('acyclic-test-visited');
                   104310: 
                   104311:         return $result;
                   104312:     }
                   104313:     /* }}} */
                   104314: 
                   104315:     /* isAcyclic {{{ */
                   104316:     /**
                   104317:     *
                   104318:     * isAcyclic returns true if a graph contains no cycles, false otherwise.
                   104319:     *
                   104320:     * @return  boolean  true iff graph is acyclic
                   104321:     * @access  public
                   104322:     */
                   104323:     function isAcyclic(&$graph) {
                   104324:         // We only test graphs
                   104325:         if (!is_a($graph, 'Structures_Graph')) return Pear::raiseError('Structures_Graph_Manipulator_AcyclicTest::isAcyclic received an object that is not a Structures_Graph', STRUCTURES_GRAPH_ERROR_GENERIC);
                   104326:         if (!$graph->isDirected()) return false; // Only directed graphs may be acyclic
                   104327: 
                   104328:         return Structures_Graph_Manipulator_AcyclicTest::_isAcyclic($graph);
                   104329:     }
                   104330:     /* }}} */
                   104331: }
                   104332: /* }}} */
                   104333: ?>
                   104334: Structures_Graph-1.0.4/Structures/Graph/Manipulator/TopologicalSorter.php0000644000076600000240000001504611461440275026213 0ustar  bbieberstaff<?php
                   104335: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
                   104336: // +-----------------------------------------------------------------------------+
                   104337: // | Copyright (c) 2003 Sérgio Gonçalves Carvalho                                |
                   104338: // +-----------------------------------------------------------------------------+
                   104339: // | This file is part of Structures_Graph.                                      |
                   104340: // |                                                                             |
                   104341: // | Structures_Graph is free software; you can redistribute it and/or modify    |
                   104342: // | it under the terms of the GNU Lesser General Public License as published by |
                   104343: // | the Free Software Foundation; either version 2.1 of the License, or         |
                   104344: // | (at your option) any later version.                                         |
                   104345: // |                                                                             |
                   104346: // | Structures_Graph is distributed in the hope that it will be useful,         |
                   104347: // | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
                   104348: // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
                   104349: // | GNU Lesser General Public License for more details.                         |
                   104350: // |                                                                             |
                   104351: // | You should have received a copy of the GNU Lesser General Public License    |
                   104352: // | along with Structures_Graph; if not, write to the Free Software             |
                   104353: // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
                   104354: // | 02111-1307 USA                                                              |
                   104355: // +-----------------------------------------------------------------------------+
                   104356: // | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com>                  |
                   104357: // +-----------------------------------------------------------------------------+
                   104358: //
                   104359: /**
                   104360:  * This file contains the definition of the Structures_Graph_Manipulator_TopologicalSorter class.
                   104361:  * 
                   104362:  * @see Structures_Graph_Manipulator_TopologicalSorter
                   104363:  * @package Structures_Graph
                   104364:  */
                   104365: 
                   104366: /* dependencies {{{ */
                   104367: /** */
                   104368: require_once 'PEAR.php';
                   104369: /** */
                   104370: require_once 'Structures/Graph.php';
                   104371: /** */
                   104372: require_once 'Structures/Graph/Node.php';
                   104373: /** */
                   104374: require_once 'Structures/Graph/Manipulator/AcyclicTest.php';
                   104375: /* }}} */
                   104376: 
                   104377: /* class Structures_Graph_Manipulator_TopologicalSorter {{{ */
                   104378: /**
                   104379:  * The Structures_Graph_Manipulator_TopologicalSorter is a manipulator 
                   104380:  * which is able to return the set of nodes in a graph, sorted by topological 
                   104381:  * order.
                   104382:  *
                   104383:  * A graph may only be sorted topologically iff it's a DAG. You can test it
                   104384:  * with the Structures_Graph_Manipulator_AcyclicTest.
                   104385:  * 
                   104386:  * @author             Sérgio Carvalho <sergio.carvalho@portugalmail.com> 
                   104387:  * @copyright  (c) 2004 by Sérgio Carvalho
                   104388:  * @see     Structures_Graph_Manipulator_AcyclicTest
                   104389:  * @package Structures_Graph
                   104390:  */
                   104391: class Structures_Graph_Manipulator_TopologicalSorter {
                   104392:     /* _nonVisitedInDegree {{{ */
                   104393:     /**
                   104394:     *
                   104395:     * This is a variant of Structures_Graph::inDegree which does 
                   104396:     * not count nodes marked as visited.
                   104397:     *
                   104398:     * @access   private
                   104399:     * @return  integer  Number of non-visited nodes that link to this one
                   104400:     */
                   104401:     function _nonVisitedInDegree(&$node) {
                   104402:         $result = 0;
                   104403:         $graphNodes =& $node->_graph->getNodes();
                   104404:         foreach (array_keys($graphNodes) as $key) {
                   104405:             if ((!$graphNodes[$key]->getMetadata('topological-sort-visited')) && $graphNodes[$key]->connectsTo($node)) $result++;
                   104406:         }
                   104407:         return $result;
                   104408:         
                   104409:     }
                   104410:     /* }}} */
                   104411: 
                   104412:     /* _sort {{{ */
                   104413:     /**
                   104414:     * @access   private
                   104415:     */
                   104416:     function _sort(&$graph) {
                   104417:         // Mark every node as not visited
                   104418:         $nodes =& $graph->getNodes();
                   104419:         $nodeKeys = array_keys($nodes);
                   104420:         $refGenerator = array();
                   104421:         foreach($nodeKeys as $key) {
                   104422:             $refGenerator[] = false;
                   104423:             $nodes[$key]->setMetadata('topological-sort-visited', $refGenerator[sizeof($refGenerator) - 1]);
                   104424:         }
                   104425: 
                   104426:         // Iteratively peel off leaf nodes
                   104427:         $topologicalLevel = 0;
                   104428:         do {
                   104429:             // Find out which nodes are leafs (excluding visited nodes)
                   104430:             $leafNodes = array();
                   104431:             foreach($nodeKeys as $key) {
                   104432:                 if ((!$nodes[$key]->getMetadata('topological-sort-visited')) && Structures_Graph_Manipulator_TopologicalSorter::_nonVisitedInDegree($nodes[$key]) == 0) {
                   104433:                     $leafNodes[] =& $nodes[$key];
                   104434:                 }
                   104435:             }
                   104436:             // Mark leafs as visited
                   104437:             $refGenerator[] = $topologicalLevel;
                   104438:             for ($i=sizeof($leafNodes) - 1; $i>=0; $i--) {
                   104439:                 $visited =& $leafNodes[$i]->getMetadata('topological-sort-visited');
                   104440:                 $visited = true;
                   104441:                 $leafNodes[$i]->setMetadata('topological-sort-visited', $visited);
                   104442:                 $leafNodes[$i]->setMetadata('topological-sort-level', $refGenerator[sizeof($refGenerator) - 1]);
                   104443:             }
                   104444:             $topologicalLevel++;
                   104445:         } while (sizeof($leafNodes) > 0);
                   104446: 
                   104447:         // Cleanup visited marks
                   104448:         foreach($nodeKeys as $key) $nodes[$key]->unsetMetadata('topological-sort-visited');
                   104449:     }
                   104450:     /* }}} */
                   104451: 
                   104452:     /* sort {{{ */
                   104453:     /**
                   104454:     *
                   104455:     * sort returns the graph's nodes, sorted by topological order. 
                   104456:     * 
                   104457:     * The result is an array with 
                   104458:     * as many entries as topological levels. Each entry in this array is an array of nodes within
                   104459:     * the given topological level.
                   104460:     *
                   104461:     * @return  array    The graph's nodes, sorted by topological order.
                   104462:     * @access  public
                   104463:     */
                   104464:     function sort(&$graph) {
                   104465:         // We only sort graphs
                   104466:         if (!is_a($graph, 'Structures_Graph')) return Pear::raiseError('Structures_Graph_Manipulator_TopologicalSorter::sort received an object that is not a Structures_Graph', STRUCTURES_GRAPH_ERROR_GENERIC);
                   104467:         if (!Structures_Graph_Manipulator_AcyclicTest::isAcyclic($graph)) return Pear::raiseError('Structures_Graph_Manipulator_TopologicalSorter::sort received an graph that has cycles', STRUCTURES_GRAPH_ERROR_GENERIC);
                   104468: 
                   104469:         Structures_Graph_Manipulator_TopologicalSorter::_sort($graph);
                   104470:         $result = array();
                   104471: 
                   104472:         // Fill out result array
                   104473:         $nodes =& $graph->getNodes();
                   104474:         $nodeKeys = array_keys($nodes);
                   104475:         foreach($nodeKeys as $key) {
                   104476:             if (!array_key_exists($nodes[$key]->getMetadata('topological-sort-level'), $result)) $result[$nodes[$key]->getMetadata('topological-sort-level')] = array();
                   104477:             $result[$nodes[$key]->getMetadata('topological-sort-level')][] =& $nodes[$key];
                   104478:             $nodes[$key]->unsetMetadata('topological-sort-level');
                   104479:         }
                   104480: 
                   104481:         return $result;
                   104482:     }
                   104483:     /* }}} */
                   104484: }
                   104485: /* }}} */
                   104486: ?>
                   104487: Structures_Graph-1.0.4/Structures/Graph/Node.php0000644000076600000240000002545011461440275021132 0ustar  bbieberstaff<?php
                   104488: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
                   104489: // +-----------------------------------------------------------------------------+
                   104490: // | Copyright (c) 2003 Sérgio Gonçalves Carvalho                                |
                   104491: // +-----------------------------------------------------------------------------+
                   104492: // | This file is part of Structures_Graph.                                      |
                   104493: // |                                                                             |
                   104494: // | Structures_Graph is free software; you can redistribute it and/or modify    |
                   104495: // | it under the terms of the GNU Lesser General Public License as published by |
                   104496: // | the Free Software Foundation; either version 2.1 of the License, or         |
                   104497: // | (at your option) any later version.                                         |
                   104498: // |                                                                             |
                   104499: // | Structures_Graph is distributed in the hope that it will be useful,         |
                   104500: // | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
                   104501: // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
                   104502: // | GNU Lesser General Public License for more details.                         |
                   104503: // |                                                                             |
                   104504: // | You should have received a copy of the GNU Lesser General Public License    |
                   104505: // | along with Structures_Graph; if not, write to the Free Software             |
                   104506: // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
                   104507: // | 02111-1307 USA                                                              |
                   104508: // +-----------------------------------------------------------------------------+
                   104509: // | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com>                  |
                   104510: // +-----------------------------------------------------------------------------+
                   104511: //
                   104512: /**
                   104513:  * This file contains the definition of the Structures_Graph_Node class
                   104514:  * 
                   104515:  * @see Structures_Graph_Node
                   104516:  * @package Structures_Graph
                   104517:  */
                   104518: 
                   104519: /* dependencies {{{ */
                   104520: /** */
                   104521: require_once 'PEAR.php';
                   104522: /** */
                   104523: require_once 'Structures/Graph.php';
                   104524: /* }}} */
                   104525: 
                   104526: /* class Structures_Graph_Node {{{ */
                   104527: /**
                   104528:  * The Structures_Graph_Node class represents a Node that can be member of a 
                   104529:  * graph node set.
                   104530:  *
                   104531:  * A graph node can contain data. Under this API, the node contains default data, 
                   104532:  * and key index data. It behaves, thus, both as a regular data node, and as a 
                   104533:  * dictionary (or associative array) node.
                   104534:  * 
                   104535:  * Regular data is accessed via getData and setData. Key indexed data is accessed
                   104536:  * via getMetadata and setMetadata.
                   104537:  *
                   104538:  * @author             Sérgio Carvalho <sergio.carvalho@portugalmail.com> 
                   104539:  * @copyright  (c) 2004 by Sérgio Carvalho
                   104540:  * @package Structures_Graph
                   104541:  */
                   104542: /* }}} */
                   104543: class Structures_Graph_Node {
                   104544:     /* fields {{{ */
                   104545:     /** 
                   104546:      * @access private 
                   104547:      */
                   104548:     var $_data = null;
                   104549:     /** @access private */
                   104550:     var $_metadata = array();
                   104551:     /** @access private */
                   104552:     var $_arcs = array();
                   104553:     /** @access private */
                   104554:     var $_graph = null;
                   104555:     /* }}} */
                   104556: 
                   104557:     /* Constructor {{{ */
                   104558:     /**
                   104559:     *
                   104560:     * Constructor
                   104561:     *
                   104562:     * @access  public
                   104563:     */
                   104564:     function Structures_Graph_Node() {
                   104565:     }
                   104566:     /* }}} */
                   104567: 
                   104568:     /* getGraph {{{ */
                   104569:     /**
                   104570:     *
                   104571:     * Node graph getter
                   104572:     *
                   104573:     * @return  Structures_Graph        Graph where node is stored
                   104574:     * @access  public
                   104575:     */
                   104576:     function &getGraph() {
                   104577:         return $this->_graph;
                   104578:     }
                   104579:     /* }}} */
                   104580: 
                   104581:     /* setGraph {{{ */
                   104582:     /**
                   104583:     *
                   104584:     * Node graph setter. This method should not be called directly. Use Graph::addNode instead.
                   104585:     *
                   104586:     * @param    Structures_Graph   Set the graph for this node. 
                   104587:     * @see      Structures_Graph::addNode()
                   104588:     * @access  public
                   104589:     */
                   104590:     function setGraph(&$graph) {
                   104591:         $this->_graph =& $graph;
                   104592:     }
                   104593:     /* }}} */
                   104594: 
                   104595:     /* getData {{{ */
                   104596:     /**
                   104597:     *
                   104598:     * Node data getter.
                   104599:     * 
                   104600:     * Each graph node can contain a reference to one variable. This is the getter for that reference.
                   104601:     *
                   104602:     * @return  mixed   Data stored in node
                   104603:     * @access  public
                   104604:     */
                   104605:     function &getData() {
                   104606:         return $this->_data;
                   104607:     }
                   104608:     /* }}} */
                   104609: 
                   104610:     /* setData {{{ */
                   104611:     /**
                   104612:     *
                   104613:     * Node data setter
                   104614:     *
                   104615:     * Each graph node can contain a reference to one variable. This is the setter for that reference.
                   104616:     *
                   104617:     * @return  mixed   Data to store in node
                   104618:     * @access  public
                   104619:     */
                   104620:     function setData($data) {
                   104621:         $this->_data =& $data;
                   104622:     }
                   104623:     /* }}} */
                   104624: 
                   104625:     /* metadataKeyExists {{{ */
                   104626:     /**
                   104627:     *
                   104628:     * Test for existence of metadata under a given key.
                   104629:     *
                   104630:     * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an 
                   104631:     * associative array or in a dictionary. This method tests whether a given metadata key exists for this node.
                   104632:     *
                   104633:     * @param    string    Key to test
                   104634:     * @return  boolean  
                   104635:     * @access  public
                   104636:     */
                   104637:     function metadataKeyExists($key) {
                   104638:         return array_key_exists($key, $this->_metadata);
                   104639:     }
                   104640:     /* }}} */
                   104641: 
                   104642:     /* getMetadata {{{ */
                   104643:     /**
                   104644:     *
                   104645:     * Node metadata getter
                   104646:     *
                   104647:     * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an 
                   104648:     * associative array or in a dictionary. This method gets the data under the given key. If the key does
                   104649:     * not exist, an error will be thrown, so testing using metadataKeyExists might be needed.
                   104650:     *
                   104651:     * @param    string  Key
                   104652:     * @param    boolean nullIfNonexistent (defaults to false).
                   104653:     * @return  mixed   Metadata Data stored in node under given key
                   104654:     * @see      metadataKeyExists
                   104655:     * @access  public
                   104656:     */
                   104657:     function &getMetadata($key, $nullIfNonexistent = false) {
                   104658:         if (array_key_exists($key, $this->_metadata)) {
                   104659:             return $this->_metadata[$key];
                   104660:         } else {
                   104661:             if ($nullIfNonexistent) {
                   104662:                 $a = null;
                   104663:                 return $a;
                   104664:             } else {
                   104665:                 $a = Pear::raiseError('Structures_Graph_Node::getMetadata: Requested key does not exist', STRUCTURES_GRAPH_ERROR_GENERIC);
                   104666:                 return $a;
                   104667:             }
                   104668:         }
                   104669:     }
                   104670:     /* }}} */
                   104671: 
                   104672:     /* unsetMetadata {{{ */
                   104673:     /**
                   104674:     *
                   104675:     * Delete metadata by key
                   104676:     *
                   104677:     * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an 
                   104678:     * associative array or in a dictionary. This method removes any data that might be stored under the provided key.
                   104679:     * If the key does not exist, no error is thrown, so it is safe using this method without testing for key existence.
                   104680:     *
                   104681:     * @param    string  Key
                   104682:     * @access  public
                   104683:     */
                   104684:     function unsetMetadata($key) {
                   104685:         if (array_key_exists($key, $this->_metadata)) unset($this->_metadata[$key]);
                   104686:     }
                   104687:     /* }}} */
                   104688: 
                   104689:     /* setMetadata {{{ */
                   104690:     /**
                   104691:     *
                   104692:     * Node metadata setter
                   104693:     *
                   104694:     * Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an 
                   104695:     * associative array or in a dictionary. This method stores data under the given key. If the key already exists,
                   104696:     * previously stored data is discarded.
                   104697:     *
                   104698:     * @param    string  Key
                   104699:     * @param    mixed   Data 
                   104700:     * @access  public
                   104701:     */
                   104702:     function setMetadata($key, $data) {
                   104703:         $this->_metadata[$key] =& $data;
                   104704:     }
                   104705:     /* }}} */
                   104706: 
                   104707:     /* _connectTo {{{ */
                   104708:     /** @access private */
                   104709:     function _connectTo(&$destinationNode) {
                   104710:         $this->_arcs[] =& $destinationNode;
                   104711:     }
                   104712:     /* }}} */
                   104713: 
                   104714:     /* connectTo {{{ */
                   104715:     /**
                   104716:     *
                   104717:     * Connect this node to another one.
                   104718:     * 
                   104719:     * If the graph is not directed, the reverse arc, connecting $destinationNode to $this is also created.
                   104720:     *
                   104721:     * @param    Structures_Graph_Node Node to connect to
                   104722:     * @access  public
                   104723:     */
                   104724:     function connectTo(&$destinationNode) {
                   104725:         // We only connect to nodes
                   104726:         if (!is_a($destinationNode, 'Structures_Graph_Node')) return Pear::raiseError('Structures_Graph_Node::connectTo received an object that is not a Structures_Graph_Node', STRUCTURES_GRAPH_ERROR_GENERIC);
                   104727:         // Nodes must already be in graphs to be connected
                   104728:         if ($this->_graph == null) return Pear::raiseError('Structures_Graph_Node::connectTo Tried to connect a node that is not in a graph', STRUCTURES_GRAPH_ERROR_GENERIC);
                   104729:         if ($destinationNode->getGraph() == null) return Pear::raiseError('Structures_Graph_Node::connectTo Tried to connect to a node that is not in a graph', STRUCTURES_GRAPH_ERROR_GENERIC);
                   104730:         // Connect here
                   104731:         $this->_connectTo($destinationNode);
                   104732:         // If graph is undirected, connect back
                   104733:         if (!$this->_graph->isDirected()) {
                   104734:             $destinationNode->_connectTo($this);
                   104735:         }
                   104736:     }
                   104737:     /* }}} */
                   104738: 
                   104739:     /* getNeighbours {{{ */
                   104740:     /**
                   104741:     *
                   104742:     * Return nodes connected to this one.
                   104743:     * 
                   104744:     * @return   array   Array of nodes
                   104745:     * @access  public
                   104746:     */
                   104747:     function getNeighbours() {
                   104748:         return $this->_arcs;
                   104749:     }
                   104750:     /* }}} */
                   104751: 
                   104752:     /* connectsTo {{{ */
                   104753:     /**
                   104754:     *
                   104755:     * Test wether this node has an arc to the target node
                   104756:     *
                   104757:     * @return  boolean   True if the two nodes are connected
                   104758:     * @access  public
                   104759:     */
                   104760:     function connectsTo(&$target) {
                   104761:         if (version_compare(PHP_VERSION, '5.0.0') >= 0) {
                   104762:             return in_array($target, $this->getNeighbours(), true);
                   104763:         }
                   104764: 
                   104765:         $copy = $target;
                   104766:         $arcKeys = array_keys($this->_arcs);
                   104767:         foreach($arcKeys as $key) {
                   104768:             /* ZE1 chokes on this expression:
                   104769:                 if ($target === $arc) return true;
                   104770:               so, we'll use more convoluted stuff
                   104771:             */
                   104772:             $arc =& $this->_arcs[$key];
                   104773:             $target = true;
                   104774:             if ($arc === true) {
                   104775:                 $target = false;
                   104776:                 if ($arc === false) {
                   104777:                     $target = $copy;
                   104778:                     return true;
                   104779:                 }
                   104780:             }
                   104781:         }
                   104782:         $target = $copy;
                   104783:         return false;
                   104784:     }
                   104785:     /* }}} */
                   104786: 
                   104787:     /* inDegree {{{ */
                   104788:     /**
                   104789:     *
                   104790:     * Calculate the in degree of the node.
                   104791:     * 
                   104792:     * The indegree for a node is the number of arcs entering the node. For non directed graphs, 
                   104793:     * the indegree is equal to the outdegree.
                   104794:     *
                   104795:     * @return  integer  In degree of the node
                   104796:     * @access  public
                   104797:     */
                   104798:     function inDegree() {
                   104799:         if ($this->_graph == null) return 0;
                   104800:         if (!$this->_graph->isDirected()) return $this->outDegree();
                   104801:         $result = 0;
                   104802:         $graphNodes =& $this->_graph->getNodes();
                   104803:         foreach (array_keys($graphNodes) as $key) {
                   104804:             if ($graphNodes[$key]->connectsTo($this)) $result++;
                   104805:         }
                   104806:         return $result;
                   104807:         
                   104808:     }
                   104809:     /* }}} */
                   104810: 
                   104811:     /* outDegree {{{ */
                   104812:     /**
                   104813:     *
                   104814:     * Calculate the out degree of the node.
                   104815:     *
                   104816:     * The outdegree for a node is the number of arcs exiting the node. For non directed graphs,
                   104817:     * the outdegree is always equal to the indegree.
                   104818:     * 
                   104819:     * @return  integer  Out degree of the node
                   104820:     * @access  public
                   104821:     */
                   104822:     function outDegree() {
                   104823:         if ($this->_graph == null) return 0;
                   104824:         return sizeof($this->_arcs);
                   104825:     }
                   104826:     /* }}} */
                   104827: }
                   104828: ?>
                   104829: Structures_Graph-1.0.4/Structures/Graph.php0000644000076600000240000001316311461440275020243 0ustar  bbieberstaff<?php
                   104830: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
                   104831: // +-----------------------------------------------------------------------------+
                   104832: // | Copyright (c) 2003 Sérgio Gonçalves Carvalho                                |
                   104833: // +-----------------------------------------------------------------------------+
                   104834: // | This file is part of Structures_Graph.                                      |
                   104835: // |                                                                             |
                   104836: // | Structures_Graph is free software; you can redistribute it and/or modify    |
                   104837: // | it under the terms of the GNU Lesser General Public License as published by |
                   104838: // | the Free Software Foundation; either version 2.1 of the License, or         |
                   104839: // | (at your option) any later version.                                         |
                   104840: // |                                                                             |
                   104841: // | Structures_Graph is distributed in the hope that it will be useful,         |
                   104842: // | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
                   104843: // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
                   104844: // | GNU Lesser General Public License for more details.                         |
                   104845: // |                                                                             |
                   104846: // | You should have received a copy of the GNU Lesser General Public License    |
                   104847: // | along with Structures_Graph; if not, write to the Free Software             |
                   104848: // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
                   104849: // | 02111-1307 USA                                                              |
                   104850: // +-----------------------------------------------------------------------------+
                   104851: // | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com>                  |
                   104852: // +-----------------------------------------------------------------------------+
                   104853: //
                   104854: /**
                   104855:  * The Graph.php file contains the definition of the Structures_Graph class 
                   104856:  *
                   104857:  * @see Structures_Graph
                   104858:  * @package Structures_Graph
                   104859:  */
                   104860: 
                   104861: /* dependencies {{{ */
                   104862: /** PEAR base classes */
                   104863: require_once 'PEAR.php';
                   104864: /** Graph Node */
                   104865: require_once 'Structures/Graph/Node.php';
                   104866: /* }}} */
                   104867: 
                   104868: define('STRUCTURES_GRAPH_ERROR_GENERIC', 100);
                   104869: 
                   104870: /* class Structures_Graph {{{ */
                   104871: /**
                   104872:  * The Structures_Graph class represents a graph data structure. 
                   104873:  *
                   104874:  * A Graph is a data structure composed by a set of nodes, connected by arcs.
                   104875:  * Graphs may either be directed or undirected. In a directed graph, arcs are 
                   104876:  * directional, and can be traveled only one way. In an undirected graph, arcs
                   104877:  * are bidirectional, and can be traveled both ways.
                   104878:  *
                   104879:  * @author             Sérgio Carvalho <sergio.carvalho@portugalmail.com> 
                   104880:  * @copyright  (c) 2004 by Sérgio Carvalho
                   104881:  * @package Structures_Graph
                   104882:  */
                   104883: /* }}} */
                   104884: class Structures_Graph {
                   104885:     /* fields {{{ */
                   104886:     /**
                   104887:      * @access private
                   104888:      */
                   104889:     var $_nodes = array();
                   104890:     /**
                   104891:      * @access private
                   104892:      */
                   104893:     var $_directed = false;
                   104894:     /* }}} */
                   104895: 
                   104896:     /* Constructor {{{ */
                   104897:     /**
                   104898:     *
                   104899:     * Constructor
                   104900:     *
                   104901:     * @param    boolean    Set to true if the graph is directed. Set to false if it is not directed. (Optional, defaults to true)
                   104902:     * @access  public
                   104903:     */
                   104904:     function Structures_Graph($directed = true) {
                   104905:         $this->_directed = $directed;
                   104906:     }
                   104907:     /* }}} */
                   104908: 
                   104909:     /* isDirected {{{ */
                   104910:     /**
                   104911:     *
                   104912:     * Return true if a graph is directed
                   104913:     *
                   104914:     * @return  boolean  true if the graph is directed
                   104915:     * @access  public
                   104916:     */
                   104917:     function isDirected() {
                   104918:         return (boolean) $this->_directed;
                   104919:     }
                   104920:     /* }}} */
                   104921: 
                   104922:     /* addNode {{{ */
                   104923:     /**
                   104924:     *
                   104925:     * Add a Node to the Graph
                   104926:     *
                   104927:     * @param    Structures_Graph_Node   The node to be added.
                   104928:     * @access  public
                   104929:     */
                   104930:     function addNode(&$newNode) {
                   104931:         // We only add nodes
                   104932:         if (!is_a($newNode, 'Structures_Graph_Node')) return Pear::raiseError('Structures_Graph::addNode received an object that is not a Structures_Graph_Node', STRUCTURES_GRAPH_ERROR_GENERIC);
                   104933:         // Graphs are node *sets*, so duplicates are forbidden. We allow nodes that are exactly equal, but disallow equal references.
                   104934:         foreach($this->_nodes as $key => $node) {
                   104935:             /*
                   104936:              ZE1 equality operators choke on the recursive cycle introduced by the _graph field in the Node object.
                   104937:              So, we'll check references the hard way (change $this->_nodes[$key] and check if the change reflects in 
                   104938:              $node)
                   104939:             */
                   104940:             $savedData = $this->_nodes[$key];
                   104941:             $referenceIsEqualFlag = false;
                   104942:             $this->_nodes[$key] = true;
                   104943:             if ($node === true) {
                   104944:                 $this->_nodes[$key] = false;
                   104945:                 if ($node === false) $referenceIsEqualFlag = true;
                   104946:             }
                   104947:             $this->_nodes[$key] = $savedData;
                   104948:             if ($referenceIsEqualFlag) return Pear::raiseError('Structures_Graph::addNode received an object that is a duplicate for this dataset', STRUCTURES_GRAPH_ERROR_GENERIC);
                   104949:         }
                   104950:         $this->_nodes[] =& $newNode;
                   104951:         $newNode->setGraph($this);
                   104952:     }
                   104953:     /* }}} */
                   104954: 
                   104955:     /* removeNode (unimplemented) {{{ */
                   104956:     /**
                   104957:     *
                   104958:     * Remove a Node from the Graph
                   104959:     *
                   104960:     * @todo     This is unimplemented
                   104961:     * @param    Structures_Graph_Node   The node to be removed from the graph
                   104962:     * @access  public
                   104963:     */
                   104964:     function removeNode(&$node) {
                   104965:     }
                   104966:     /* }}} */
                   104967: 
                   104968:     /* getNodes {{{ */
                   104969:     /**
                   104970:     *
                   104971:     * Return the node set, in no particular order. For ordered node sets, use a Graph Manipulator insted.
                   104972:     *
                   104973:     * @access   public
                   104974:     * @see      Structures_Graph_Manipulator_TopologicalSorter
                   104975:     * @return   array The set of nodes in this graph
                   104976:     */
                   104977:     function &getNodes() {
                   104978:         return $this->_nodes;
                   104979:     }
                   104980:     /* }}} */
                   104981: }
                   104982: ?>
                   104983: Structures_Graph-1.0.4/tests/testCase/BasicGraph.php0000644000076600000240000002161111461440275021734 0ustar  bbieberstaff<?php
                   104984: /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
                   104985: // +-----------------------------------------------------------------------------+
                   104986: // | Copyright (c) 2003 Sérgio Gonçalves Carvalho                                |
                   104987: // +-----------------------------------------------------------------------------+
                   104988: // | This file is part of Structures_Graph.                                      |
                   104989: // |                                                                             |
                   104990: // | Structures_Graph is free software; you can redistribute it and/or modify    |
                   104991: // | it under the terms of the GNU Lesser General Public License as published by |
                   104992: // | the Free Software Foundation; either version 2.1 of the License, or         |
                   104993: // | (at your option) any later version.                                         |
                   104994: // |                                                                             |
                   104995: // | Structures_Graph is distributed in the hope that it will be useful,         |
                   104996: // | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
                   104997: // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
                   104998: // | GNU Lesser General Public License for more details.                         |
                   104999: // |                                                                             |
                   105000: // | You should have received a copy of the GNU Lesser General Public License    |
                   105001: // | along with Structures_Graph; if not, write to the Free Software             |
                   105002: // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA                    |
                   105003: // | 02111-1307 USA                                                              |
                   105004: // +-----------------------------------------------------------------------------+
                   105005: // | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com>                  |
                   105006: // +-----------------------------------------------------------------------------+
                   105007: //
                   105008: 
                   105009: require_once 'Structures/Graph.php';
                   105010: require_once 'PHPUnit/Framework.php';
                   105011: 
                   105012: /**
                   105013:  * @access private
                   105014:  */
                   105015: class BasicGraph extends PHPUnit_Framework_TestCase
                   105016: {
                   105017:     var $_graph = null;
                   105018: 
                   105019:     function test_create_graph() {
                   105020:         $this->_graph = new Structures_Graph();
                   105021:         $this->assertTrue(is_a($this->_graph, 'Structures_Graph')); 
                   105022:     }
                   105023: 
                   105024:     function test_add_node() {
                   105025:         $this->_graph = new Structures_Graph();
                   105026:         $data = 1;
                   105027:         $node = new Structures_Graph_Node($data);
                   105028:         $this->_graph->addNode($node);
                   105029:         $node = new Structures_Graph_Node($data);
                   105030:         $this->_graph->addNode($node);
                   105031:         $node = new Structures_Graph_Node($data);
                   105032:         $this->_graph->addNode($node);
                   105033:     }
                   105034: 
                   105035:     function test_connect_node() {
                   105036:         $this->_graph = new Structures_Graph();
                   105037:         $data = 1;
                   105038:         $node1 = new Structures_Graph_Node($data);
                   105039:         $node2 = new Structures_Graph_Node($data);
                   105040:         $this->_graph->addNode($node1);
                   105041:         $this->_graph->addNode($node2);
                   105042:         $node1->connectTo($node2);
                   105043: 
                   105044:         $node =& $this->_graph->getNodes();
                   105045:         $node =& $node[0];
                   105046:         $node = $node->getNeighbours();
                   105047:         $node =& $node[0];
                   105048:         /* 
                   105049:          ZE1 == and === operators fail on $node,$node2 because of the recursion introduced
                   105050:          by the _graph field in the Node object. So, we'll use the stupid method for reference
                   105051:          testing
                   105052:         */
                   105053:         $node = true;
                   105054:         $this->assertTrue($node2);
                   105055:         $node = false;
                   105056:         $this->assertFalse($node2);
                   105057:     }
                   105058: 
                   105059:     function test_data_references() {
                   105060:         $this->_graph = new Structures_Graph();
                   105061:         $data = 1;
                   105062:         $node = new Structures_Graph_Node();
                   105063:         $node->setData(&$data);
                   105064:         $this->_graph->addNode($node);
                   105065:         $data = 2;
                   105066:         $dataInNode =& $this->_graph->getNodes();
                   105067:         $dataInNode =& $dataInNode[0];
                   105068:         $dataInNode =& $dataInNode->getData();
                   105069:         $this->assertTrue($data === $dataInNode);
                   105070:     }
                   105071: 
                   105072:     function test_metadata_references() {
                   105073:         $this->_graph = new Structures_Graph();
                   105074:         $data = 1;
                   105075:         $node = new Structures_Graph_Node();
                   105076:         $node->setMetadata('5', &$data);
                   105077:         $data = 2;
                   105078:         $dataInNode =& $node->getMetadata('5');
                   105079:         $this->assertTrue($data === $dataInNode);
                   105080:     }
                   105081:    
                   105082:     function test_metadata_key_exists() {
                   105083:         $this->_graph = new Structures_Graph();
                   105084:         $data = 1;
                   105085:         $node = new Structures_Graph_Node();
                   105086:         $node->setMetadata('5', $data);
                   105087:         $this->assertTrue($node->metadataKeyExists('5'));
                   105088:         $this->assertFalse($node->metadataKeyExists('1'));
                   105089:     }
                   105090: 
                   105091:     function test_directed_degree() {
                   105092:         $this->_graph = new Structures_Graph(true);
                   105093:         $node = array();
                   105094:         $node[] = new Structures_Graph_Node();
                   105095:         $node[] = new Structures_Graph_Node();
                   105096:         $node[] = new Structures_Graph_Node();
                   105097:         $this->_graph->addNode($node[0]);
                   105098:         $this->_graph->addNode($node[1]);
                   105099:         $this->_graph->addNode($node[2]);
                   105100:         $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 0 arcs');
                   105101:         $this->assertEquals(0, $node[1]->inDegree(), 'inDegree test failed for node 1 with 0 arcs');
                   105102:         $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 0 arcs');
                   105103:         $this->assertEquals(0, $node[0]->outDegree(), 'outDegree test failed for node 0 with 0 arcs');
                   105104:         $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 0 arcs');
                   105105:         $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 0 arcs');
                   105106:         $node[0]->connectTo($node[1]);
                   105107:         $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 1 arc');
                   105108:         $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 1 arc');
                   105109:         $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 1 arc');
                   105110:         $this->assertEquals(1, $node[0]->outDegree(), 'outDegree test failed for node 0 with 1 arc');
                   105111:         $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 1 arc');
                   105112:         $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 1 arc');
                   105113:         $node[0]->connectTo($node[2]);
                   105114:         $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 2 arcs');
                   105115:         $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 2 arcs');
                   105116:         $this->assertEquals(1, $node[2]->inDegree(), 'inDegree test failed for node 2 with 2 arcs');
                   105117:         $this->assertEquals(2, $node[0]->outDegree(), 'outDegree test failed for node 0 with 2 arcs');
                   105118:         $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 2 arcs');
                   105119:         $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 2 arcs');
                   105120:     }
                   105121: 
                   105122:     function test_undirected_degree() {
                   105123:         $this->_graph = new Structures_Graph(false);
                   105124:         $node = array();
                   105125:         $node[] = new Structures_Graph_Node();
                   105126:         $node[] = new Structures_Graph_Node();
                   105127:         $node[] = new Structures_Graph_Node();
                   105128:         $this->_graph->addNode($node[0]);
                   105129:         $this->_graph->addNode($node[1]);
                   105130:         $this->_graph->addNode($node[2]);
                   105131:         $this->assertEquals(0, $node[0]->inDegree(), 'inDegree test failed for node 0 with 0 arcs');
                   105132:         $this->assertEquals(0, $node[1]->inDegree(), 'inDegree test failed for node 1 with 0 arcs');
                   105133:         $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 0 arcs');
                   105134:         $this->assertEquals(0, $node[0]->outDegree(), 'outDegree test failed for node 0 with 0 arcs');
                   105135:         $this->assertEquals(0, $node[1]->outDegree(), 'outDegree test failed for node 1 with 0 arcs');
                   105136:         $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 0 arcs');
                   105137:         $node[0]->connectTo($node[1]);
                   105138:         $this->assertEquals(1, $node[0]->inDegree(), 'inDegree test failed for node 0 with 1 arc');
                   105139:         $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 1 arc');
                   105140:         $this->assertEquals(0, $node[2]->inDegree(), 'inDegree test failed for node 2 with 1 arc');
                   105141:         $this->assertEquals(1, $node[0]->outDegree(), 'outDegree test failed for node 0 with 1 arc');
                   105142:         $this->assertEquals(1, $node[1]->outDegree(), 'outDegree test failed for node 1 with 1 arc');
                   105143:         $this->assertEquals(0, $node[2]->outDegree(), 'outDegree test failed for node 2 with 1 arc');
                   105144:         $node[0]->connectTo($node[2]);
                   105145:         $this->assertEquals(2, $node[0]->inDegree(), 'inDegree test failed for node 0 with 2 arcs');
                   105146:         $this->assertEquals(1, $node[1]->inDegree(), 'inDegree test failed for node 1 with 2 arcs');
                   105147:         $this->assertEquals(1, $node[2]->inDegree(), 'inDegree test failed for node 2 with 2 arcs');
                   105148:         $this->assertEquals(2, $node[0]->outDegree(), 'outDegree test failed for node 0 with 2 arcs');
                   105149:         $this->assertEquals(1, $node[1]->outDegree(), 'outDegree test failed for node 1 with 2 arcs');
                   105150:         $this->assertEquals(1, $node[2]->outDegree(), 'outDegree test failed for node 2 with 2 arcs');
                   105151:     }
                   105152: }
                   105153: ?>
                   105154: Structures_Graph-1.0.4/tests/AllTests.php0000644000076600000240000000641411461440275017715 0ustar  bbieberstaff<?php
                   105155: 
                   105156: /**
                   105157:  * Master Unit Test Suite file for Structures_Graph
                   105158:  * 
                   105159:  * This top-level test suite file organizes 
                   105160:  * all class test suite files, 
                   105161:  * so that the full suite can be run 
                   105162:  * by PhpUnit or via "pear run-tests -u". 
                   105163:  *
                   105164:  * PHP version 5
                   105165:  *
                   105166:  * @category   XML
                   105167:  * @package    XML_Util
                   105168:  * @subpackage UnitTesting
                   105169:  * @author     Chuck Burgess <ashnazg@php.net>
                   105170:  * @license    http://www.opensource.org/licenses/bsd-license.php New BSD License
                   105171:  * @version    CVS: $Id$
                   105172:  * @link       http://pear.php.net/package/XML_Util
                   105173:  * @since      1.2.0a1
                   105174:  */
                   105175: 
                   105176: 
                   105177: /**
                   105178:  * Check PHP version... PhpUnit v3+ requires at least PHP v5.1.4
                   105179:  */
                   105180: if (version_compare(PHP_VERSION, "5.1.4") < 0) {
                   105181:     // Cannnot run test suites
                   105182:     echo 'Cannot run test suite via PhpUnit... requires at least PHP v5.1.4.' . PHP_EOL;
                   105183:     echo 'Use "pear run-tests -p xml_util" to run the PHPT tests directly.' . PHP_EOL;
                   105184:     exit(1);
                   105185: }
                   105186: 
                   105187: 
                   105188: /**
                   105189:  * Derive the "main" method name
                   105190:  * @internal PhpUnit would have to rename PHPUnit_MAIN_METHOD to PHPUNIT_MAIN_METHOD
                   105191:  *           to make this usage meet the PEAR CS... we cannot rename it here.
                   105192:  */
                   105193: if (!defined('PHPUnit_MAIN_METHOD')) {
                   105194:     define('PHPUnit_MAIN_METHOD', 'Structures_Graph_AllTests::main');
                   105195: }
                   105196: 
                   105197: 
                   105198: /*
                   105199:  * Files needed by PhpUnit
                   105200:  */
                   105201: require_once 'PHPUnit/Framework.php';
                   105202: require_once 'PHPUnit/TextUI/TestRunner.php';
                   105203: require_once 'PHPUnit/Extensions/PhptTestSuite.php';
                   105204: 
                   105205: /*
                   105206:  * You must add each additional class-level test suite file here
                   105207:  */
                   105208: require_once dirname(__FILE__).'/testCase/BasicGraph.php';
                   105209: 
                   105210: 
                   105211: /**
                   105212:  * Master Unit Test Suite class for Structures_Graph
                   105213:  * 
                   105214:  * This top-level test suite class organizes 
                   105215:  * all class test suite files, 
                   105216:  * so that the full suite can be run 
                   105217:  * by PhpUnit or via "pear run-tests -up Structures_Graph". 
                   105218:  *
                   105219:  * @category   Structures
                   105220:  * @package    Structures_Graph
                   105221:  * @subpackage UnitTesting
                   105222:  * @author     Chuck Burgess <ashnazg@php.net>
                   105223:  * @license    http://www.opensource.org/licenses/bsd-license.php New BSD License
                   105224:  * @version    Release: @package_version@
                   105225:  * @link       http://pear.php.net/package/XML_Util
                   105226:  * @since      1.2.0a1
                   105227:  */
                   105228: class Structures_Graph_AllTests
                   105229: {
                   105230: 
                   105231:     /**
                   105232:      * Launches the TextUI test runner
                   105233:      *
                   105234:      * @return void
                   105235:      * @uses PHPUnit_TextUI_TestRunner
                   105236:      */
                   105237:     public static function main()
                   105238:     {
                   105239:         PHPUnit_TextUI_TestRunner::run(self::suite());
                   105240:     }
                   105241: 
                   105242: 
                   105243:     /**
                   105244:      * Adds all class test suites into the master suite
                   105245:      *
                   105246:      * @return PHPUnit_Framework_TestSuite a master test suite
                   105247:      *                                     containing all class test suites
                   105248:      * @uses PHPUnit_Framework_TestSuite
                   105249:      */ 
                   105250:     public static function suite()
                   105251:     {
                   105252:         $suite = new PHPUnit_Framework_TestSuite(
                   105253:             'Structures_Graph Full Suite of Unit Tests');
                   105254: 
                   105255:         /*
                   105256:          * You must add each additional class-level test suite name here
                   105257:          */
                   105258:         $suite->addTestSuite('BasicGraph');
                   105259: 
                   105260:         return $suite;
                   105261:     }
                   105262: }
                   105263: 
                   105264: /**
                   105265:  * Call the main method if this file is executed directly
                   105266:  * @internal PhpUnit would have to rename PHPUnit_MAIN_METHOD to PHPUNIT_MAIN_METHOD
                   105267:  *           to make this usage meet the PEAR CS... we cannot rename it here.
                   105268:  */
                   105269: if (PHPUnit_MAIN_METHOD == 'Structures_Graph_AllTests::main') {
                   105270:     Structures_Graph_AllTests::main();
                   105271: }
                   105272: 
                   105273: /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
                   105274: ?>
                   105275: Structures_Graph-1.0.4/LICENSE0000644000076600000240000006347611461440275015327 0ustar  bbieberstaff             GNU LESSER GENERAL PUBLIC LICENSE
                   105276:                       Version 2.1, February 1999
                   105277: 
                   105278:  Copyright (C) 1991, 1999 Free Software Foundation, Inc.
                   105279:      59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                   105280:  Everyone is permitted to copy and distribute verbatim copies
                   105281:  of this license document, but changing it is not allowed.
                   105282: 
                   105283: [This is the first released version of the Lesser GPL.  It also counts
                   105284:  as the successor of the GNU Library Public License, version 2, hence
                   105285:  the version number 2.1.]
                   105286: 
                   105287:                            Preamble
                   105288: 
                   105289:   The licenses for most software are designed to take away your
                   105290: freedom to share and change it.  By contrast, the GNU General Public
                   105291: Licenses are intended to guarantee your freedom to share and change
                   105292: free software--to make sure the software is free for all its users.
                   105293: 
                   105294:   This license, the Lesser General Public License, applies to some
                   105295: specially designated software packages--typically libraries--of the
                   105296: Free Software Foundation and other authors who decide to use it.  You
                   105297: can use it too, but we suggest you first think carefully about whether
                   105298: this license or the ordinary General Public License is the better
                   105299: strategy to use in any particular case, based on the explanations below.
                   105300: 
                   105301:   When we speak of free software, we are referring to freedom of use,
                   105302: not price.  Our General Public Licenses are designed to make sure that
                   105303: you have the freedom to distribute copies of free software (and charge
                   105304: for this service if you wish); that you receive source code or can get
                   105305: it if you want it; that you can change the software and use pieces of
                   105306: it in new free programs; and that you are informed that you can do
                   105307: these things.
                   105308: 
                   105309:   To protect your rights, we need to make restrictions that forbid
                   105310: distributors to deny you these rights or to ask you to surrender these
                   105311: rights.  These restrictions translate to certain responsibilities for
                   105312: you if you distribute copies of the library or if you modify it.
                   105313: 
                   105314:   For example, if you distribute copies of the library, whether gratis
                   105315: or for a fee, you must give the recipients all the rights that we gave
                   105316: you.  You must make sure that they, too, receive or can get the source
                   105317: code.  If you link other code with the library, you must provide
                   105318: complete object files to the recipients, so that they can relink them
                   105319: with the library after making changes to the library and recompiling
                   105320: it.  And you must show them these terms so they know their rights.
                   105321: 
                   105322:   We protect your rights with a two-step method: (1) we copyright the
                   105323: library, and (2) we offer you this license, which gives you legal
                   105324: permission to copy, distribute and/or modify the library.
                   105325: 
                   105326:   To protect each distributor, we want to make it very clear that
                   105327: there is no warranty for the free library.  Also, if the library is
                   105328: modified by someone else and passed on, the recipients should know
                   105329: that what they have is not the original version, so that the original
                   105330: author's reputation will not be affected by problems that might be
                   105331: introduced by others.
                   105332: 
                   105333:   Finally, software patents pose a constant threat to the existence of
                   105334: any free program.  We wish to make sure that a company cannot
                   105335: effectively restrict the users of a free program by obtaining a
                   105336: restrictive license from a patent holder.  Therefore, we insist that
                   105337: any patent license obtained for a version of the library must be
                   105338: consistent with the full freedom of use specified in this license.
                   105339: 
                   105340:   Most GNU software, including some libraries, is covered by the
                   105341: ordinary GNU General Public License.  This license, the GNU Lesser
                   105342: General Public License, applies to certain designated libraries, and
                   105343: is quite different from the ordinary General Public License.  We use
                   105344: this license for certain libraries in order to permit linking those
                   105345: libraries into non-free programs.
                   105346: 
                   105347:   When a program is linked with a library, whether statically or using
                   105348: a shared library, the combination of the two is legally speaking a
                   105349: combined work, a derivative of the original library.  The ordinary
                   105350: General Public License therefore permits such linking only if the
                   105351: entire combination fits its criteria of freedom.  The Lesser General
                   105352: Public License permits more lax criteria for linking other code with
                   105353: the library.
                   105354: 
                   105355:   We call this license the "Lesser" General Public License because it
                   105356: does Less to protect the user's freedom than the ordinary General
                   105357: Public License.  It also provides other free software developers Less
                   105358: of an advantage over competing non-free programs.  These disadvantages
                   105359: are the reason we use the ordinary General Public License for many
                   105360: libraries.  However, the Lesser license provides advantages in certain
                   105361: special circumstances.
                   105362: 
                   105363:   For example, on rare occasions, there may be a special need to
                   105364: encourage the widest possible use of a certain library, so that it becomes
                   105365: a de-facto standard.  To achieve this, non-free programs must be
                   105366: allowed to use the library.  A more frequent case is that a free
                   105367: library does the same job as widely used non-free libraries.  In this
                   105368: case, there is little to gain by limiting the free library to free
                   105369: software only, so we use the Lesser General Public License.
                   105370: 
                   105371:   In other cases, permission to use a particular library in non-free
                   105372: programs enables a greater number of people to use a large body of
                   105373: free software.  For example, permission to use the GNU C Library in
                   105374: non-free programs enables many more people to use the whole GNU
                   105375: operating system, as well as its variant, the GNU/Linux operating
                   105376: system.
                   105377: 
                   105378:   Although the Lesser General Public License is Less protective of the
                   105379: users' freedom, it does ensure that the user of a program that is
                   105380: linked with the Library has the freedom and the wherewithal to run
                   105381: that program using a modified version of the Library.
                   105382: 
                   105383:   The precise terms and conditions for copying, distribution and
                   105384: modification follow.  Pay close attention to the difference between a
                   105385: "work based on the library" and a "work that uses the library".  The
                   105386: former contains code derived from the library, whereas the latter must
                   105387: be combined with the library in order to run.
                   105388: 
                   105389:                  GNU LESSER GENERAL PUBLIC LICENSE
                   105390:    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
                   105391: 
                   105392:   0. This License Agreement applies to any software library or other
                   105393: program which contains a notice placed by the copyright holder or
                   105394: other authorized party saying it may be distributed under the terms of
                   105395: this Lesser General Public License (also called "this License").
                   105396: Each licensee is addressed as "you".
                   105397: 
                   105398:   A "library" means a collection of software functions and/or data
                   105399: prepared so as to be conveniently linked with application programs
                   105400: (which use some of those functions and data) to form executables.
                   105401: 
                   105402:   The "Library", below, refers to any such software library or work
                   105403: which has been distributed under these terms.  A "work based on the
                   105404: Library" means either the Library or any derivative work under
                   105405: copyright law: that is to say, a work containing the Library or a
                   105406: portion of it, either verbatim or with modifications and/or translated
                   105407: straightforwardly into another language.  (Hereinafter, translation is
                   105408: included without limitation in the term "modification".)
                   105409: 
                   105410:   "Source code" for a work means the preferred form of the work for
                   105411: making modifications to it.  For a library, complete source code means
                   105412: all the source code for all modules it contains, plus any associated
                   105413: interface definition files, plus the scripts used to control compilation
                   105414: and installation of the library.
                   105415: 
                   105416:   Activities other than copying, distribution and modification are not
                   105417: covered by this License; they are outside its scope.  The act of
                   105418: running a program using the Library is not restricted, and output from
                   105419: such a program is covered only if its contents constitute a work based
                   105420: on the Library (independent of the use of the Library in a tool for
                   105421: writing it).  Whether that is true depends on what the Library does
                   105422: and what the program that uses the Library does.
                   105423:   
                   105424:   1. You may copy and distribute verbatim copies of the Library's
                   105425: complete source code as you receive it, in any medium, provided that
                   105426: you conspicuously and appropriately publish on each copy an
                   105427: appropriate copyright notice and disclaimer of warranty; keep intact
                   105428: all the notices that refer to this License and to the absence of any
                   105429: warranty; and distribute a copy of this License along with the
                   105430: Library.
                   105431: 
                   105432:   You may charge a fee for the physical act of transferring a copy,
                   105433: and you may at your option offer warranty protection in exchange for a
                   105434: fee.
                   105435: 
                   105436:   2. You may modify your copy or copies of the Library or any portion
                   105437: of it, thus forming a work based on the Library, and copy and
                   105438: distribute such modifications or work under the terms of Section 1
                   105439: above, provided that you also meet all of these conditions:
                   105440: 
                   105441:     a) The modified work must itself be a software library.
                   105442: 
                   105443:     b) You must cause the files modified to carry prominent notices
                   105444:     stating that you changed the files and the date of any change.
                   105445: 
                   105446:     c) You must cause the whole of the work to be licensed at no
                   105447:     charge to all third parties under the terms of this License.
                   105448: 
                   105449:     d) If a facility in the modified Library refers to a function or a
                   105450:     table of data to be supplied by an application program that uses
                   105451:     the facility, other than as an argument passed when the facility
                   105452:     is invoked, then you must make a good faith effort to ensure that,
                   105453:     in the event an application does not supply such function or
                   105454:     table, the facility still operates, and performs whatever part of
                   105455:     its purpose remains meaningful.
                   105456: 
                   105457:     (For example, a function in a library to compute square roots has
                   105458:     a purpose that is entirely well-defined independent of the
                   105459:     application.  Therefore, Subsection 2d requires that any
                   105460:     application-supplied function or table used by this function must
                   105461:     be optional: if the application does not supply it, the square
                   105462:     root function must still compute square roots.)
                   105463: 
                   105464: These requirements apply to the modified work as a whole.  If
                   105465: identifiable sections of that work are not derived from the Library,
                   105466: and can be reasonably considered independent and separate works in
                   105467: themselves, then this License, and its terms, do not apply to those
                   105468: sections when you distribute them as separate works.  But when you
                   105469: distribute the same sections as part of a whole which is a work based
                   105470: on the Library, the distribution of the whole must be on the terms of
                   105471: this License, whose permissions for other licensees extend to the
                   105472: entire whole, and thus to each and every part regardless of who wrote
                   105473: it.
                   105474: 
                   105475: Thus, it is not the intent of this section to claim rights or contest
                   105476: your rights to work written entirely by you; rather, the intent is to
                   105477: exercise the right to control the distribution of derivative or
                   105478: collective works based on the Library.
                   105479: 
                   105480: In addition, mere aggregation of another work not based on the Library
                   105481: with the Library (or with a work based on the Library) on a volume of
                   105482: a storage or distribution medium does not bring the other work under
                   105483: the scope of this License.
                   105484: 
                   105485:   3. You may opt to apply the terms of the ordinary GNU General Public
                   105486: License instead of this License to a given copy of the Library.  To do
                   105487: this, you must alter all the notices that refer to this License, so
                   105488: that they refer to the ordinary GNU General Public License, version 2,
                   105489: instead of to this License.  (If a newer version than version 2 of the
                   105490: ordinary GNU General Public License has appeared, then you can specify
                   105491: that version instead if you wish.)  Do not make any other change in
                   105492: these notices.
                   105493: 
                   105494:   Once this change is made in a given copy, it is irreversible for
                   105495: that copy, so the ordinary GNU General Public License applies to all
                   105496: subsequent copies and derivative works made from that copy.
                   105497: 
                   105498:   This option is useful when you wish to copy part of the code of
                   105499: the Library into a program that is not a library.
                   105500: 
                   105501:   4. You may copy and distribute the Library (or a portion or
                   105502: derivative of it, under Section 2) in object code or executable form
                   105503: under the terms of Sections 1 and 2 above provided that you accompany
                   105504: it with the complete corresponding machine-readable source code, which
                   105505: must be distributed under the terms of Sections 1 and 2 above on a
                   105506: medium customarily used for software interchange.
                   105507: 
                   105508:   If distribution of object code is made by offering access to copy
                   105509: from a designated place, then offering equivalent access to copy the
                   105510: source code from the same place satisfies the requirement to
                   105511: distribute the source code, even though third parties are not
                   105512: compelled to copy the source along with the object code.
                   105513: 
                   105514:   5. A program that contains no derivative of any portion of the
                   105515: Library, but is designed to work with the Library by being compiled or
                   105516: linked with it, is called a "work that uses the Library".  Such a
                   105517: work, in isolation, is not a derivative work of the Library, and
                   105518: therefore falls outside the scope of this License.
                   105519: 
                   105520:   However, linking a "work that uses the Library" with the Library
                   105521: creates an executable that is a derivative of the Library (because it
                   105522: contains portions of the Library), rather than a "work that uses the
                   105523: library".  The executable is therefore covered by this License.
                   105524: Section 6 states terms for distribution of such executables.
                   105525: 
                   105526:   When a "work that uses the Library" uses material from a header file
                   105527: that is part of the Library, the object code for the work may be a
                   105528: derivative work of the Library even though the source code is not.
                   105529: Whether this is true is especially significant if the work can be
                   105530: linked without the Library, or if the work is itself a library.  The
                   105531: threshold for this to be true is not precisely defined by law.
                   105532: 
                   105533:   If such an object file uses only numerical parameters, data
                   105534: structure layouts and accessors, and small macros and small inline
                   105535: functions (ten lines or less in length), then the use of the object
                   105536: file is unrestricted, regardless of whether it is legally a derivative
                   105537: work.  (Executables containing this object code plus portions of the
                   105538: Library will still fall under Section 6.)
                   105539: 
                   105540:   Otherwise, if the work is a derivative of the Library, you may
                   105541: distribute the object code for the work under the terms of Section 6.
                   105542: Any executables containing that work also fall under Section 6,
                   105543: whether or not they are linked directly with the Library itself.
                   105544: 
                   105545:   6. As an exception to the Sections above, you may also combine or
                   105546: link a "work that uses the Library" with the Library to produce a
                   105547: work containing portions of the Library, and distribute that work
                   105548: under terms of your choice, provided that the terms permit
                   105549: modification of the work for the customer's own use and reverse
                   105550: engineering for debugging such modifications.
                   105551: 
                   105552:   You must give prominent notice with each copy of the work that the
                   105553: Library is used in it and that the Library and its use are covered by
                   105554: this License.  You must supply a copy of this License.  If the work
                   105555: during execution displays copyright notices, you must include the
                   105556: copyright notice for the Library among them, as well as a reference
                   105557: directing the user to the copy of this License.  Also, you must do one
                   105558: of these things:
                   105559: 
                   105560:     a) Accompany the work with the complete corresponding
                   105561:     machine-readable source code for the Library including whatever
                   105562:     changes were used in the work (which must be distributed under
                   105563:     Sections 1 and 2 above); and, if the work is an executable linked
                   105564:     with the Library, with the complete machine-readable "work that
                   105565:     uses the Library", as object code and/or source code, so that the
                   105566:     user can modify the Library and then relink to produce a modified
                   105567:     executable containing the modified Library.  (It is understood
                   105568:     that the user who changes the contents of definitions files in the
                   105569:     Library will not necessarily be able to recompile the application
                   105570:     to use the modified definitions.)
                   105571: 
                   105572:     b) Use a suitable shared library mechanism for linking with the
                   105573:     Library.  A suitable mechanism is one that (1) uses at run time a
                   105574:     copy of the library already present on the user's computer system,
                   105575:     rather than copying library functions into the executable, and (2)
                   105576:     will operate properly with a modified version of the library, if
                   105577:     the user installs one, as long as the modified version is
                   105578:     interface-compatible with the version that the work was made with.
                   105579: 
                   105580:     c) Accompany the work with a written offer, valid for at
                   105581:     least three years, to give the same user the materials
                   105582:     specified in Subsection 6a, above, for a charge no more
                   105583:     than the cost of performing this distribution.
                   105584: 
                   105585:     d) If distribution of the work is made by offering access to copy
                   105586:     from a designated place, offer equivalent access to copy the above
                   105587:     specified materials from the same place.
                   105588: 
                   105589:     e) Verify that the user has already received a copy of these
                   105590:     materials or that you have already sent this user a copy.
                   105591: 
                   105592:   For an executable, the required form of the "work that uses the
                   105593: Library" must include any data and utility programs needed for
                   105594: reproducing the executable from it.  However, as a special exception,
                   105595: the materials to be distributed need not include anything that is
                   105596: normally distributed (in either source or binary form) with the major
                   105597: components (compiler, kernel, and so on) of the operating system on
                   105598: which the executable runs, unless that component itself accompanies
                   105599: the executable.
                   105600: 
                   105601:   It may happen that this requirement contradicts the license
                   105602: restrictions of other proprietary libraries that do not normally
                   105603: accompany the operating system.  Such a contradiction means you cannot
                   105604: use both them and the Library together in an executable that you
                   105605: distribute.
                   105606: 
                   105607:   7. You may place library facilities that are a work based on the
                   105608: Library side-by-side in a single library together with other library
                   105609: facilities not covered by this License, and distribute such a combined
                   105610: library, provided that the separate distribution of the work based on
                   105611: the Library and of the other library facilities is otherwise
                   105612: permitted, and provided that you do these two things:
                   105613: 
                   105614:     a) Accompany the combined library with a copy of the same work
                   105615:     based on the Library, uncombined with any other library
                   105616:     facilities.  This must be distributed under the terms of the
                   105617:     Sections above.
                   105618: 
                   105619:     b) Give prominent notice with the combined library of the fact
                   105620:     that part of it is a work based on the Library, and explaining
                   105621:     where to find the accompanying uncombined form of the same work.
                   105622: 
                   105623:   8. You may not copy, modify, sublicense, link with, or distribute
                   105624: the Library except as expressly provided under this License.  Any
                   105625: attempt otherwise to copy, modify, sublicense, link with, or
                   105626: distribute the Library is void, and will automatically terminate your
                   105627: rights under this License.  However, parties who have received copies,
                   105628: or rights, from you under this License will not have their licenses
                   105629: terminated so long as such parties remain in full compliance.
                   105630: 
                   105631:   9. You are not required to accept this License, since you have not
                   105632: signed it.  However, nothing else grants you permission to modify or
                   105633: distribute the Library or its derivative works.  These actions are
                   105634: prohibited by law if you do not accept this License.  Therefore, by
                   105635: modifying or distributing the Library (or any work based on the
                   105636: Library), you indicate your acceptance of this License to do so, and
                   105637: all its terms and conditions for copying, distributing or modifying
                   105638: the Library or works based on it.
                   105639: 
                   105640:   10. Each time you redistribute the Library (or any work based on the
                   105641: Library), the recipient automatically receives a license from the
                   105642: original licensor to copy, distribute, link with or modify the Library
                   105643: subject to these terms and conditions.  You may not impose any further
                   105644: restrictions on the recipients' exercise of the rights granted herein.
                   105645: You are not responsible for enforcing compliance by third parties with
                   105646: this License.
                   105647: 
                   105648:   11. If, as a consequence of a court judgment or allegation of patent
                   105649: infringement or for any other reason (not limited to patent issues),
                   105650: conditions are imposed on you (whether by court order, agreement or
                   105651: otherwise) that contradict the conditions of this License, they do not
                   105652: excuse you from the conditions of this License.  If you cannot
                   105653: distribute so as to satisfy simultaneously your obligations under this
                   105654: License and any other pertinent obligations, then as a consequence you
                   105655: may not distribute the Library at all.  For example, if a patent
                   105656: license would not permit royalty-free redistribution of the Library by
                   105657: all those who receive copies directly or indirectly through you, then
                   105658: the only way you could satisfy both it and this License would be to
                   105659: refrain entirely from distribution of the Library.
                   105660: 
                   105661: If any portion of this section is held invalid or unenforceable under any
                   105662: particular circumstance, the balance of the section is intended to apply,
                   105663: and the section as a whole is intended to apply in other circumstances.
                   105664: 
                   105665: It is not the purpose of this section to induce you to infringe any
                   105666: patents or other property right claims or to contest validity of any
                   105667: such claims; this section has the sole purpose of protecting the
                   105668: integrity of the free software distribution system which is
                   105669: implemented by public license practices.  Many people have made
                   105670: generous contributions to the wide range of software distributed
                   105671: through that system in reliance on consistent application of that
                   105672: system; it is up to the author/donor to decide if he or she is willing
                   105673: to distribute software through any other system and a licensee cannot
                   105674: impose that choice.
                   105675: 
                   105676: This section is intended to make thoroughly clear what is believed to
                   105677: be a consequence of the rest of this License.
                   105678: 
                   105679:   12. If the distribution and/or use of the Library is restricted in
                   105680: certain countries either by patents or by copyrighted interfaces, the
                   105681: original copyright holder who places the Library under this License may add
                   105682: an explicit geographical distribution limitation excluding those countries,
                   105683: so that distribution is permitted only in or among countries not thus
                   105684: excluded.  In such case, this License incorporates the limitation as if
                   105685: written in the body of this License.
                   105686: 
                   105687:   13. The Free Software Foundation may publish revised and/or new
                   105688: versions of the Lesser General Public License from time to time.
                   105689: Such new versions will be similar in spirit to the present version,
                   105690: but may differ in detail to address new problems or concerns.
                   105691: 
                   105692: Each version is given a distinguishing version number.  If the Library
                   105693: specifies a version number of this License which applies to it and
                   105694: "any later version", you have the option of following the terms and
                   105695: conditions either of that version or of any later version published by
                   105696: the Free Software Foundation.  If the Library does not specify a
                   105697: license version number, you may choose any version ever published by
                   105698: the Free Software Foundation.
                   105699: 
                   105700:   14. If you wish to incorporate parts of the Library into other free
                   105701: programs whose distribution conditions are incompatible with these,
                   105702: write to the author to ask for permission.  For software which is
                   105703: copyrighted by the Free Software Foundation, write to the Free
                   105704: Software Foundation; we sometimes make exceptions for this.  Our
                   105705: decision will be guided by the two goals of preserving the free status
                   105706: of all derivatives of our free software and of promoting the sharing
                   105707: and reuse of software generally.
                   105708: 
                   105709:                            NO WARRANTY
                   105710: 
                   105711:   15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
                   105712: WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
                   105713: EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
                   105714: OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
                   105715: KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
                   105716: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                   105717: PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
                   105718: LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
                   105719: THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
                   105720: 
                   105721:   16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
                   105722: WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
                   105723: AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
                   105724: FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
                   105725: CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
                   105726: LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
                   105727: RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
                   105728: FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
                   105729: SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
                   105730: DAMAGES.
                   105731: 
                   105732:                     END OF TERMS AND CONDITIONS
                   105733: 
                   105734:            How to Apply These Terms to Your New Libraries
                   105735: 
                   105736:   If you develop a new library, and you want it to be of the greatest
                   105737: possible use to the public, we recommend making it free software that
                   105738: everyone can redistribute and change.  You can do so by permitting
                   105739: redistribution under these terms (or, alternatively, under the terms of the
                   105740: ordinary General Public License).
                   105741: 
                   105742:   To apply these terms, attach the following notices to the library.  It is
                   105743: safest to attach them to the start of each source file to most effectively
                   105744: convey the exclusion of warranty; and each file should have at least the
                   105745: "copyright" line and a pointer to where the full notice is found.
                   105746: 
                   105747:     <one line to give the library's name and a brief idea of what it does.>
                   105748:     Copyright (C) <year>  <name of author>
                   105749: 
                   105750:     This library is free software; you can redistribute it and/or
                   105751:     modify it under the terms of the GNU Lesser General Public
                   105752:     License as published by the Free Software Foundation; either
                   105753:     version 2.1 of the License, or (at your option) any later version.
                   105754: 
                   105755:     This library is distributed in the hope that it will be useful,
                   105756:     but WITHOUT ANY WARRANTY; without even the implied warranty of
                   105757:     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                   105758:     Lesser General Public License for more details.
                   105759: 
                   105760:     You should have received a copy of the GNU Lesser General Public
                   105761:     License along with this library; if not, write to the Free Software
                   105762:     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                   105763: 
                   105764: Also add information on how to contact you by electronic and paper mail.
                   105765: 
                   105766: You should also get your employer (if you work as a programmer) or your
                   105767: school, if any, to sign a "copyright disclaimer" for the library, if
                   105768: necessary.  Here is a sample; alter the names:
                   105769: 
                   105770:   Yoyodyne, Inc., hereby disclaims all copyright interest in the
                   105771:   library `Frob' (a library for tweaking knobs) written by James Random Hacker.
                   105772: 
                   105773:   <signature of Ty Coon>, 1 April 1990
                   105774:   Ty Coon, President of Vice
                   105775: 
                   105776: That's all there is to it!
                   105777: 
                   105778: 
                   105779: <?php
                   105780: /**
                   105781:  * File/Directory manipulation
                   105782:  *
                   105783:  * PHP versions 4 and 5
                   105784:  *
                   105785:  * @category   pear
                   105786:  * @package    System
                   105787:  * @author     Tomas V.V.Cox <cox@idecnet.com>
                   105788:  * @copyright  1997-2009 The Authors
                   105789:  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    105790:  * @version    CVS: $Id: System.php 313024 2011-07-06 19:51:24Z dufuz $
1.1       misho    105791:  * @link       http://pear.php.net/package/PEAR
                   105792:  * @since      File available since Release 0.1
                   105793:  */
                   105794: 
                   105795: /**
                   105796:  * base class
                   105797:  */
                   105798: require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   105799: require_once 'phar://install-pear-nozlib.phar/' . 'Console/Getopt.php';
                   105800: 
                   105801: $GLOBALS['_System_temp_files'] = array();
                   105802: 
                   105803: /**
                   105804: * System offers cross plattform compatible system functions
                   105805: *
                   105806: * Static functions for different operations. Should work under
                   105807: * Unix and Windows. The names and usage has been taken from its respectively
                   105808: * GNU commands. The functions will return (bool) false on error and will
                   105809: * trigger the error with the PHP trigger_error() function (you can silence
                   105810: * the error by prefixing a '@' sign after the function call, but this
                   105811: * is not recommended practice.  Instead use an error handler with
                   105812: * {@link set_error_handler()}).
                   105813: *
                   105814: * Documentation on this class you can find in:
                   105815: * http://pear.php.net/manual/
                   105816: *
                   105817: * Example usage:
                   105818: * if (!@System::rm('-r file1 dir1')) {
                   105819: *    print "could not delete file1 or dir1";
                   105820: * }
                   105821: *
                   105822: * In case you need to to pass file names with spaces,
                   105823: * pass the params as an array:
                   105824: *
                   105825: * System::rm(array('-r', $file1, $dir1));
                   105826: *
                   105827: * @category   pear
                   105828: * @package    System
                   105829: * @author     Tomas V.V. Cox <cox@idecnet.com>
                   105830: * @copyright  1997-2006 The PHP Group
                   105831: * @license    http://opensource.org/licenses/bsd-license.php New BSD License
1.1.1.2 ! misho    105832: * @version    Release: 1.9.4
1.1       misho    105833: * @link       http://pear.php.net/package/PEAR
                   105834: * @since      Class available since Release 0.1
                   105835: * @static
                   105836: */
                   105837: class System
                   105838: {
                   105839:     /**
                   105840:      * returns the commandline arguments of a function
                   105841:      *
                   105842:      * @param    string  $argv           the commandline
                   105843:      * @param    string  $short_options  the allowed option short-tags
                   105844:      * @param    string  $long_options   the allowed option long-tags
                   105845:      * @return   array   the given options and there values
                   105846:      * @static
                   105847:      * @access private
                   105848:      */
                   105849:     function _parseArgs($argv, $short_options, $long_options = null)
                   105850:     {
                   105851:         if (!is_array($argv) && $argv !== null) {
                   105852:             // Find all items, quoted or otherwise
                   105853:             preg_match_all("/(?:[\"'])(.*?)(?:['\"])|([^\s]+)/", $argv, $av);
                   105854:             $argv = $av[1];
                   105855:             foreach ($av[2] as $k => $a) {
                   105856:                 if (empty($a)) {
                   105857:                     continue;
                   105858:                 }
                   105859:                 $argv[$k] = trim($a) ;
                   105860:             }
                   105861:         }
                   105862:         return Console_Getopt::getopt2($argv, $short_options, $long_options);
                   105863:     }
                   105864: 
                   105865:     /**
                   105866:      * Output errors with PHP trigger_error(). You can silence the errors
                   105867:      * with prefixing a "@" sign to the function call: @System::mkdir(..);
                   105868:      *
                   105869:      * @param mixed $error a PEAR error or a string with the error message
                   105870:      * @return bool false
                   105871:      * @static
                   105872:      * @access private
                   105873:      */
                   105874:     function raiseError($error)
                   105875:     {
                   105876:         if (PEAR::isError($error)) {
                   105877:             $error = $error->getMessage();
                   105878:         }
                   105879:         trigger_error($error, E_USER_WARNING);
                   105880:         return false;
                   105881:     }
                   105882: 
                   105883:     /**
                   105884:      * Creates a nested array representing the structure of a directory
                   105885:      *
                   105886:      * System::_dirToStruct('dir1', 0) =>
                   105887:      *   Array
                   105888:      *    (
                   105889:      *    [dirs] => Array
                   105890:      *        (
                   105891:      *            [0] => dir1
                   105892:      *        )
                   105893:      *
                   105894:      *    [files] => Array
                   105895:      *        (
                   105896:      *            [0] => dir1/file2
                   105897:      *            [1] => dir1/file3
                   105898:      *        )
                   105899:      *    )
                   105900:      * @param    string  $sPath      Name of the directory
                   105901:      * @param    integer $maxinst    max. deep of the lookup
                   105902:      * @param    integer $aktinst    starting deep of the lookup
                   105903:      * @param    bool    $silent     if true, do not emit errors.
                   105904:      * @return   array   the structure of the dir
                   105905:      * @static
                   105906:      * @access   private
                   105907:      */
                   105908:     function _dirToStruct($sPath, $maxinst, $aktinst = 0, $silent = false)
                   105909:     {
                   105910:         $struct = array('dirs' => array(), 'files' => array());
                   105911:         if (($dir = @opendir($sPath)) === false) {
                   105912:             if (!$silent) {
                   105913:                 System::raiseError("Could not open dir $sPath");
                   105914:             }
                   105915:             return $struct; // XXX could not open error
                   105916:         }
                   105917: 
                   105918:         $struct['dirs'][] = $sPath = realpath($sPath); // XXX don't add if '.' or '..' ?
                   105919:         $list = array();
                   105920:         while (false !== ($file = readdir($dir))) {
                   105921:             if ($file != '.' && $file != '..') {
                   105922:                 $list[] = $file;
                   105923:             }
                   105924:         }
                   105925: 
                   105926:         closedir($dir);
                   105927:         natsort($list);
                   105928:         if ($aktinst < $maxinst || $maxinst == 0) {
                   105929:             foreach ($list as $val) {
                   105930:                 $path = $sPath . DIRECTORY_SEPARATOR . $val;
                   105931:                 if (is_dir($path) && !is_link($path)) {
                   105932:                     $tmp    = System::_dirToStruct($path, $maxinst, $aktinst+1, $silent);
                   105933:                     $struct = array_merge_recursive($struct, $tmp);
                   105934:                 } else {
                   105935:                     $struct['files'][] = $path;
                   105936:                 }
                   105937:             }
                   105938:         }
                   105939: 
                   105940:         return $struct;
                   105941:     }
                   105942: 
                   105943:     /**
                   105944:      * Creates a nested array representing the structure of a directory and files
                   105945:      *
                   105946:      * @param    array $files Array listing files and dirs
                   105947:      * @return   array
                   105948:      * @static
                   105949:      * @see System::_dirToStruct()
                   105950:      */
                   105951:     function _multipleToStruct($files)
                   105952:     {
                   105953:         $struct = array('dirs' => array(), 'files' => array());
                   105954:         settype($files, 'array');
                   105955:         foreach ($files as $file) {
                   105956:             if (is_dir($file) && !is_link($file)) {
                   105957:                 $tmp    = System::_dirToStruct($file, 0);
                   105958:                 $struct = array_merge_recursive($tmp, $struct);
                   105959:             } else {
                   105960:                 if (!in_array($file, $struct['files'])) {
                   105961:                     $struct['files'][] = $file;
                   105962:                 }
                   105963:             }
                   105964:         }
                   105965:         return $struct;
                   105966:     }
                   105967: 
                   105968:     /**
                   105969:      * The rm command for removing files.
                   105970:      * Supports multiple files and dirs and also recursive deletes
                   105971:      *
                   105972:      * @param    string  $args   the arguments for rm
                   105973:      * @return   mixed   PEAR_Error or true for success
                   105974:      * @static
                   105975:      * @access   public
                   105976:      */
                   105977:     function rm($args)
                   105978:     {
                   105979:         $opts = System::_parseArgs($args, 'rf'); // "f" does nothing but I like it :-)
                   105980:         if (PEAR::isError($opts)) {
                   105981:             return System::raiseError($opts);
                   105982:         }
                   105983:         foreach ($opts[0] as $opt) {
                   105984:             if ($opt[0] == 'r') {
                   105985:                 $do_recursive = true;
                   105986:             }
                   105987:         }
                   105988:         $ret = true;
                   105989:         if (isset($do_recursive)) {
                   105990:             $struct = System::_multipleToStruct($opts[1]);
                   105991:             foreach ($struct['files'] as $file) {
                   105992:                 if (!@unlink($file)) {
                   105993:                     $ret = false;
                   105994:                 }
                   105995:             }
                   105996: 
                   105997:             rsort($struct['dirs']);
                   105998:             foreach ($struct['dirs'] as $dir) {
                   105999:                 if (!@rmdir($dir)) {
                   106000:                     $ret = false;
                   106001:                 }
                   106002:             }
                   106003:         } else {
                   106004:             foreach ($opts[1] as $file) {
                   106005:                 $delete = (is_dir($file)) ? 'rmdir' : 'unlink';
                   106006:                 if (!@$delete($file)) {
                   106007:                     $ret = false;
                   106008:                 }
                   106009:             }
                   106010:         }
                   106011:         return $ret;
                   106012:     }
                   106013: 
                   106014:     /**
                   106015:      * Make directories.
                   106016:      *
                   106017:      * The -p option will create parent directories
                   106018:      * @param    string  $args    the name of the director(y|ies) to create
                   106019:      * @return   bool    True for success
                   106020:      * @static
                   106021:      * @access   public
                   106022:      */
                   106023:     function mkDir($args)
                   106024:     {
                   106025:         $opts = System::_parseArgs($args, 'pm:');
                   106026:         if (PEAR::isError($opts)) {
                   106027:             return System::raiseError($opts);
                   106028:         }
                   106029: 
                   106030:         $mode = 0777; // default mode
                   106031:         foreach ($opts[0] as $opt) {
                   106032:             if ($opt[0] == 'p') {
                   106033:                 $create_parents = true;
                   106034:             } elseif ($opt[0] == 'm') {
                   106035:                 // if the mode is clearly an octal number (starts with 0)
                   106036:                 // convert it to decimal
                   106037:                 if (strlen($opt[1]) && $opt[1]{0} == '0') {
                   106038:                     $opt[1] = octdec($opt[1]);
                   106039:                 } else {
                   106040:                     // convert to int
                   106041:                     $opt[1] += 0;
                   106042:                 }
                   106043:                 $mode = $opt[1];
                   106044:             }
                   106045:         }
                   106046: 
                   106047:         $ret = true;
                   106048:         if (isset($create_parents)) {
                   106049:             foreach ($opts[1] as $dir) {
                   106050:                 $dirstack = array();
                   106051:                 while ((!file_exists($dir) || !is_dir($dir)) &&
                   106052:                         $dir != DIRECTORY_SEPARATOR) {
                   106053:                     array_unshift($dirstack, $dir);
                   106054:                     $dir = dirname($dir);
                   106055:                 }
                   106056: 
                   106057:                 while ($newdir = array_shift($dirstack)) {
                   106058:                     if (!is_writeable(dirname($newdir))) {
                   106059:                         $ret = false;
                   106060:                         break;
                   106061:                     }
                   106062: 
                   106063:                     if (!mkdir($newdir, $mode)) {
                   106064:                         $ret = false;
                   106065:                     }
                   106066:                 }
                   106067:             }
                   106068:         } else {
                   106069:             foreach($opts[1] as $dir) {
                   106070:                 if ((@file_exists($dir) || !is_dir($dir)) && !mkdir($dir, $mode)) {
                   106071:                     $ret = false;
                   106072:                 }
                   106073:             }
                   106074:         }
                   106075: 
                   106076:         return $ret;
                   106077:     }
                   106078: 
                   106079:     /**
                   106080:      * Concatenate files
                   106081:      *
                   106082:      * Usage:
                   106083:      * 1) $var = System::cat('sample.txt test.txt');
                   106084:      * 2) System::cat('sample.txt test.txt > final.txt');
                   106085:      * 3) System::cat('sample.txt test.txt >> final.txt');
                   106086:      *
                   106087:      * Note: as the class use fopen, urls should work also (test that)
                   106088:      *
                   106089:      * @param    string  $args   the arguments
                   106090:      * @return   boolean true on success
                   106091:      * @static
                   106092:      * @access   public
                   106093:      */
                   106094:     function &cat($args)
                   106095:     {
                   106096:         $ret = null;
                   106097:         $files = array();
                   106098:         if (!is_array($args)) {
                   106099:             $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY);
                   106100:         }
                   106101: 
                   106102:         $count_args = count($args);
                   106103:         for ($i = 0; $i < $count_args; $i++) {
                   106104:             if ($args[$i] == '>') {
                   106105:                 $mode = 'wb';
                   106106:                 $outputfile = $args[$i+1];
                   106107:                 break;
                   106108:             } elseif ($args[$i] == '>>') {
                   106109:                 $mode = 'ab+';
                   106110:                 $outputfile = $args[$i+1];
                   106111:                 break;
                   106112:             } else {
                   106113:                 $files[] = $args[$i];
                   106114:             }
                   106115:         }
                   106116:         $outputfd = false;
                   106117:         if (isset($mode)) {
                   106118:             if (!$outputfd = fopen($outputfile, $mode)) {
                   106119:                 $err = System::raiseError("Could not open $outputfile");
                   106120:                 return $err;
                   106121:             }
                   106122:             $ret = true;
                   106123:         }
                   106124:         foreach ($files as $file) {
                   106125:             if (!$fd = fopen($file, 'r')) {
                   106126:                 System::raiseError("Could not open $file");
                   106127:                 continue;
                   106128:             }
                   106129:             while ($cont = fread($fd, 2048)) {
                   106130:                 if (is_resource($outputfd)) {
                   106131:                     fwrite($outputfd, $cont);
                   106132:                 } else {
                   106133:                     $ret .= $cont;
                   106134:                 }
                   106135:             }
                   106136:             fclose($fd);
                   106137:         }
                   106138:         if (is_resource($outputfd)) {
                   106139:             fclose($outputfd);
                   106140:         }
                   106141:         return $ret;
                   106142:     }
                   106143: 
                   106144:     /**
                   106145:      * Creates temporary files or directories. This function will remove
                   106146:      * the created files when the scripts finish its execution.
                   106147:      *
                   106148:      * Usage:
                   106149:      *   1) $tempfile = System::mktemp("prefix");
                   106150:      *   2) $tempdir  = System::mktemp("-d prefix");
                   106151:      *   3) $tempfile = System::mktemp();
                   106152:      *   4) $tempfile = System::mktemp("-t /var/tmp prefix");
                   106153:      *
                   106154:      * prefix -> The string that will be prepended to the temp name
                   106155:      *           (defaults to "tmp").
                   106156:      * -d     -> A temporary dir will be created instead of a file.
                   106157:      * -t     -> The target dir where the temporary (file|dir) will be created. If
                   106158:      *           this param is missing by default the env vars TMP on Windows or
                   106159:      *           TMPDIR in Unix will be used. If these vars are also missing
                   106160:      *           c:\windows\temp or /tmp will be used.
                   106161:      *
                   106162:      * @param   string  $args  The arguments
                   106163:      * @return  mixed   the full path of the created (file|dir) or false
                   106164:      * @see System::tmpdir()
                   106165:      * @static
                   106166:      * @access  public
                   106167:      */
                   106168:     function mktemp($args = null)
                   106169:     {
                   106170:         static $first_time = true;
                   106171:         $opts = System::_parseArgs($args, 't:d');
                   106172:         if (PEAR::isError($opts)) {
                   106173:             return System::raiseError($opts);
                   106174:         }
                   106175: 
                   106176:         foreach ($opts[0] as $opt) {
                   106177:             if ($opt[0] == 'd') {
                   106178:                 $tmp_is_dir = true;
                   106179:             } elseif ($opt[0] == 't') {
                   106180:                 $tmpdir = $opt[1];
                   106181:             }
                   106182:         }
                   106183: 
                   106184:         $prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp';
                   106185:         if (!isset($tmpdir)) {
                   106186:             $tmpdir = System::tmpdir();
                   106187:         }
                   106188: 
                   106189:         if (!System::mkDir(array('-p', $tmpdir))) {
                   106190:             return false;
                   106191:         }
                   106192: 
                   106193:         $tmp = tempnam($tmpdir, $prefix);
                   106194:         if (isset($tmp_is_dir)) {
                   106195:             unlink($tmp); // be careful possible race condition here
                   106196:             if (!mkdir($tmp, 0700)) {
                   106197:                 return System::raiseError("Unable to create temporary directory $tmpdir");
                   106198:             }
                   106199:         }
                   106200: 
                   106201:         $GLOBALS['_System_temp_files'][] = $tmp;
                   106202:         if (isset($tmp_is_dir)) {
                   106203:             //$GLOBALS['_System_temp_files'][] = dirname($tmp);
                   106204:         }
                   106205: 
                   106206:         if ($first_time) {
                   106207:             PEAR::registerShutdownFunc(array('System', '_removeTmpFiles'));
                   106208:             $first_time = false;
                   106209:         }
                   106210: 
                   106211:         return $tmp;
                   106212:     }
                   106213: 
                   106214:     /**
                   106215:      * Remove temporary files created my mkTemp. This function is executed
                   106216:      * at script shutdown time
                   106217:      *
                   106218:      * @static
                   106219:      * @access private
                   106220:      */
                   106221:     function _removeTmpFiles()
                   106222:     {
                   106223:         if (count($GLOBALS['_System_temp_files'])) {
                   106224:             $delete = $GLOBALS['_System_temp_files'];
                   106225:             array_unshift($delete, '-r');
                   106226:             System::rm($delete);
                   106227:             $GLOBALS['_System_temp_files'] = array();
                   106228:         }
                   106229:     }
                   106230: 
                   106231:     /**
                   106232:      * Get the path of the temporal directory set in the system
                   106233:      * by looking in its environments variables.
                   106234:      * Note: php.ini-recommended removes the "E" from the variables_order setting,
                   106235:      * making unavaible the $_ENV array, that s why we do tests with _ENV
                   106236:      *
                   106237:      * @static
                   106238:      * @return string The temporary directory on the system
                   106239:      */
                   106240:     function tmpdir()
                   106241:     {
                   106242:         if (OS_WINDOWS) {
                   106243:             if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) {
                   106244:                 return $var;
                   106245:             }
                   106246:             if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) {
                   106247:                 return $var;
                   106248:             }
                   106249:             if ($var = isset($_ENV['USERPROFILE']) ? $_ENV['USERPROFILE'] : getenv('USERPROFILE')) {
                   106250:                 return $var;
                   106251:             }
                   106252:             if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) {
                   106253:                 return $var;
                   106254:             }
                   106255:             return getenv('SystemRoot') . '\temp';
                   106256:         }
                   106257:         if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) {
                   106258:             return $var;
                   106259:         }
                   106260:         return realpath('/tmp');
                   106261:     }
                   106262: 
                   106263:     /**
                   106264:      * The "which" command (show the full path of a command)
                   106265:      *
                   106266:      * @param string $program The command to search for
                   106267:      * @param mixed  $fallback Value to return if $program is not found
                   106268:      *
                   106269:      * @return mixed A string with the full path or false if not found
                   106270:      * @static
                   106271:      * @author Stig Bakken <ssb@php.net>
                   106272:      */
                   106273:     function which($program, $fallback = false)
                   106274:     {
                   106275:         // enforce API
                   106276:         if (!is_string($program) || '' == $program) {
                   106277:             return $fallback;
                   106278:         }
                   106279: 
                   106280:         // full path given
                   106281:         if (basename($program) != $program) {
                   106282:             $path_elements[] = dirname($program);
                   106283:             $program = basename($program);
                   106284:         } else {
                   106285:             // Honor safe mode
                   106286:             if (!ini_get('safe_mode') || !$path = ini_get('safe_mode_exec_dir')) {
                   106287:                 $path = getenv('PATH');
                   106288:                 if (!$path) {
                   106289:                     $path = getenv('Path'); // some OSes are just stupid enough to do this
                   106290:                 }
                   106291:             }
                   106292:             $path_elements = explode(PATH_SEPARATOR, $path);
                   106293:         }
                   106294: 
                   106295:         if (OS_WINDOWS) {
                   106296:             $exe_suffixes = getenv('PATHEXT')
                   106297:                                 ? explode(PATH_SEPARATOR, getenv('PATHEXT'))
                   106298:                                 : array('.exe','.bat','.cmd','.com');
                   106299:             // allow passing a command.exe param
                   106300:             if (strpos($program, '.') !== false) {
                   106301:                 array_unshift($exe_suffixes, '');
                   106302:             }
                   106303:             // is_executable() is not available on windows for PHP4
                   106304:             $pear_is_executable = (function_exists('is_executable')) ? 'is_executable' : 'is_file';
                   106305:         } else {
                   106306:             $exe_suffixes = array('');
                   106307:             $pear_is_executable = 'is_executable';
                   106308:         }
                   106309: 
                   106310:         foreach ($exe_suffixes as $suff) {
                   106311:             foreach ($path_elements as $dir) {
                   106312:                 $file = $dir . DIRECTORY_SEPARATOR . $program . $suff;
                   106313:                 if (@$pear_is_executable($file)) {
                   106314:                     return $file;
                   106315:                 }
                   106316:             }
                   106317:         }
                   106318:         return $fallback;
                   106319:     }
                   106320: 
                   106321:     /**
                   106322:      * The "find" command
                   106323:      *
                   106324:      * Usage:
                   106325:      *
                   106326:      * System::find($dir);
                   106327:      * System::find("$dir -type d");
                   106328:      * System::find("$dir -type f");
                   106329:      * System::find("$dir -name *.php");
                   106330:      * System::find("$dir -name *.php -name *.htm*");
                   106331:      * System::find("$dir -maxdepth 1");
                   106332:      *
                   106333:      * Params implmented:
                   106334:      * $dir            -> Start the search at this directory
                   106335:      * -type d         -> return only directories
                   106336:      * -type f         -> return only files
                   106337:      * -maxdepth <n>   -> max depth of recursion
                   106338:      * -name <pattern> -> search pattern (bash style). Multiple -name param allowed
                   106339:      *
                   106340:      * @param  mixed Either array or string with the command line
                   106341:      * @return array Array of found files
                   106342:      * @static
                   106343:      *
                   106344:      */
                   106345:     function find($args)
                   106346:     {
                   106347:         if (!is_array($args)) {
                   106348:             $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY);
                   106349:         }
                   106350:         $dir = realpath(array_shift($args));
                   106351:         if (!$dir) {
                   106352:             return array();
                   106353:         }
                   106354:         $patterns = array();
                   106355:         $depth = 0;
                   106356:         $do_files = $do_dirs = true;
                   106357:         $args_count = count($args);
                   106358:         for ($i = 0; $i < $args_count; $i++) {
                   106359:             switch ($args[$i]) {
                   106360:                 case '-type':
                   106361:                     if (in_array($args[$i+1], array('d', 'f'))) {
                   106362:                         if ($args[$i+1] == 'd') {
                   106363:                             $do_files = false;
                   106364:                         } else {
                   106365:                             $do_dirs = false;
                   106366:                         }
                   106367:                     }
                   106368:                     $i++;
                   106369:                     break;
                   106370:                 case '-name':
                   106371:                     $name = preg_quote($args[$i+1], '#');
                   106372:                     // our magic characters ? and * have just been escaped,
                   106373:                     // so now we change the escaped versions to PCRE operators
                   106374:                     $name = strtr($name, array('\?' => '.', '\*' => '.*'));
                   106375:                     $patterns[] = '('.$name.')';
                   106376:                     $i++;
                   106377:                     break;
                   106378:                 case '-maxdepth':
                   106379:                     $depth = $args[$i+1];
                   106380:                     break;
                   106381:             }
                   106382:         }
                   106383:         $path = System::_dirToStruct($dir, $depth, 0, true);
                   106384:         if ($do_files && $do_dirs) {
                   106385:             $files = array_merge($path['files'], $path['dirs']);
                   106386:         } elseif ($do_dirs) {
                   106387:             $files = $path['dirs'];
                   106388:         } else {
                   106389:             $files = $path['files'];
                   106390:         }
                   106391:         if (count($patterns)) {
                   106392:             $dsq = preg_quote(DIRECTORY_SEPARATOR, '#');
                   106393:             $pattern = '#(^|'.$dsq.')'.implode('|', $patterns).'($|'.$dsq.')#';
                   106394:             $ret = array();
                   106395:             $files_count = count($files);
                   106396:             for ($i = 0; $i < $files_count; $i++) {
                   106397:                 // only search in the part of the file below the current directory
                   106398:                 $filepart = basename($files[$i]);
                   106399:                 if (preg_match($pattern, $filepart)) {
                   106400:                     $ret[] = $files[$i];
                   106401:                 }
                   106402:             }
                   106403:             return $ret;
                   106404:         }
                   106405:         return $files;
                   106406:     }
                   106407: }<?php
                   106408: 
                   106409: /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
                   106410: 
                   106411: /**
                   106412:  * XML_Util
                   106413:  *
                   106414:  * XML Utilities package
1.1.1.2 ! misho    106415:  * 
1.1       misho    106416:  * PHP versions 4 and 5
                   106417:  *
                   106418:  * LICENSE:
                   106419:  *
                   106420:  * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
                   106421:  * All rights reserved.
                   106422:  *
                   106423:  * Redistribution and use in source and binary forms, with or without
                   106424:  * modification, are permitted provided that the following conditions
                   106425:  * are met:
                   106426:  *
                   106427:  *    * Redistributions of source code must retain the above copyright
                   106428:  *      notice, this list of conditions and the following disclaimer.
                   106429:  *    * Redistributions in binary form must reproduce the above copyright
                   106430:  *      notice, this list of conditions and the following disclaimer in the
                   106431:  *      documentation and/or other materials provided with the distribution.
                   106432:  *    * The name of the author may not be used to endorse or promote products
                   106433:  *      derived from this software without specific prior written permission.
                   106434:  *
                   106435:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
                   106436:  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
                   106437:  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                   106438:  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
                   106439:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                   106440:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                   106441:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
                   106442:  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
                   106443:  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
                   106444:  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
                   106445:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                   106446:  *
                   106447:  * @category  XML
                   106448:  * @package   XML_Util
                   106449:  * @author    Stephan Schmidt <schst@php.net>
                   106450:  * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
                   106451:  * @license   http://opensource.org/licenses/bsd-license New BSD License
1.1.1.2 ! misho    106452:  * @version   CVS: $Id: Util.php,v 1.38 2008/11/13 00:03:38 ashnazg Exp $
1.1       misho    106453:  * @link      http://pear.php.net/package/XML_Util
                   106454:  */
                   106455: 
                   106456: /**
                   106457:  * error code for invalid chars in XML name
                   106458:  */
                   106459: define('XML_UTIL_ERROR_INVALID_CHARS', 51);
                   106460: 
                   106461: /**
                   106462:  * error code for invalid chars in XML name
                   106463:  */
                   106464: define('XML_UTIL_ERROR_INVALID_START', 52);
                   106465: 
                   106466: /**
                   106467:  * error code for non-scalar tag content
                   106468:  */
                   106469: define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);
                   106470: 
                   106471: /**
                   106472:  * error code for missing tag name
                   106473:  */
                   106474: define('XML_UTIL_ERROR_NO_TAG_NAME', 61);
                   106475: 
                   106476: /**
                   106477:  * replace XML entities
                   106478:  */
                   106479: define('XML_UTIL_REPLACE_ENTITIES', 1);
                   106480: 
                   106481: /**
                   106482:  * embedd content in a CData Section
                   106483:  */
                   106484: define('XML_UTIL_CDATA_SECTION', 5);
                   106485: 
                   106486: /**
                   106487:  * do not replace entitites
                   106488:  */
                   106489: define('XML_UTIL_ENTITIES_NONE', 0);
                   106490: 
                   106491: /**
                   106492:  * replace all XML entitites
                   106493:  * This setting will replace <, >, ", ' and &
                   106494:  */
                   106495: define('XML_UTIL_ENTITIES_XML', 1);
                   106496: 
                   106497: /**
                   106498:  * replace only required XML entitites
                   106499:  * This setting will replace <, " and &
                   106500:  */
                   106501: define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);
                   106502: 
                   106503: /**
                   106504:  * replace HTML entitites
                   106505:  * @link http://www.php.net/htmlentities
                   106506:  */
                   106507: define('XML_UTIL_ENTITIES_HTML', 3);
                   106508: 
                   106509: /**
                   106510:  * Collapse all empty tags.
                   106511:  */
                   106512: define('XML_UTIL_COLLAPSE_ALL', 1);
                   106513: 
                   106514: /**
                   106515:  * Collapse only empty XHTML tags that have no end tag.
                   106516:  */
                   106517: define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);
                   106518: 
                   106519: /**
                   106520:  * utility class for working with XML documents
                   106521:  *
                   106522: 
                   106523:  * @category  XML
                   106524:  * @package   XML_Util
                   106525:  * @author    Stephan Schmidt <schst@php.net>
                   106526:  * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
                   106527:  * @license   http://opensource.org/licenses/bsd-license New BSD License
1.1.1.2 ! misho    106528:  * @version   Release: 1.2.1
1.1       misho    106529:  * @link      http://pear.php.net/package/XML_Util
                   106530:  */
                   106531: class XML_Util
                   106532: {
                   106533:     /**
                   106534:      * return API version
                   106535:      *
                   106536:      * @return string $version API version
                   106537:      * @access public
                   106538:      * @static
                   106539:      */
                   106540:     function apiVersion()
                   106541:     {
                   106542:         return '1.1';
                   106543:     }
                   106544: 
                   106545:     /**
                   106546:      * replace XML entities
                   106547:      *
                   106548:      * With the optional second parameter, you may select, which
                   106549:      * entities should be replaced.
                   106550:      *
                   106551:      * <code>
                   106552:      * require_once 'XML/Util.php';
                   106553:      *
                   106554:      * // replace XML entites:
                   106555:      * $string = XML_Util::replaceEntities('This string contains < & >.');
                   106556:      * </code>
                   106557:      *
                   106558:      * With the optional third parameter, you may pass the character encoding
                   106559:      * <code>
                   106560:      * require_once 'XML/Util.php';
                   106561:      *
                   106562:      * // replace XML entites in UTF-8:
                   106563:      * $string = XML_Util::replaceEntities(
                   106564:      *     'This string contains < & > as well as ä, ö, ß, à and ê',
                   106565:      *     XML_UTIL_ENTITIES_HTML,
                   106566:      *     'UTF-8'
                   106567:      * );
                   106568:      * </code>
                   106569:      *
1.1.1.2 ! misho    106570:      * @param string $string          string where XML special chars 
1.1       misho    106571:      *                                should be replaced
1.1.1.2 ! misho    106572:      * @param int    $replaceEntities setting for entities in attribute values 
        !          106573:      *                                (one of XML_UTIL_ENTITIES_XML, 
        !          106574:      *                                XML_UTIL_ENTITIES_XML_REQUIRED, 
1.1       misho    106575:      *                                XML_UTIL_ENTITIES_HTML)
                   106576:      * @param string $encoding        encoding value (if any)...
                   106577:      *                                must be a valid encoding as determined
                   106578:      *                                by the htmlentities() function
                   106579:      *
                   106580:      * @return string string with replaced chars
                   106581:      * @access public
                   106582:      * @static
                   106583:      * @see reverseEntities()
                   106584:      */
                   106585:     function replaceEntities($string, $replaceEntities = XML_UTIL_ENTITIES_XML,
                   106586:         $encoding = 'ISO-8859-1')
                   106587:     {
                   106588:         switch ($replaceEntities) {
                   106589:         case XML_UTIL_ENTITIES_XML:
                   106590:             return strtr($string, array(
                   106591:                 '&'  => '&amp;',
                   106592:                 '>'  => '&gt;',
                   106593:                 '<'  => '&lt;',
                   106594:                 '"'  => '&quot;',
                   106595:                 '\'' => '&apos;' ));
                   106596:             break;
                   106597:         case XML_UTIL_ENTITIES_XML_REQUIRED:
                   106598:             return strtr($string, array(
                   106599:                 '&' => '&amp;',
                   106600:                 '<' => '&lt;',
                   106601:                 '"' => '&quot;' ));
                   106602:             break;
                   106603:         case XML_UTIL_ENTITIES_HTML:
                   106604:             return htmlentities($string, ENT_COMPAT, $encoding);
                   106605:             break;
                   106606:         }
                   106607:         return $string;
                   106608:     }
                   106609: 
                   106610:     /**
                   106611:      * reverse XML entities
                   106612:      *
                   106613:      * With the optional second parameter, you may select, which
                   106614:      * entities should be reversed.
                   106615:      *
                   106616:      * <code>
                   106617:      * require_once 'XML/Util.php';
                   106618:      *
                   106619:      * // reverse XML entites:
                   106620:      * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
                   106621:      * </code>
                   106622:      *
                   106623:      * With the optional third parameter, you may pass the character encoding
                   106624:      * <code>
                   106625:      * require_once 'XML/Util.php';
                   106626:      *
                   106627:      * // reverse XML entites in UTF-8:
                   106628:      * $string = XML_Util::reverseEntities(
                   106629:      *     'This string contains &lt; &amp; &gt; as well as'
                   106630:      *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
                   106631:      *     XML_UTIL_ENTITIES_HTML,
                   106632:      *     'UTF-8'
                   106633:      * );
                   106634:      * </code>
                   106635:      *
1.1.1.2 ! misho    106636:      * @param string $string          string where XML special chars 
1.1       misho    106637:      *                                should be replaced
1.1.1.2 ! misho    106638:      * @param int    $replaceEntities setting for entities in attribute values 
        !          106639:      *                                (one of XML_UTIL_ENTITIES_XML, 
        !          106640:      *                                XML_UTIL_ENTITIES_XML_REQUIRED, 
1.1       misho    106641:      *                                XML_UTIL_ENTITIES_HTML)
                   106642:      * @param string $encoding        encoding value (if any)...
                   106643:      *                                must be a valid encoding as determined
                   106644:      *                                by the html_entity_decode() function
                   106645:      *
                   106646:      * @return string string with replaced chars
                   106647:      * @access public
                   106648:      * @static
                   106649:      * @see replaceEntities()
                   106650:      */
                   106651:     function reverseEntities($string, $replaceEntities = XML_UTIL_ENTITIES_XML,
                   106652:         $encoding = 'ISO-8859-1')
                   106653:     {
                   106654:         switch ($replaceEntities) {
                   106655:         case XML_UTIL_ENTITIES_XML:
                   106656:             return strtr($string, array(
                   106657:                 '&amp;'  => '&',
                   106658:                 '&gt;'   => '>',
                   106659:                 '&lt;'   => '<',
                   106660:                 '&quot;' => '"',
                   106661:                 '&apos;' => '\'' ));
                   106662:             break;
                   106663:         case XML_UTIL_ENTITIES_XML_REQUIRED:
                   106664:             return strtr($string, array(
                   106665:                 '&amp;'  => '&',
                   106666:                 '&lt;'   => '<',
                   106667:                 '&quot;' => '"' ));
                   106668:             break;
                   106669:         case XML_UTIL_ENTITIES_HTML:
                   106670:             return html_entity_decode($string, ENT_COMPAT, $encoding);
                   106671:             break;
                   106672:         }
                   106673:         return $string;
                   106674:     }
                   106675: 
                   106676:     /**
                   106677:      * build an xml declaration
                   106678:      *
                   106679:      * <code>
                   106680:      * require_once 'XML/Util.php';
                   106681:      *
                   106682:      * // get an XML declaration:
                   106683:      * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
                   106684:      * </code>
                   106685:      *
                   106686:      * @param string $version    xml version
                   106687:      * @param string $encoding   character encoding
                   106688:      * @param bool   $standalone document is standalone (or not)
                   106689:      *
                   106690:      * @return string xml declaration
                   106691:      * @access public
                   106692:      * @static
                   106693:      * @uses attributesToString() to serialize the attributes of the XML declaration
                   106694:      */
1.1.1.2 ! misho    106695:     function getXMLDeclaration($version = '1.0', $encoding = null, 
1.1       misho    106696:         $standalone = null)
                   106697:     {
                   106698:         $attributes = array(
                   106699:             'version' => $version,
                   106700:         );
                   106701:         // add encoding
                   106702:         if ($encoding !== null) {
                   106703:             $attributes['encoding'] = $encoding;
                   106704:         }
                   106705:         // add standalone, if specified
                   106706:         if ($standalone !== null) {
                   106707:             $attributes['standalone'] = $standalone ? 'yes' : 'no';
                   106708:         }
                   106709: 
1.1.1.2 ! misho    106710:         return sprintf('<?xml%s?>', 
1.1       misho    106711:             XML_Util::attributesToString($attributes, false));
                   106712:     }
                   106713: 
                   106714:     /**
                   106715:      * build a document type declaration
                   106716:      *
                   106717:      * <code>
                   106718:      * require_once 'XML/Util.php';
                   106719:      *
                   106720:      * // get a doctype declaration:
                   106721:      * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
                   106722:      * </code>
                   106723:      *
                   106724:      * @param string $root        name of the root tag
1.1.1.2 ! misho    106725:      * @param string $uri         uri of the doctype definition 
1.1       misho    106726:      *                            (or array with uri and public id)
                   106727:      * @param string $internalDtd internal dtd entries
                   106728:      *
                   106729:      * @return string doctype declaration
                   106730:      * @access public
                   106731:      * @static
                   106732:      * @since 0.2
                   106733:      */
                   106734:     function getDocTypeDeclaration($root, $uri = null, $internalDtd = null)
                   106735:     {
                   106736:         if (is_array($uri)) {
                   106737:             $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
                   106738:         } elseif (!empty($uri)) {
                   106739:             $ref = sprintf(' SYSTEM "%s"', $uri);
                   106740:         } else {
                   106741:             $ref = '';
                   106742:         }
                   106743: 
                   106744:         if (empty($internalDtd)) {
                   106745:             return sprintf('<!DOCTYPE %s%s>', $root, $ref);
                   106746:         } else {
                   106747:             return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
                   106748:         }
                   106749:     }
                   106750: 
                   106751:     /**
                   106752:      * create string representation of an attribute list
                   106753:      *
                   106754:      * <code>
                   106755:      * require_once 'XML/Util.php';
                   106756:      *
                   106757:      * // build an attribute string
                   106758:      * $att = array(
                   106759:      *              'foo'   =>  'bar',
                   106760:      *              'argh'  =>  'tomato'
                   106761:      *            );
                   106762:      *
                   106763:      * $attList = XML_Util::attributesToString($att);
                   106764:      * </code>
                   106765:      *
                   106766:      * @param array      $attributes attribute array
1.1.1.2 ! misho    106767:      * @param bool|array $sort       sort attribute list alphabetically, 
        !          106768:      *                               may also be an assoc array containing 
        !          106769:      *                               the keys 'sort', 'multiline', 'indent', 
1.1       misho    106770:      *                               'linebreak' and 'entities'
1.1.1.2 ! misho    106771:      * @param bool       $multiline  use linebreaks, if more than 
1.1       misho    106772:      *                               one attribute is given
1.1.1.2 ! misho    106773:      * @param string     $indent     string used for indentation of 
1.1       misho    106774:      *                               multiline attributes
1.1.1.2 ! misho    106775:      * @param string     $linebreak  string used for linebreaks of 
1.1       misho    106776:      *                               multiline attributes
1.1.1.2 ! misho    106777:      * @param int        $entities   setting for entities in attribute values 
        !          106778:      *                               (one of XML_UTIL_ENTITIES_NONE, 
        !          106779:      *                               XML_UTIL_ENTITIES_XML, 
        !          106780:      *                               XML_UTIL_ENTITIES_XML_REQUIRED, 
1.1       misho    106781:      *                               XML_UTIL_ENTITIES_HTML)
                   106782:      *
                   106783:      * @return string string representation of the attributes
                   106784:      * @access public
                   106785:      * @static
                   106786:      * @uses replaceEntities() to replace XML entities in attribute values
                   106787:      * @todo allow sort also to be an options array
                   106788:      */
1.1.1.2 ! misho    106789:     function attributesToString($attributes, $sort = true, $multiline = false, 
1.1       misho    106790:         $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML)
                   106791:     {
                   106792:         /*
                   106793:          * second parameter may be an array
                   106794:          */
                   106795:         if (is_array($sort)) {
                   106796:             if (isset($sort['multiline'])) {
                   106797:                 $multiline = $sort['multiline'];
                   106798:             }
                   106799:             if (isset($sort['indent'])) {
                   106800:                 $indent = $sort['indent'];
                   106801:             }
                   106802:             if (isset($sort['linebreak'])) {
                   106803:                 $multiline = $sort['linebreak'];
                   106804:             }
                   106805:             if (isset($sort['entities'])) {
                   106806:                 $entities = $sort['entities'];
                   106807:             }
                   106808:             if (isset($sort['sort'])) {
                   106809:                 $sort = $sort['sort'];
                   106810:             } else {
                   106811:                 $sort = true;
                   106812:             }
                   106813:         }
                   106814:         $string = '';
                   106815:         if (is_array($attributes) && !empty($attributes)) {
                   106816:             if ($sort) {
                   106817:                 ksort($attributes);
                   106818:             }
                   106819:             if ( !$multiline || count($attributes) == 1) {
                   106820:                 foreach ($attributes as $key => $value) {
                   106821:                     if ($entities != XML_UTIL_ENTITIES_NONE) {
                   106822:                         if ($entities === XML_UTIL_CDATA_SECTION) {
                   106823:                             $entities = XML_UTIL_ENTITIES_XML;
                   106824:                         }
                   106825:                         $value = XML_Util::replaceEntities($value, $entities);
                   106826:                     }
                   106827:                     $string .= ' ' . $key . '="' . $value . '"';
                   106828:                 }
                   106829:             } else {
                   106830:                 $first = true;
                   106831:                 foreach ($attributes as $key => $value) {
                   106832:                     if ($entities != XML_UTIL_ENTITIES_NONE) {
                   106833:                         $value = XML_Util::replaceEntities($value, $entities);
                   106834:                     }
                   106835:                     if ($first) {
                   106836:                         $string .= ' ' . $key . '="' . $value . '"';
                   106837:                         $first   = false;
                   106838:                     } else {
                   106839:                         $string .= $linebreak . $indent . $key . '="' . $value . '"';
                   106840:                     }
                   106841:                 }
                   106842:             }
                   106843:         }
                   106844:         return $string;
                   106845:     }
                   106846: 
                   106847:     /**
                   106848:      * Collapses empty tags.
                   106849:      *
                   106850:      * @param string $xml  XML
                   106851:      * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
                   106852:      *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
                   106853:      *
                   106854:      * @return string XML
                   106855:      * @access public
                   106856:      * @static
                   106857:      * @todo PEAR CS - unable to avoid "space after open parens" error
                   106858:      *       in the IF branch
                   106859:      */
1.1.1.2 ! misho    106860:     function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL) 
1.1       misho    106861:     {
                   106862:         if ($mode == XML_UTIL_COLLAPSE_XHTML_ONLY) {
                   106863:             return preg_replace(
                   106864:                 '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                   106865:                 . 'param)([^>]*)><\/\\1>/s',
                   106866:                 '<\\1\\2 />',
                   106867:                 $xml);
                   106868:         } else {
                   106869:             return preg_replace('/<(\w+)([^>]*)><\/\\1>/s', '<\\1\\2 />', $xml);
                   106870:         }
                   106871:     }
                   106872: 
                   106873:     /**
                   106874:      * create a tag
                   106875:      *
                   106876:      * This method will call XML_Util::createTagFromArray(), which
                   106877:      * is more flexible.
                   106878:      *
                   106879:      * <code>
                   106880:      * require_once 'XML/Util.php';
                   106881:      *
                   106882:      * // create an XML tag:
1.1.1.2 ! misho    106883:      * $tag = XML_Util::createTag('myNs:myTag', 
        !          106884:      *     array('foo' => 'bar'), 
        !          106885:      *     'This is inside the tag', 
1.1       misho    106886:      *     'http://www.w3c.org/myNs#');
                   106887:      * </code>
                   106888:      *
                   106889:      * @param string $qname           qualified tagname (including namespace)
                   106890:      * @param array  $attributes      array containg attributes
                   106891:      * @param mixed  $content         the content
                   106892:      * @param string $namespaceUri    URI of the namespace
1.1.1.2 ! misho    106893:      * @param int    $replaceEntities whether to replace XML special chars in 
        !          106894:      *                                content, embedd it in a CData section 
1.1       misho    106895:      *                                or none of both
1.1.1.2 ! misho    106896:      * @param bool   $multiline       whether to create a multiline tag where 
1.1       misho    106897:      *                                each attribute gets written to a single line
1.1.1.2 ! misho    106898:      * @param string $indent          string used to indent attributes 
        !          106899:      *                                (_auto indents attributes so they start 
1.1       misho    106900:      *                                at the same column)
                   106901:      * @param string $linebreak       string used for linebreaks
                   106902:      * @param bool   $sortAttributes  Whether to sort the attributes or not
                   106903:      *
                   106904:      * @return string XML tag
                   106905:      * @access public
                   106906:      * @static
                   106907:      * @see createTagFromArray()
                   106908:      * @uses createTagFromArray() to create the tag
                   106909:      */
1.1.1.2 ! misho    106910:     function createTag($qname, $attributes = array(), $content = null, 
        !          106911:         $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES, 
        !          106912:         $multiline = false, $indent = '_auto', $linebreak = "\n", 
1.1       misho    106913:         $sortAttributes = true)
                   106914:     {
                   106915:         $tag = array(
                   106916:             'qname'      => $qname,
                   106917:             'attributes' => $attributes
                   106918:         );
                   106919: 
                   106920:         // add tag content
                   106921:         if ($content !== null) {
                   106922:             $tag['content'] = $content;
                   106923:         }
                   106924: 
                   106925:         // add namespace Uri
                   106926:         if ($namespaceUri !== null) {
                   106927:             $tag['namespaceUri'] = $namespaceUri;
                   106928:         }
                   106929: 
1.1.1.2 ! misho    106930:         return XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, 
1.1       misho    106931:             $indent, $linebreak, $sortAttributes);
                   106932:     }
                   106933: 
                   106934:     /**
                   106935:      * create a tag from an array
                   106936:      * this method awaits an array in the following format
                   106937:      * <pre>
                   106938:      * array(
                   106939:      *     // qualified name of the tag
1.1.1.2 ! misho    106940:      *     'qname' => $qname        
1.1       misho    106941:      *
                   106942:      *     // namespace prefix (optional, if qname is specified or no namespace)
1.1.1.2 ! misho    106943:      *     'namespace' => $namespace    
1.1       misho    106944:      *
                   106945:      *     // local part of the tagname (optional, if qname is specified)
1.1.1.2 ! misho    106946:      *     'localpart' => $localpart,   
1.1       misho    106947:      *
                   106948:      *     // array containing all attributes (optional)
1.1.1.2 ! misho    106949:      *     'attributes' => array(),      
1.1       misho    106950:      *
                   106951:      *     // tag content (optional)
1.1.1.2 ! misho    106952:      *     'content' => $content,     
1.1       misho    106953:      *
                   106954:      *     // namespaceUri for the given namespace (optional)
1.1.1.2 ! misho    106955:      *     'namespaceUri' => $namespaceUri 
1.1       misho    106956:      * )
                   106957:      * </pre>
                   106958:      *
                   106959:      * <code>
                   106960:      * require_once 'XML/Util.php';
                   106961:      *
                   106962:      * $tag = array(
                   106963:      *     'qname'        => 'foo:bar',
                   106964:      *     'namespaceUri' => 'http://foo.com',
                   106965:      *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
                   106966:      *     'content'      => 'I\'m inside the tag',
                   106967:      * );
                   106968:      * // creating a tag with qualified name and namespaceUri
                   106969:      * $string = XML_Util::createTagFromArray($tag);
                   106970:      * </code>
                   106971:      *
                   106972:      * @param array  $tag             tag definition
1.1.1.2 ! misho    106973:      * @param int    $replaceEntities whether to replace XML special chars in 
        !          106974:      *                                content, embedd it in a CData section 
1.1       misho    106975:      *                                or none of both
1.1.1.2 ! misho    106976:      * @param bool   $multiline       whether to create a multiline tag where each 
1.1       misho    106977:      *                                attribute gets written to a single line
1.1.1.2 ! misho    106978:      * @param string $indent          string used to indent attributes 
        !          106979:      *                                (_auto indents attributes so they start 
1.1       misho    106980:      *                                at the same column)
                   106981:      * @param string $linebreak       string used for linebreaks
                   106982:      * @param bool   $sortAttributes  Whether to sort the attributes or not
                   106983:      *
                   106984:      * @return string XML tag
                   106985:      * @access public
                   106986:      * @static
                   106987:      * @see createTag()
                   106988:      * @uses attributesToString() to serialize the attributes of the tag
                   106989:      * @uses splitQualifiedName() to get local part and namespace of a qualified name
                   106990:      * @uses createCDataSection()
                   106991:      * @uses raiseError()
                   106992:      */
                   106993:     function createTagFromArray($tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
1.1.1.2 ! misho    106994:         $multiline = false, $indent = '_auto', $linebreak = "\n", 
1.1       misho    106995:         $sortAttributes = true)
                   106996:     {
                   106997:         if (isset($tag['content']) && !is_scalar($tag['content'])) {
                   106998:             return XML_Util::raiseError('Supplied non-scalar value as tag content',
                   106999:             XML_UTIL_ERROR_NON_SCALAR_CONTENT);
                   107000:         }
                   107001: 
                   107002:         if (!isset($tag['qname']) && !isset($tag['localPart'])) {
                   107003:             return XML_Util::raiseError('You must either supply a qualified name '
1.1.1.2 ! misho    107004:                 . '(qname) or local tag name (localPart).', 
1.1       misho    107005:                 XML_UTIL_ERROR_NO_TAG_NAME);
                   107006:         }
                   107007: 
                   107008:         // if no attributes hav been set, use empty attributes
                   107009:         if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
                   107010:             $tag['attributes'] = array();
                   107011:         }
                   107012: 
                   107013:         if (isset($tag['namespaces'])) {
                   107014:             foreach ($tag['namespaces'] as $ns => $uri) {
                   107015:                 $tag['attributes']['xmlns:' . $ns] = $uri;
                   107016:             }
                   107017:         }
                   107018: 
                   107019:         if (!isset($tag['qname'])) {
                   107020:             // qualified name is not given
                   107021: 
                   107022:             // check for namespace
                   107023:             if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                   107024:                 $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
                   107025:             } else {
                   107026:                 $tag['qname'] = $tag['localPart'];
                   107027:             }
                   107028:         } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
                   107029:             // namespace URI is set, but no namespace
                   107030: 
                   107031:             $parts = XML_Util::splitQualifiedName($tag['qname']);
                   107032: 
                   107033:             $tag['localPart'] = $parts['localPart'];
                   107034:             if (isset($parts['namespace'])) {
                   107035:                 $tag['namespace'] = $parts['namespace'];
                   107036:             }
                   107037:         }
                   107038: 
                   107039:         if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
                   107040:             // is a namespace given
                   107041:             if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                   107042:                 $tag['attributes']['xmlns:' . $tag['namespace']] =
                   107043:                     $tag['namespaceUri'];
                   107044:             } else {
                   107045:                 // define this Uri as the default namespace
                   107046:                 $tag['attributes']['xmlns'] = $tag['namespaceUri'];
                   107047:             }
                   107048:         }
                   107049: 
                   107050:         // check for multiline attributes
                   107051:         if ($multiline === true) {
                   107052:             if ($indent === '_auto') {
                   107053:                 $indent = str_repeat(' ', (strlen($tag['qname'])+2));
                   107054:             }
                   107055:         }
                   107056: 
                   107057:         // create attribute list
1.1.1.2 ! misho    107058:         $attList = XML_Util::attributesToString($tag['attributes'], 
1.1       misho    107059:             $sortAttributes, $multiline, $indent, $linebreak, $replaceEntities);
                   107060:         if (!isset($tag['content']) || (string)$tag['content'] == '') {
                   107061:             $tag = sprintf('<%s%s />', $tag['qname'], $attList);
                   107062:         } else {
                   107063:             switch ($replaceEntities) {
                   107064:             case XML_UTIL_ENTITIES_NONE:
                   107065:                 break;
                   107066:             case XML_UTIL_CDATA_SECTION:
                   107067:                 $tag['content'] = XML_Util::createCDataSection($tag['content']);
                   107068:                 break;
                   107069:             default:
1.1.1.2 ! misho    107070:                 $tag['content'] = XML_Util::replaceEntities($tag['content'], 
1.1       misho    107071:                     $replaceEntities);
                   107072:                 break;
                   107073:             }
                   107074:             $tag = sprintf('<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
                   107075:                 $tag['qname']);
                   107076:         }
                   107077:         return $tag;
                   107078:     }
                   107079: 
                   107080:     /**
                   107081:      * create a start element
                   107082:      *
                   107083:      * <code>
                   107084:      * require_once 'XML/Util.php';
                   107085:      *
                   107086:      * // create an XML start element:
1.1.1.2 ! misho    107087:      * $tag = XML_Util::createStartElement('myNs:myTag', 
1.1       misho    107088:      *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
                   107089:      * </code>
                   107090:      *
                   107091:      * @param string $qname          qualified tagname (including namespace)
                   107092:      * @param array  $attributes     array containg attributes
                   107093:      * @param string $namespaceUri   URI of the namespace
1.1.1.2 ! misho    107094:      * @param bool   $multiline      whether to create a multiline tag where each 
1.1       misho    107095:      *                               attribute gets written to a single line
                   107096:      * @param string $indent         string used to indent attributes (_auto indents
                   107097:      *                               attributes so they start at the same column)
                   107098:      * @param string $linebreak      string used for linebreaks
                   107099:      * @param bool   $sortAttributes Whether to sort the attributes or not
                   107100:      *
                   107101:      * @return string XML start element
                   107102:      * @access public
                   107103:      * @static
                   107104:      * @see createEndElement(), createTag()
                   107105:      */
                   107106:     function createStartElement($qname, $attributes = array(), $namespaceUri = null,
1.1.1.2 ! misho    107107:         $multiline = false, $indent = '_auto', $linebreak = "\n", 
1.1       misho    107108:         $sortAttributes = true)
                   107109:     {
                   107110:         // if no attributes hav been set, use empty attributes
                   107111:         if (!isset($attributes) || !is_array($attributes)) {
                   107112:             $attributes = array();
                   107113:         }
                   107114: 
                   107115:         if ($namespaceUri != null) {
                   107116:             $parts = XML_Util::splitQualifiedName($qname);
                   107117:         }
                   107118: 
                   107119:         // check for multiline attributes
                   107120:         if ($multiline === true) {
                   107121:             if ($indent === '_auto') {
                   107122:                 $indent = str_repeat(' ', (strlen($qname)+2));
                   107123:             }
                   107124:         }
                   107125: 
                   107126:         if ($namespaceUri != null) {
                   107127:             // is a namespace given
                   107128:             if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                   107129:                 $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
                   107130:             } else {
                   107131:                 // define this Uri as the default namespace
                   107132:                 $attributes['xmlns'] = $namespaceUri;
                   107133:             }
                   107134:         }
                   107135: 
                   107136:         // create attribute list
1.1.1.2 ! misho    107137:         $attList = XML_Util::attributesToString($attributes, $sortAttributes, 
1.1       misho    107138:             $multiline, $indent, $linebreak);
                   107139:         $element = sprintf('<%s%s>', $qname, $attList);
                   107140:         return  $element;
                   107141:     }
                   107142: 
                   107143:     /**
                   107144:      * create an end element
                   107145:      *
                   107146:      * <code>
                   107147:      * require_once 'XML/Util.php';
                   107148:      *
                   107149:      * // create an XML start element:
                   107150:      * $tag = XML_Util::createEndElement('myNs:myTag');
                   107151:      * </code>
                   107152:      *
                   107153:      * @param string $qname qualified tagname (including namespace)
                   107154:      *
                   107155:      * @return string XML end element
                   107156:      * @access public
                   107157:      * @static
                   107158:      * @see createStartElement(), createTag()
                   107159:      */
                   107160:     function createEndElement($qname)
                   107161:     {
                   107162:         $element = sprintf('</%s>', $qname);
                   107163:         return $element;
                   107164:     }
                   107165: 
                   107166:     /**
                   107167:      * create an XML comment
                   107168:      *
                   107169:      * <code>
                   107170:      * require_once 'XML/Util.php';
                   107171:      *
                   107172:      * // create an XML start element:
                   107173:      * $tag = XML_Util::createComment('I am a comment');
                   107174:      * </code>
                   107175:      *
                   107176:      * @param string $content content of the comment
                   107177:      *
                   107178:      * @return string XML comment
                   107179:      * @access public
                   107180:      * @static
                   107181:      */
                   107182:     function createComment($content)
                   107183:     {
                   107184:         $comment = sprintf('<!-- %s -->', $content);
                   107185:         return $comment;
                   107186:     }
                   107187: 
                   107188:     /**
                   107189:      * create a CData section
                   107190:      *
                   107191:      * <code>
                   107192:      * require_once 'XML/Util.php';
                   107193:      *
                   107194:      * // create a CData section
                   107195:      * $tag = XML_Util::createCDataSection('I am content.');
                   107196:      * </code>
                   107197:      *
                   107198:      * @param string $data data of the CData section
                   107199:      *
                   107200:      * @return string CData section with content
                   107201:      * @access public
                   107202:      * @static
                   107203:      */
                   107204:     function createCDataSection($data)
                   107205:     {
1.1.1.2 ! misho    107206:         return sprintf('<![CDATA[%s]]>', 
1.1       misho    107207:             preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data)));
                   107208: 
                   107209:     }
                   107210: 
                   107211:     /**
                   107212:      * split qualified name and return namespace and local part
                   107213:      *
                   107214:      * <code>
                   107215:      * require_once 'XML/Util.php';
                   107216:      *
                   107217:      * // split qualified tag
                   107218:      * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
                   107219:      * </code>
                   107220:      * the returned array will contain two elements:
                   107221:      * <pre>
                   107222:      * array(
                   107223:      *     'namespace' => 'xslt',
                   107224:      *     'localPart' => 'stylesheet'
                   107225:      * );
                   107226:      * </pre>
                   107227:      *
                   107228:      * @param string $qname     qualified tag name
                   107229:      * @param string $defaultNs default namespace (optional)
                   107230:      *
                   107231:      * @return array array containing namespace and local part
                   107232:      * @access public
                   107233:      * @static
                   107234:      */
                   107235:     function splitQualifiedName($qname, $defaultNs = null)
                   107236:     {
                   107237:         if (strstr($qname, ':')) {
                   107238:             $tmp = explode(':', $qname);
                   107239:             return array(
                   107240:                 'namespace' => $tmp[0],
                   107241:                 'localPart' => $tmp[1]
                   107242:             );
                   107243:         }
                   107244:         return array(
                   107245:             'namespace' => $defaultNs,
                   107246:             'localPart' => $qname
                   107247:         );
                   107248:     }
                   107249: 
                   107250:     /**
                   107251:      * check, whether string is valid XML name
                   107252:      *
                   107253:      * <p>XML names are used for tagname, attribute names and various
                   107254:      * other, lesser known entities.</p>
                   107255:      * <p>An XML name may only consist of alphanumeric characters,
                   107256:      * dashes, undescores and periods, and has to start with a letter
                   107257:      * or an underscore.</p>
                   107258:      *
                   107259:      * <code>
                   107260:      * require_once 'XML/Util.php';
                   107261:      *
                   107262:      * // verify tag name
                   107263:      * $result = XML_Util::isValidName('invalidTag?');
                   107264:      * if (is_a($result, 'PEAR_Error')) {
                   107265:      *    print 'Invalid XML name: ' . $result->getMessage();
                   107266:      * }
                   107267:      * </code>
                   107268:      *
                   107269:      * @param string $string string that should be checked
                   107270:      *
                   107271:      * @return mixed true, if string is a valid XML name, PEAR error otherwise
                   107272:      * @access public
                   107273:      * @static
                   107274:      * @todo support for other charsets
                   107275:      * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
                   107276:      */
                   107277:     function isValidName($string)
                   107278:     {
                   107279:         // check for invalid chars
1.1.1.2 ! misho    107280:         if (!preg_match('/^[[:alpha:]_]$/', $string{0})) {
1.1       misho    107281:             return XML_Util::raiseError('XML names may only start with letter '
                   107282:                 . 'or underscore', XML_UTIL_ERROR_INVALID_START);
                   107283:         }
                   107284: 
                   107285:         // check for invalid chars
1.1.1.2 ! misho    107286:         if (!preg_match('/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?[[:alpha:]_]([[:alnum:]\_\-\.]+)?$/',
1.1       misho    107287:             $string)
                   107288:         ) {
                   107289:             return XML_Util::raiseError('XML names may only contain alphanumeric '
1.1.1.2 ! misho    107290:                 . 'chars, period, hyphen, colon and underscores', 
1.1       misho    107291:                 XML_UTIL_ERROR_INVALID_CHARS);
                   107292:         }
                   107293:         // XML name is valid
                   107294:         return true;
                   107295:     }
                   107296: 
                   107297:     /**
                   107298:      * replacement for XML_Util::raiseError
                   107299:      *
                   107300:      * Avoids the necessity to always require
                   107301:      * PEAR.php
                   107302:      *
                   107303:      * @param string $msg  error message
                   107304:      * @param int    $code error code
                   107305:      *
                   107306:      * @return PEAR_Error
                   107307:      * @access public
                   107308:      * @static
                   107309:      * @todo PEAR CS - should this use include_once instead?
                   107310:      */
                   107311:     function raiseError($msg, $code)
                   107312:     {
                   107313:         require_once 'phar://install-pear-nozlib.phar/' . 'PEAR.php';
                   107314:         return PEAR::raiseError($msg, $code);
                   107315:     }
                   107316: }
                   107317: ?>
                   107318: package.xml100644   1750   1750       36035 11117075467   6455 <?xml version="1.0" encoding="UTF-8"?>
                   107319: <package packagerversion="1.7.2" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0     http://pear.php.net/dtd/tasks-1.0.xsd     http://pear.php.net/dtd/package-2.0     http://pear.php.net/dtd/package-2.0.xsd">
                   107320:  <name>XML_Util</name>
                   107321:  <channel>pear.php.net</channel>
                   107322:  <summary>XML utility class</summary>
                   107323:  <description>Selection of methods that are often needed when working with XML documents.  Functionality includes creating of attribute lists from arrays, creation of tags, validation of XML names and more.</description>
                   107324:  <lead>
                   107325:   <name>Chuck Burgess</name>
                   107326:   <user>ashnazg</user>
                   107327:   <email>ashnazg@php.net</email>
                   107328:   <active>yes</active>
                   107329:  </lead>
                   107330:  <lead>
                   107331:   <name>Stephan Schmidt</name>
                   107332:   <user>schst</user>
                   107333:   <email>schst@php-tools.net</email>
                   107334:   <active>no</active>
                   107335:  </lead>
                   107336:  <helper>
                   107337:   <name>Davey Shafik</name>
                   107338:   <user>davey</user>
                   107339:   <email>davey@php.net</email>
                   107340:   <active>no</active>
                   107341:  </helper>
                   107342:  <date>2008-12-07</date>
                   107343:  <time>19:41:10</time>
                   107344:  <version>
                   107345:   <release>1.2.1</release>
                   107346:   <api>1.2.0</api>
                   107347:  </version>
                   107348:  <stability>
                   107349:   <release>stable</release>
                   107350:   <api>stable</api>
                   107351:  </stability>
                   107352:  <license uri="http://opensource.org/licenses/bsd-license">BSD License</license>
                   107353:  <notes>Fixed Bug #14760: Bug in getDocTypeDeclaration() [ashnazg|fpospisil]</notes>
                   107354:  <contents>
                   107355:   <dir baseinstalldir="XML" name="/">
                   107356:    <file baseinstalldir="XML" md5sum="06b6662b91b1a466e7b5113f37d4725f" name="examples/example.php" role="doc" />
                   107357:    <file baseinstalldir="XML" md5sum="77355702c9e861d3fc0a5318ea689eee" name="examples/example2.php" role="doc" />
                   107358:    <file baseinstalldir="XML" md5sum="0af0cff09232a6c275803bb36213cdd9" name="tests/AllTests.php" role="test" />
                   107359:    <file baseinstalldir="XML" md5sum="73088689d58b71cd4f86013c88b72216" name="tests/testBasic_apiVersion.phpt" role="test" />
                   107360:    <file baseinstalldir="XML" md5sum="4b17c0df7fbfb1bb2f3f636ebd6c2cbd" name="tests/testBasic_attributesToString.phpt" role="test" />
                   107361:    <file baseinstalldir="XML" md5sum="dc4202f1451bbeb62a5bc7d56a7c774c" name="tests/testBasic_collapseEmptyTags.phpt" role="test" />
                   107362:    <file baseinstalldir="XML" md5sum="4c87fda94fdfb7a78ba84998d6e28f45" name="tests/testBasic_createCDataSection.phpt" role="test" />
                   107363:    <file baseinstalldir="XML" md5sum="c101844768f146653c59c81978060158" name="tests/testBasic_createComment.phpt" role="test" />
                   107364:    <file baseinstalldir="XML" md5sum="ba75d66c2f0fb0010c71f3bcd1f64eb2" name="tests/testBasic_createEndElement.phpt" role="test" />
                   107365:    <file baseinstalldir="XML" md5sum="ad786fb687e1eea1f6890a7424709c79" name="tests/testBasic_createStartElement.phpt" role="test" />
                   107366:    <file baseinstalldir="XML" md5sum="5f453edadebaa3435c8e6f09a3aaaa9c" name="tests/testBasic_createTag.phpt" role="test" />
                   107367:    <file baseinstalldir="XML" md5sum="d2792da0d9c5f0987ee4587912017aa9" name="tests/testBasic_createTagFromArray.phpt" role="test" />
                   107368:    <file baseinstalldir="XML" md5sum="817882a0ab33e60f17ee71874ad975f0" name="tests/testBasic_getDocTypeDeclaration.phpt" role="test" />
                   107369:    <file baseinstalldir="XML" md5sum="5bc1926a488a6b63ec6366bfcf06a50a" name="tests/testBasic_getXmlDeclaration.phpt" role="test" />
                   107370:    <file baseinstalldir="XML" md5sum="a727860d55c14194fdaffa839a59a540" name="tests/testBasic_isValidName.phpt" role="test" />
                   107371:    <file baseinstalldir="XML" md5sum="300a6192f7cc6f7bc3d8f2576b51e4b0" name="tests/testBasic_raiseError.phpt" role="test" />
                   107372:    <file baseinstalldir="XML" md5sum="e6717d43001775cccd52bd5195cf02e0" name="tests/testBasic_replaceEntities.phpt" role="test" />
                   107373:    <file baseinstalldir="XML" md5sum="431856aa83a23396a9f00915dd2be192" name="tests/testBasic_reverseEntities.phpt" role="test" />
                   107374:    <file baseinstalldir="XML" md5sum="ab035534463cae8cc903e907aead8ffe" name="tests/testBasic_splitQualifiedName.phpt" role="test" />
                   107375:    <file baseinstalldir="XML" md5sum="1850856692ff6c6df5e8acb16e1080ce" name="tests/testBug_4950.phpt" role="test" />
                   107376:    <file baseinstalldir="XML" md5sum="b4127883df40a4b0d1736ad42215ee25" name="tests/testBug_5392.phpt" role="test" />
                   107377:    <file baseinstalldir="XML" md5sum="9bb265dafaaf06c86ca5c48f50368ded" name="Util.php" role="php">
                   107378:     <tasks:replace from="@version@" to="version" type="package-info" />
                   107379:    </file>
                   107380:   </dir>
                   107381:  </contents>
                   107382:  <dependencies>
                   107383:   <required>
                   107384:    <php>
                   107385:     <min>4.3.0</min>
                   107386:    </php>
                   107387:    <pearinstaller>
                   107388:     <min>1.4.3</min>
                   107389:    </pearinstaller>
                   107390:    <extension>
                   107391:     <name>pcre</name>
                   107392:    </extension>
                   107393:   </required>
                   107394:  </dependencies>
                   107395:  <phprelease />
                   107396:  <changelog>
                   107397:   <release>
                   107398:    <version>
                   107399:     <release>1.2.1</release>
                   107400:     <api>1.2.0</api>
                   107401:    </version>
                   107402:    <stability>
                   107403:     <release>stable</release>
                   107404:     <api>stable</api>
                   107405:    </stability>
                   107406:    <date>2008-12-07</date>
                   107407:    <license uri="http://opensource.org/licenses/bsd-license">BSD License</license>
                   107408:    <notes>Fixed Bug #14760: Bug in getDocTypeDeclaration() [ashnazg|fpospisil]</notes>
                   107409:   </release>
                   107410:   <release>
                   107411:    <version>
                   107412:     <release>1.2.0</release>
                   107413:     <api>1.2.0</api>
                   107414:    </version>
                   107415:    <stability>
                   107416:     <release>stable</release>
                   107417:     <api>stable</api>
                   107418:    </stability>
                   107419:    <date>2008-07-26</date>
                   107420:    <license uri="http://opensource.org/licenses/bsd-license">BSD License</license>
                   107421:    <notes>Changed license to New BSD License (Req #13826 [ashnazg])
                   107422: Added a test suite against all API methods [ashnazg]
                   107423: Switch to package.xml v2 [ashnazg]
                   107424: Added Req #13839: Missing XHTML empty tags to collapse [ashnazg|drry]
                   107425: Fixed Bug #5392: encoding of ISO-8859-1 is the only supported encoding [ashnazg]
                   107426: Fixed Bug #4950: Incorrect CDATA serializing [ashnazg|drry]
                   107427: -- (this fix differs from the one in v1.2.0a1)</notes>
                   107428:   </release>
                   107429:   <release>
                   107430:    <version>
                   107431:     <release>1.2.0RC1</release>
                   107432:     <api>1.2.0</api>
                   107433:    </version>
                   107434:    <stability>
                   107435:     <release>beta</release>
                   107436:     <api>beta</api>
                   107437:    </stability>
                   107438:    <date>2008-07-12</date>
                   107439:    <license uri="http://opensource.org/licenses/bsd-license">BSD License</license>
                   107440:    <notes>Changed license to New BSD License (Req #13826 [ashnazg])
                   107441: Added a test suite against all API methods [ashnazg]
                   107442: Switch to package.xml v2 [ashnazg]
                   107443: Added Req #13839: Missing XHTML empty tags to collapse [ashnazg|drry]
                   107444: Fixed Bug #5392: encoding of ISO-8859-1 is the only supported encoding [ashnazg]
                   107445: Fixed Bug #4950: Incorrect CDATA serializing [ashnazg|drry]
                   107446: -- (this fix differs from the one in v1.2.0a1)</notes>
                   107447:   </release>
                   107448:   <release>
                   107449:    <version>
                   107450:     <release>1.2.0a2</release>
                   107451:     <api>1.2.0</api>
                   107452:    </version>
                   107453:    <stability>
                   107454:     <release>alpha</release>
                   107455:     <api>alpha</api>
                   107456:    </stability>
                   107457:    <date>2008-05-22</date>
                   107458:    <license uri="http://opensource.org/licenses/bsd-license">BSD License</license>
                   107459:    <notes>Changed license to New BSD License (Req #13826 [ashnazg])
                   107460: Added a test suite against all API methods [ashnazg]
                   107461: Switch to package.xml v2 [ashnazg]
                   107462: Added Req #13839: Missing XHTML empty tags to collapse [ashnazg|drry]
                   107463: Fixed Bug #5392: encoding of ISO-8859-1 is the only supported encoding [ashnazg]
                   107464: Fixed Bug #4950: Incorrect CDATA serializing [ashnazg|drry]
                   107465: -- (this fix differs from the one in v1.2.0a1)</notes>
                   107466:   </release>
                   107467:   <release>
                   107468:    <version>
                   107469:     <release>1.2.0a1</release>
                   107470:     <api>1.2.0</api>
                   107471:    </version>
                   107472:    <stability>
                   107473:     <release>alpha</release>
                   107474:     <api>alpha</api>
                   107475:    </stability>
                   107476:    <date>2008-05-04</date>
                   107477:    <license uri="http://opensource.org/licenses/bsd-license">BSD License</license>
                   107478:    <notes>Changed license to New BSD License (Req #13826 [ashnazg])
                   107479: Added a test suite against all API methods [ashnazg]
                   107480: Switch to package.xml v2 [ashnazg]
                   107481: Fixed Bug #4950: Incorrect CDATA serializing [ashnazg|ja.doma]</notes>
                   107482:   </release>
                   107483:   <release>
                   107484:    <version>
                   107485:     <release>1.1.4</release>
                   107486:     <api>1.1.4</api>
                   107487:    </version>
                   107488:    <stability>
                   107489:     <release>stable</release>
                   107490:     <api>stable</api>
                   107491:    </stability>
                   107492:    <date>2006-12-16</date>
                   107493:    <license uri="http://www.php.net/license">PHP License</license>
                   107494:    <notes>- Fixed bug #9561: Not allowing underscores in middle of tags</notes>
                   107495:   </release>
                   107496:   <release>
                   107497:    <version>
                   107498:     <release>1.1.2</release>
                   107499:     <api>1.1.2</api>
                   107500:    </version>
                   107501:    <stability>
                   107502:     <release>stable</release>
                   107503:     <api>stable</api>
                   107504:    </stability>
                   107505:    <date>2006-12-01</date>
                   107506:    <license uri="http://www.php.net/license">PHP License</license>
                   107507:    <notes>- fixed bug #5419: isValidName() now checks for character classes
                   107508: - implemented request #8196: added optional parameter to influence array sorting to createTag() createTagFromArray() and createStartElement()</notes>
                   107509:   </release>
                   107510:   <release>
                   107511:    <version>
                   107512:     <release>1.1.1</release>
                   107513:     <api>1.1.1</api>
                   107514:    </version>
                   107515:    <stability>
                   107516:     <release>stable</release>
                   107517:     <api>stable</api>
                   107518:    </stability>
                   107519:    <date>2004-12-23</date>
                   107520:    <license uri="http://www.php.net/license">PHP License</license>
                   107521:    <notes>- fixed bug in replaceEntities() and reverseEntities() in conjunction with XML_UTIL_ENTITIES_HTML
                   107522: - createTag() and createTagFromArray() now accept XML_UTIL_ENTITIES_XML, XML_UTIL_ENTITIES_XML_REQUIRED, XML_UTIL_ENTITIES_HTML, XML_UTIL_ENTITIES_NONE and XML_UTIL_CDATA_SECTION as $replaceEntities parameter</notes>
                   107523:   </release>
                   107524:   <release>
                   107525:    <version>
                   107526:     <release>1.1.0</release>
                   107527:     <api>1.1.0</api>
                   107528:    </version>
                   107529:    <stability>
                   107530:     <release>stable</release>
                   107531:     <api>stable</api>
                   107532:    </stability>
                   107533:    <date>2004-11-19</date>
                   107534:    <license uri="http://www.php.net/license">PHP License</license>
                   107535:    <notes>- Added collapseEmptyTags (patch by Sebastian Bergmann and Thomas Duffey)</notes>
                   107536:   </release>
                   107537:   <release>
                   107538:    <version>
                   107539:     <release>1.0.0</release>
                   107540:     <api>1.0.0</api>
                   107541:    </version>
                   107542:    <stability>
                   107543:     <release>stable</release>
                   107544:     <api>stable</api>
                   107545:    </stability>
                   107546:    <date>2004-10-28</date>
                   107547:    <license uri="http://www.php.net/license">PHP License</license>
                   107548:    <notes>- Added reverseEntities() (request #2639)</notes>
                   107549:   </release>
                   107550:   <release>
                   107551:    <version>
                   107552:     <release>0.6.1</release>
                   107553:     <api>0.6.1</api>
                   107554:    </version>
                   107555:    <stability>
                   107556:     <release>stable</release>
                   107557:     <api>stable</api>
                   107558:    </stability>
                   107559:    <date>2004-10-28</date>
                   107560:    <license uri="http://www.php.net/license">PHP License</license>
                   107561:    <notes>- Added check for tag name (either as local part or qualified name) in createTagFromArray() (bug #1083)</notes>
                   107562:   </release>
                   107563:   <release>
                   107564:    <version>
                   107565:     <release>0.6.0</release>
                   107566:     <api>0.6.0</api>
                   107567:    </version>
                   107568:    <stability>
                   107569:     <release>stable</release>
                   107570:     <api>stable</api>
                   107571:    </stability>
                   107572:    <date>2004-06-07</date>
                   107573:    <license uri="http://www.php.net/license">PHP License</license>
                   107574:    <notes>- Fixed bug 1438 (namespaces not accepted for isValidName()) (thanks to davey)
                   107575: - added optional parameter to replaceEntities() to define the set of entities to replace
                   107576: - added optional parameter to attributesToString() to define, whether entities should be replaced (requested by Sebastian Bergmann)
                   107577: - allowed second parameter to XML_Util::attributesToString() to be an array containing options (easier to use, if you only need to set the last parameter)
                   107578: - introduced XML_Util::raiseError() to avoid the necessity of including PEAR.php, will only be included on error</notes>
                   107579:   </release>
                   107580:   <release>
                   107581:    <version>
                   107582:     <release>0.6.0beta1</release>
                   107583:     <api>0.6.0beta1</api>
                   107584:    </version>
                   107585:    <stability>
                   107586:     <release>beta</release>
                   107587:     <api>beta</api>
                   107588:    </stability>
                   107589:    <date>2004-05-24</date>
                   107590:    <license uri="http://www.php.net/license">PHP License</license>
                   107591:    <notes>- Fixed bug 1438 (namespaces not accepted for isValidName()) (thanks to davey)
                   107592: - added optional parameter to replaceEntities() to define the set of entities to replace
                   107593: - added optional parameter to attributesToString() to define, whether entities should be replaced (requested by Sebastian Bergmann)
                   107594: - allowed second parameter to XML_Util::attributesToString() to be an array containing options (easier to use, if you only need to set the last parameter)
                   107595: - introduced XML_Util::raiseError() to avoid the necessity of including PEAR.php, will only be included on error</notes>
                   107596:   </release>
                   107597:   <release>
                   107598:    <version>
                   107599:     <release>0.5.2</release>
                   107600:     <api>0.5.2</api>
                   107601:    </version>
                   107602:    <stability>
                   107603:     <release>stable</release>
                   107604:     <api>stable</api>
                   107605:    </stability>
                   107606:    <date>2003-11-22</date>
                   107607:    <license uri="http://www.php.net/license">PHP License</license>
                   107608:    <notes>now creates XHTML compliant empty tags (Davey),
                   107609: minor whitespace fixes (Davey)</notes>
                   107610:   </release>
                   107611:   <release>
                   107612:    <version>
                   107613:     <release>0.5.1</release>
                   107614:     <api>0.5.1</api>
                   107615:    </version>
                   107616:    <stability>
                   107617:     <release>stable</release>
                   107618:     <api>stable</api>
                   107619:    </stability>
                   107620:    <date>2003-09-26</date>
                   107621:    <license uri="http://www.php.net/license">PHP License</license>
                   107622:    <notes>added default namespace parameter (optional) in splitQualifiedName() (requested by Sebastian Bergmann)</notes>
                   107623:   </release>
                   107624:   <release>
                   107625:    <version>
                   107626:     <release>0.5</release>
                   107627:     <api>0.5</api>
                   107628:    </version>
                   107629:    <stability>
                   107630:     <release>stable</release>
                   107631:     <api>stable</api>
                   107632:    </stability>
                   107633:    <date>2003-09-23</date>
                   107634:    <license uri="http://www.php.net/license">PHP License</license>
                   107635:    <notes>added support for multiline attributes in attributesToString(), createTag*() and createStartElement (requested by Yavor Shahpasov for XML_Serializer),
                   107636: added createComment</notes>
                   107637:   </release>
                   107638:   <release>
                   107639:    <version>
                   107640:     <release>0.4</release>
                   107641:     <api>0.4</api>
                   107642:    </version>
                   107643:    <stability>
                   107644:     <release>stable</release>
                   107645:     <api>stable</api>
                   107646:    </stability>
                   107647:    <date>2003-09-21</date>
                   107648:    <license uri="http://www.php.net/license">PHP License</license>
                   107649:    <notes>added createCDataSection(),
                   107650: added support for CData sections in createTag* methods,
                   107651: fixed bug #23,
                   107652: fixed bug in splitQualifiedName()</notes>
                   107653:   </release>
                   107654:   <release>
                   107655:    <version>
                   107656:     <release>0.3</release>
                   107657:     <api>0.3</api>
                   107658:    </version>
                   107659:    <stability>
                   107660:     <release>stable</release>
                   107661:     <api>stable</api>
                   107662:    </stability>
                   107663:    <date>2003-09-12</date>
                   107664:    <license uri="http://www.php.net/license">PHP License</license>
                   107665:    <notes>added createStartElement() and createEndElement()</notes>
                   107666:   </release>
                   107667:   <release>
                   107668:    <version>
                   107669:     <release>0.2.1</release>
                   107670:     <api>0.2.1</api>
                   107671:    </version>
                   107672:    <stability>
                   107673:     <release>stable</release>
                   107674:     <api>stable</api>
                   107675:    </stability>
                   107676:    <date>2003-09-05</date>
                   107677:    <license uri="http://www.php.net/license">PHP License</license>
                   107678:    <notes>fixed bug with zero as tag content in createTagFromArray and createTag</notes>
                   107679:   </release>
                   107680:   <release>
                   107681:    <version>
                   107682:     <release>0.2</release>
                   107683:     <api>0.2</api>
                   107684:    </version>
                   107685:    <stability>
                   107686:     <release>stable</release>
                   107687:     <api>stable</api>
                   107688:    </stability>
                   107689:    <date>2003-08-12</date>
                   107690:    <license uri="http://www.php.net/license">PHP License</license>
                   107691:    <notes>added XML_Util::getDocTypeDeclaration()</notes>
                   107692:   </release>
                   107693:   <release>
                   107694:    <version>
                   107695:     <release>0.1.1</release>
                   107696:     <api>0.1.1</api>
                   107697:    </version>
                   107698:    <stability>
                   107699:     <release>stable</release>
                   107700:     <api>stable</api>
                   107701:    </stability>
                   107702:    <date>2003-08-02</date>
                   107703:    <license uri="http://www.php.net/license">PHP License</license>
                   107704:    <notes>bugfix: removed bug in createTagFromArray</notes>
                   107705:   </release>
                   107706:   <release>
                   107707:    <version>
                   107708:     <release>0.1</release>
                   107709:     <api>0.1</api>
                   107710:    </version>
                   107711:    <stability>
                   107712:     <release>stable</release>
                   107713:     <api>stable</api>
                   107714:    </stability>
                   107715:    <date>2003-08-01</date>
                   107716:    <license uri="http://www.php.net/license">PHP License</license>
                   107717:    <notes>inital release</notes>
                   107718:   </release>
                   107719:  </changelog>
                   107720: </package>
                   107721: XML_Util-1.2.1/examples/example.php100644   1750   1750       21775 11117075466  12420 <?php
                   107722: 
                   107723: /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
                   107724: 
                   107725: /**
                   107726:  * Examples (file #1)
                   107727:  *
                   107728:  * several examples for the methods of XML_Util
                   107729:  * 
                   107730:  * PHP versions 4 and 5
                   107731:  *
                   107732:  * LICENSE:
                   107733:  *
                   107734:  * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
                   107735:  * All rights reserved.
                   107736:  *
                   107737:  * Redistribution and use in source and binary forms, with or without
                   107738:  * modification, are permitted provided that the following conditions
                   107739:  * are met:
                   107740:  *
                   107741:  *    * Redistributions of source code must retain the above copyright
                   107742:  *      notice, this list of conditions and the following disclaimer.
                   107743:  *    * Redistributions in binary form must reproduce the above copyright
                   107744:  *      notice, this list of conditions and the following disclaimer in the
                   107745:  *      documentation and/or other materials provided with the distribution.
                   107746:  *    * The name of the author may not be used to endorse or promote products
                   107747:  *      derived from this software without specific prior written permission.
                   107748:  *
                   107749:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
                   107750:  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
                   107751:  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                   107752:  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
                   107753:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                   107754:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                   107755:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
                   107756:  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
                   107757:  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
                   107758:  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
                   107759:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                   107760:  *
                   107761:  * @category   XML
                   107762:  * @package    XML_Util
                   107763:  * @subpackage Examples
                   107764:  * @author     Stephan Schmidt <schst@php.net>
                   107765:  * @copyright  2003-2008 Stephan Schmidt <schst@php.net>
                   107766:  * @license    http://opensource.org/licenses/bsd-license New BSD License
                   107767:  * @version    CVS: $Id: example.php,v 1.17 2008/05/05 19:05:28 ashnazg Exp $
                   107768:  * @link       http://pear.php.net/package/XML_Util
                   107769:  */
                   107770: 
                   107771:     /**
                   107772:      * set error level
                   107773:      */
                   107774:     error_reporting(E_ALL);
                   107775: 
                   107776:     require_once 'XML/Util.php';
                   107777:     
                   107778:     /**
                   107779:      * replacing XML entities
                   107780:      */
                   107781:     print 'replace XML entities:<br>';
                   107782:     print XML_Util::replaceEntities('This string contains < & >.');
                   107783:     print "\n<br><br>\n";
                   107784: 
                   107785:     /**
                   107786:      * reversing XML entities
                   107787:      */
                   107788:     print 'replace XML entities:<br>';
                   107789:     print XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
                   107790:     print "\n<br><br>\n";
                   107791: 
                   107792:     /**
                   107793:      * building XML declaration
                   107794:      */
                   107795:     print 'building XML declaration:<br>';
                   107796:     print htmlspecialchars(XML_Util::getXMLDeclaration());
                   107797:     print "\n<br><br>\n";
                   107798: 
                   107799:     print 'building XML declaration with additional attributes:<br>';
                   107800:     print htmlspecialchars(XML_Util::getXMLDeclaration('1.0', 'UTF-8', true));
                   107801:     print "\n<br><br>\n";
                   107802: 
                   107803:     /**
                   107804:      * building document type declaration
                   107805:      */
                   107806:     print 'building DocType declaration:<br>';
                   107807:     print htmlspecialchars(XML_Util::getDocTypeDeclaration('package', 
                   107808:         'http://pear.php.net/dtd/package-1.0'));
                   107809:     print "\n<br><br>\n";
                   107810: 
                   107811:     print 'building DocType declaration with public ID (does not exist):<br>';
                   107812:     print htmlspecialchars(XML_Util::getDocTypeDeclaration('package', 
                   107813:         array('uri' => 'http://pear.php.net/dtd/package-1.0', 
                   107814:             'id' => '-//PHP//PEAR/DTD PACKAGE 0.1')));
                   107815:     print "\n<br><br>\n";
                   107816: 
                   107817:     print 'building DocType declaration with internal DTD:<br>';
                   107818:     print '<pre>';
                   107819:     print htmlspecialchars(XML_Util::getDocTypeDeclaration('package', 
                   107820:         'http://pear.php.net/dtd/package-1.0', 
                   107821:         '<!ELEMENT additionalInfo (#PCDATA)>'));
                   107822:     print '</pre>';
                   107823:     print "\n<br><br>\n";
                   107824: 
                   107825:     /**
                   107826:      * creating an attribute string
                   107827:      */
                   107828:     $att = array(
                   107829:         'foo'  => 'bar',
                   107830:         'argh' => 'tomato'
                   107831:     );
                   107832: 
                   107833:     print 'converting array to string:<br>';
                   107834:     print XML_Util::attributesToString($att);
                   107835:     print "\n<br><br>\n";
                   107836: 
                   107837: 
                   107838:     /**
                   107839:      * creating an attribute string with linebreaks
                   107840:      */
                   107841:     $att = array(
                   107842:         'foo'  => 'bar',
                   107843:         'argh' => 'tomato'
                   107844:     );
                   107845: 
                   107846:     print 'converting array to string (including line breaks):<br>';
                   107847:     print '<pre>';
                   107848:     print XML_Util::attributesToString($att, true, true);
                   107849:     print '</pre>';
                   107850:     print "\n<br><br>\n";
                   107851: 
                   107852: 
                   107853:     /**
                   107854:      * splitting a qualified tag name
                   107855:      */
                   107856:     print 'splitting qualified tag name:<br>';
                   107857:     print '<pre>';
                   107858:     print_r(XML_Util::splitQualifiedName('xslt:stylesheet'));
                   107859:     print '</pre>';
                   107860:     print "\n<br>\n";
                   107861: 
                   107862: 
                   107863:     /**
                   107864:      * splitting a qualified tag name (no namespace)
                   107865:      */
                   107866:     print 'splitting qualified tag name (no namespace):<br>';
                   107867:     print '<pre>';
                   107868:     print_r(XML_Util::splitQualifiedName('foo'));
                   107869:     print '</pre>';
                   107870:     print "\n<br>\n";
                   107871: 
                   107872:     /**
                   107873:      * splitting a qualified tag name (no namespace, but default namespace specified)
                   107874:      */
                   107875:     print 'splitting qualified tag name '
                   107876:         . '(no namespace, but default namespace specified):<br>';
                   107877:     print '<pre>';
                   107878:     print_r(XML_Util::splitQualifiedName('foo', 'bar'));
                   107879:     print '</pre>';
                   107880:     print "\n<br>\n";
                   107881: 
                   107882:     /**
                   107883:      * verifying XML names
                   107884:      */
                   107885:     print 'verifying \'My private tag\':<br>';
                   107886:     print '<pre>';
                   107887:     print_r(XML_Util::isValidname('My Private Tag'));
                   107888:     print '</pre>';
                   107889:     print "\n<br><br>\n";
                   107890:     
                   107891:     print 'verifying \'-MyTag\':<br>';
                   107892:     print '<pre>';
                   107893:     print_r(XML_Util::isValidname('-MyTag'));
                   107894:     print '</pre>';
                   107895:     print "\n<br><br>\n";
                   107896: 
                   107897:     /**
                   107898:      * creating an XML tag
                   107899:      */
                   107900:     $tag = array(
                   107901:         'namespace'  => 'foo',
                   107902:         'localPart'  => 'bar',
                   107903:         'attributes' => array('key' => 'value', 'argh' => 'fruit&vegetable'),
                   107904:         'content'    => 'I\'m inside the tag'
                   107905:     );
                   107906: 
                   107907:     print 'creating a tag with namespace and local part:<br>';
                   107908:     print htmlentities(XML_Util::createTagFromArray($tag));
                   107909:     print "\n<br><br>\n";
                   107910: 
                   107911:     /**
                   107912:      * creating an XML tag
                   107913:      */
                   107914:     $tag = array(
                   107915:         'qname'        => 'foo:bar',
                   107916:         'namespaceUri' => 'http://foo.com',
                   107917:         'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
                   107918:         'content'      => 'I\'m inside the tag'
                   107919:     );
                   107920: 
                   107921:     print 'creating a tag with qualified name and namespaceUri:<br>';
                   107922:     print htmlentities(XML_Util::createTagFromArray($tag));
                   107923:     print "\n<br><br>\n";
                   107924: 
                   107925:     /**
                   107926:      * creating an XML tag
                   107927:      */
                   107928:     $tag = array(
                   107929:         'qname'        => 'bar',
                   107930:         'namespaceUri' => 'http://foo.com',
                   107931:         'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable')
                   107932:     );
                   107933: 
                   107934:     print 'creating an empty tag without namespace but namespace Uri:<br>';
                   107935:     print htmlentities(XML_Util::createTagFromArray($tag));
                   107936:     print "\n<br><br>\n";
                   107937: 
                   107938:     /**
                   107939:      * creating an XML tag with more namespaces
                   107940:      */
                   107941:     $tag = array(
                   107942:         'namespace'   => 'foo',
                   107943:         'localPart'   => 'bar',
                   107944:         'attributes'  => array('key' => 'value', 'argh' => 'fruit&vegetable'),
                   107945:         'content'     => 'I\'m inside the tag',
                   107946:         'namespaces'  => array(
                   107947:             'bar'  => 'http://bar.com',
                   107948:             'pear' => 'http://pear.php.net',
                   107949:         )
                   107950:     );
                   107951: 
                   107952:     print 'creating an XML tag with more namespaces:<br />';
                   107953:     print htmlentities(XML_Util::createTagFromArray($tag));
                   107954:     print "\n<br><br>\n";
                   107955: 
                   107956:     /**
                   107957:      * creating an XML tag with a CData Section
                   107958:      */
                   107959:     $tag = array(
                   107960:         'qname'      => 'foo',
                   107961:         'attributes' => array('key' => 'value', 'argh' => 'fruit&vegetable'),
                   107962:         'content'    => 'I\'m inside the tag'
                   107963:     );
                   107964: 
                   107965:     print 'creating a tag with CData section:<br>';
                   107966:     print htmlentities(XML_Util::createTagFromArray($tag, XML_UTIL_CDATA_SECTION));
                   107967:     print "\n<br><br>\n";
                   107968: 
                   107969:     /**
                   107970:      * creating an XML tag with a CData Section
                   107971:      */
                   107972:     $tag = array(
                   107973:         'qname'      => 'foo',
                   107974:         'attributes' => array('key' => 'value', 'argh' => 'tütü'),
                   107975:         'content'    => 
                   107976:             'Also XHTML-tags can be created '
                   107977:             . 'and HTML entities can be replaced Ä ä Ü ö <>.'
                   107978:     );
                   107979: 
                   107980:     print 'creating a tag with HTML entities:<br>';
                   107981:     print htmlentities(XML_Util::createTagFromArray($tag, XML_UTIL_ENTITIES_HTML));
                   107982:     print "\n<br><br>\n";
                   107983: 
                   107984:     /**
                   107985:     * creating an XML tag with createTag
                   107986:     */
                   107987:     print 'creating a tag with createTag:<br>';
                   107988:     print htmlentities(XML_Util::createTag('myNs:myTag', 
                   107989:         array('foo' => 'bar'), 
                   107990:         'This is inside the tag', 
                   107991:         'http://www.w3c.org/myNs#'));
                   107992:     print "\n<br><br>\n";
                   107993: 
                   107994:     
                   107995:     /**
                   107996:      * trying to create an XML tag with an array as content
                   107997:      */
                   107998:     $tag = array(
                   107999:         'qname'   => 'bar',
                   108000:         'content' => array('foo' => 'bar')
                   108001:     );
                   108002:     print 'trying to create an XML tag with an array as content:<br>';
                   108003:     print '<pre>';
                   108004:     print_r(XML_Util::createTagFromArray($tag));
                   108005:     print '</pre>';
                   108006:     print "\n<br><br>\n";
                   108007:     
                   108008:     /**
                   108009:      * trying to create an XML tag without a name
                   108010:      */
                   108011:     $tag = array(
                   108012:         'attributes' => array('foo' => 'bar'),
                   108013:     );
                   108014:     print 'trying to create an XML tag without a name:<br>';
                   108015:     print '<pre>';
                   108016:     print_r(XML_Util::createTagFromArray($tag));
                   108017:     print '</pre>';
                   108018:     print "\n<br><br>\n";
                   108019: ?>
                   108020: XML_Util-1.2.1/examples/example2.php100644   1750   1750       11441 11117075466  12467 <?php
                   108021: 
                   108022: /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
                   108023: 
                   108024: /**
                   108025:  * Examples (file #2)
                   108026:  *
                   108027:  * several examples for the methods of XML_Util
                   108028:  * 
                   108029:  * PHP versions 4 and 5
                   108030:  *
                   108031:  * LICENSE:
                   108032:  *
                   108033:  * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
                   108034:  * All rights reserved.
                   108035:  *
                   108036:  * Redistribution and use in source and binary forms, with or without
                   108037:  * modification, are permitted provided that the following conditions
                   108038:  * are met:
                   108039:  *
                   108040:  *    * Redistributions of source code must retain the above copyright
                   108041:  *      notice, this list of conditions and the following disclaimer.
                   108042:  *    * Redistributions in binary form must reproduce the above copyright
                   108043:  *      notice, this list of conditions and the following disclaimer in the
                   108044:  *      documentation and/or other materials provided with the distribution.
                   108045:  *    * The name of the author may not be used to endorse or promote products
                   108046:  *      derived from this software without specific prior written permission.
                   108047:  *
                   108048:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
                   108049:  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
                   108050:  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                   108051:  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
                   108052:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                   108053:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                   108054:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
                   108055:  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
                   108056:  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
                   108057:  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
                   108058:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                   108059:  *
                   108060:  * @category   XML
                   108061:  * @package    XML_Util
                   108062:  * @subpackage Examples
                   108063:  * @author     Stephan Schmidt <schst@php.net>
                   108064:  * @copyright  2003-2008 Stephan Schmidt <schst@php.net>
                   108065:  * @license    http://opensource.org/licenses/bsd-license New BSD License
                   108066:  * @version    CVS: $Id: example2.php,v 1.11 2008/05/05 19:03:13 ashnazg Exp $
                   108067:  * @link       http://pear.php.net/package/XML_Util
                   108068:  */
                   108069: 
                   108070:     /**
                   108071:      * set error level
                   108072:      */
                   108073:     error_reporting(E_ALL);
                   108074: 
                   108075:     require_once 'XML/Util.php';
                   108076: 
                   108077:     /**
                   108078:      * creating a start element
                   108079:      */
                   108080:     print 'creating a start element:<br>';
                   108081:     print htmlentities(XML_Util::createStartElement('myNs:myTag', 
                   108082:         array('foo' => 'bar'), 'http://www.w3c.org/myNs#'));
                   108083:     print "\n<br><br>\n";
                   108084: 
                   108085: 
                   108086:     /**
                   108087:      * creating a start element
                   108088:      */
                   108089:     print 'creating a start element:<br>';
                   108090:     print htmlentities(XML_Util::createStartElement('myTag', 
                   108091:         array(), 'http://www.w3c.org/myNs#'));
                   108092:     print "\n<br><br>\n";
                   108093: 
                   108094:     /**
                   108095:      * creating a start element
                   108096:      */
                   108097:     print 'creating a start element:<br>';
                   108098:     print '<pre>';
                   108099:     print htmlentities(XML_Util::createStartElement('myTag', 
                   108100:         array('foo' => 'bar', 'argh' => 'tomato'), 
                   108101:         'http://www.w3c.org/myNs#', true));
                   108102:     print '</pre>';
                   108103:     print "\n<br><br>\n";
                   108104: 
                   108105: 
                   108106:     /**
                   108107:      * creating an end element
                   108108:      */
                   108109:     print 'creating an end element:<br>';
                   108110:     print htmlentities(XML_Util::createEndElement('myNs:myTag'));
                   108111:     print "\n<br><br>\n";
                   108112: 
                   108113:     /**
                   108114:      * creating a CData section
                   108115:      */
                   108116:     print 'creating a CData section:<br>';
                   108117:     print htmlentities(XML_Util::createCDataSection('I am content.'));
                   108118:     print "\n<br><br>\n";
                   108119: 
                   108120:     /**
                   108121:      * creating a comment
                   108122:      */
                   108123:     print 'creating a comment:<br>';
                   108124:     print htmlentities(XML_Util::createComment('I am a comment.'));
                   108125:     print "\n<br><br>\n";
                   108126: 
                   108127:     /**
                   108128:      * creating an XML tag with multiline mode
                   108129:      */
                   108130:     $tag = array(
                   108131:         'qname'        => 'foo:bar',
                   108132:         'namespaceUri' => 'http://foo.com',
                   108133:         'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
                   108134:         'content'      => 'I\'m inside the tag & contain dangerous chars'
                   108135:     );
                   108136: 
                   108137:     print 'creating a tag with qualified name and namespaceUri:<br>';
                   108138:     print '<pre>';
                   108139:     print htmlentities(XML_Util::createTagFromArray($tag, 
                   108140:         XML_UTIL_REPLACE_ENTITIES, true));
                   108141:     print '</pre>';
                   108142:     print "\n<br><br>\n";
                   108143: 
                   108144:     /**
                   108145:      * create an attribute string without replacing the entities
                   108146:      */
                   108147:     $atts = array('series' => 'Starsky &amp; Hutch', 'channel' => 'ABC');
                   108148:     print 'creating a attribute string, '
                   108149:         . 'entities in values already had been replaced:<br>';
                   108150:     print htmlentities(XML_Util::attributesToString($atts, 
                   108151:         true, false, false, false, XML_UTIL_ENTITIES_NONE));
                   108152:     print "\n<br><br>\n";
                   108153: 
                   108154:     /**
                   108155:      * using the array-syntax for attributesToString()
                   108156:      */
                   108157:     $atts = array('series' => 'Starsky &amp; Hutch', 'channel' => 'ABC');
                   108158:     print 'using the array-syntax for attributesToString()<br>';
                   108159:     print htmlentities(XML_Util::attributesToString($atts, 
                   108160:         array('entities' => XML_UTIL_ENTITIES_NONE)));
                   108161:     print "\n<br><br>\n";
                   108162: 
                   108163: 
                   108164: ?>
                   108165: XML_Util-1.2.1/tests/AllTests.php100644   1750   1750        7060 11117075466  12013 <?php
                   108166: 
                   108167: /**
                   108168:  * Master Unit Test Suite file for XML_Util
                   108169:  * 
                   108170:  * This top-level test suite file organizes 
                   108171:  * all class test suite files, 
                   108172:  * so that the full suite can be run 
                   108173:  * by PhpUnit or via "pear run-tests -u". 
                   108174:  *
                   108175:  * PHP version 5
                   108176:  *
                   108177:  * @category   XML
                   108178:  * @package    XML_Util
                   108179:  * @subpackage UnitTesting
                   108180:  * @author     Chuck Burgess <ashnazg@php.net>
                   108181:  * @license    http://www.opensource.org/licenses/bsd-license.php New BSD License
                   108182:  * @version    CVS: $Id: AllTests.php,v 1.5 2008/05/30 11:53:09 ashnazg Exp $
                   108183:  * @link       http://pear.php.net/package/XML_Util
                   108184:  * @since      1.2.0a1
                   108185:  */
                   108186: 
                   108187: 
                   108188: /**
                   108189:  * Check PHP version... PhpUnit v3+ requires at least PHP v5.1.4
                   108190:  */
                   108191: if (version_compare(PHP_VERSION, "5.1.4") < 0) {
                   108192:     // Cannnot run test suites
                   108193:     echo 'Cannot run test suite via PhpUnit... requires at least PHP v5.1.4.' . PHP_EOL;
                   108194:     echo 'Use "pear run-tests -p xml_util" to run the PHPT tests directly.' . PHP_EOL
                   108195: ;
                   108196:     exit(1);
                   108197: }
                   108198: 
                   108199: 
                   108200: /**
                   108201:  * Derive the "main" method name
                   108202:  * @internal PhpUnit would have to rename PHPUnit_MAIN_METHOD to PHPUNIT_MAIN_METHOD
                   108203:  *           to make this usage meet the PEAR CS... we cannot rename it here.
                   108204:  */
                   108205: if (!defined('PHPUnit_MAIN_METHOD')) {
                   108206:     define('PHPUnit_MAIN_METHOD', 'XML_Util_AllTests::main');
                   108207: }
                   108208: 
                   108209: 
                   108210: /*
                   108211:  * Files needed by PhpUnit
                   108212:  */
                   108213: require_once 'PHPUnit/Framework.php';
                   108214: require_once 'PHPUnit/TextUI/TestRunner.php';
                   108215: require_once 'PHPUnit/Extensions/PhptTestSuite.php';
                   108216: 
                   108217: /*
                   108218:  * You must add each additional class-level test suite file here
                   108219:  */
                   108220: // there are no PhpUnit test files... only PHPTs.. so nothing is listed here
                   108221: 
                   108222: /**
                   108223:  * directory where PHPT tests are located
                   108224:  */
                   108225: define('XML_UTIL_DIR_PHPT', dirname(__FILE__));
                   108226: 
                   108227: /**
                   108228:  * Master Unit Test Suite class for XML_Util
                   108229:  * 
                   108230:  * This top-level test suite class organizes 
                   108231:  * all class test suite files, 
                   108232:  * so that the full suite can be run 
                   108233:  * by PhpUnit or via "pear run-tests -up xml_util". 
                   108234:  *
                   108235:  * @category   XML
                   108236:  * @package    XML_Util
                   108237:  * @subpackage UnitTesting
                   108238:  * @author     Chuck Burgess <ashnazg@php.net>
                   108239:  * @license    http://www.opensource.org/licenses/bsd-license.php New BSD License
                   108240:  * @version    Release: @package_version@
                   108241:  * @link       http://pear.php.net/package/XML_Util
                   108242:  * @since      1.2.0a1
                   108243:  */
                   108244: class XML_Util_AllTests
                   108245: {
                   108246: 
                   108247:     /**
                   108248:      * Launches the TextUI test runner
                   108249:      *
                   108250:      * @return void
                   108251:      * @uses PHPUnit_TextUI_TestRunner
                   108252:      */
                   108253:     public static function main()
                   108254:     {
                   108255:         PHPUnit_TextUI_TestRunner::run(self::suite());
                   108256:     }
                   108257: 
                   108258: 
                   108259:     /**
                   108260:      * Adds all class test suites into the master suite
                   108261:      *
                   108262:      * @return PHPUnit_Framework_TestSuite a master test suite
                   108263:      *                                     containing all class test suites
                   108264:      * @uses PHPUnit_Framework_TestSuite
                   108265:      */ 
                   108266:     public static function suite()
                   108267:     {
                   108268:         $suite = new PHPUnit_Framework_TestSuite(
                   108269:             'XML_Util Full Suite of Unit Tests');
                   108270: 
                   108271:         /*
                   108272:          * You must add each additional class-level test suite name here
                   108273:          */
                   108274:         // there are no PhpUnit test files... only PHPTs.. so nothing is listed here
                   108275: 
                   108276:         /*
                   108277:          * add PHPT tests
                   108278:          */
                   108279:         $phpt = new PHPUnit_Extensions_PhptTestSuite(XML_UTIL_DIR_PHPT);
                   108280:         $suite->addTestSuite($phpt);
                   108281: 
                   108282:         return $suite;
                   108283:     }
                   108284: }
                   108285: 
                   108286: /**
                   108287:  * Call the main method if this file is executed directly
                   108288:  * @internal PhpUnit would have to rename PHPUnit_MAIN_METHOD to PHPUNIT_MAIN_METHOD
                   108289:  *           to make this usage meet the PEAR CS... we cannot rename it here.
                   108290:  */
                   108291: if (PHPUnit_MAIN_METHOD == 'XML_Util_AllTests::main') {
                   108292:     XML_Util_AllTests::main();
                   108293: }
                   108294: 
                   108295: /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
                   108296: ?>
                   108297: XML_Util-1.2.1/tests/testBasic_apiVersion.phpt100644   1750   1750         701 11117075466  14537 --TEST--
                   108298: XML_Util::apiVersion() basic tests
                   108299: --CREDITS--
                   108300: Chuck Burgess <ashnazg@php.net>
                   108301: # created for v1.2.0a1 2008-05-04
                   108302: --FILE--
                   108303: <?php
                   108304: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   108305: echo '=====XML_Util::apiVersion() basic tests=====' . PHP_EOL . PHP_EOL;
                   108306: 
                   108307: echo "TEST:  basic apiVersion() call" . PHP_EOL;
                   108308: echo XML_Util::apiVersion() . PHP_EOL;
                   108309: ?>
                   108310: --EXPECT--
                   108311: =====XML_Util::apiVersion() basic tests=====
                   108312: 
                   108313: TEST:  basic apiVersion() call
                   108314: 1.1
                   108315: XML_Util-1.2.1/tests/testBasic_attributesToString.phpt100644   1750   1750        7057 11117075466  16333 --TEST--
                   108316: XML_Util::attributesToString() basic tests
                   108317: --CREDITS--
                   108318: Chuck Burgess <ashnazg@php.net>
                   108319: # created for v1.2.0a1 2008-05-04
                   108320: --FILE--
                   108321: <?php
                   108322: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   108323: echo '=====XML_Util::attributesToString() basic tests=====' . PHP_EOL . PHP_EOL;
                   108324: 
                   108325: $att = array("foo" => "bar", "boo" => "baz");
                   108326: $sort1 = array(
                   108327:     'multiline' => true, 
                   108328:     'indent'    => '----', 
                   108329:     'linebreak' => "^", 
                   108330:     'entities'  => XML_UTIL_ENTITIES_XML, 
                   108331:     'sort'      => true
                   108332: );
                   108333: $sort2 = array(
                   108334:     'multiline' => true, 
                   108335:     'indent'    => '----', 
                   108336:     'linebreak' => "^", 
                   108337:     'entities'  => XML_UTIL_ENTITIES_XML, 
                   108338: );
                   108339: 
                   108340: echo "TEST:  basic usage" . PHP_EOL;
                   108341: echo XML_Util::attributesToString($att) . PHP_EOL . PHP_EOL;
                   108342: 
                   108343: echo "TEST:  explicit \$sort = true" . PHP_EOL;
                   108344: echo XML_Util::attributesToString($att, true) . PHP_EOL . PHP_EOL;
                   108345: 
                   108346: echo "TEST:  explicit \$sort = false" . PHP_EOL;
                   108347: echo XML_Util::attributesToString($att, false) . PHP_EOL . PHP_EOL;
                   108348: 
                   108349: echo "TEST:  explicit \$multiline = false" . PHP_EOL;
                   108350: echo XML_Util::attributesToString($att, true, false) . PHP_EOL . PHP_EOL;
                   108351: 
                   108352: echo "TEST:  explicit \$multiline = true" . PHP_EOL;
                   108353: echo XML_Util::attributesToString($att, true, true) . PHP_EOL . PHP_EOL;
                   108354: 
                   108355: echo "TEST:  explicit \$indent = '        ' (8 spaces)" . PHP_EOL;
                   108356: echo XML_Util::attributesToString($att, true, true, '        ') . PHP_EOL . PHP_EOL;
                   108357: 
                   108358: echo "TEST:  explicit \$linebreak = '^' (some dummy char)" . PHP_EOL;
                   108359: echo XML_Util::attributesToString($att, true, true, '^') . PHP_EOL . PHP_EOL;
                   108360: 
                   108361: echo "TEST:  passing \$sort array of options that includes 'sort'" . PHP_EOL;
                   108362: echo XML_Util::attributesToString($att, $sort1) . PHP_EOL . PHP_EOL;
                   108363: 
                   108364: echo "TEST:  passing \$sort array of options that doesn't include 'sort'" . PHP_EOL;
                   108365: echo XML_Util::attributesToString($att, $sort2) . PHP_EOL . PHP_EOL;
                   108366: 
                   108367: echo "TEST:  do not replace entities" . PHP_EOL;
                   108368: $arr = array("foo" => "b@&r", "boo" => "b><z");
                   108369: echo XML_Util::attributesToString($arr, true, false, '    ', PHP_EOL, 
                   108370:     XML_UTIL_ENTITIES_NONE) . PHP_EOL . PHP_EOL;
                   108371: 
                   108372: echo "TEST:  replace all XML entities" . PHP_EOL;
                   108373: $arr = array("foo" => "b@&r", "boo" => "b><z");
                   108374: echo XML_Util::attributesToString($arr, true, false, '    ', PHP_EOL, 
                   108375:     XML_UTIL_ENTITIES_XML) . PHP_EOL . PHP_EOL;
                   108376: 
                   108377: echo "TEST:  replace only required XML entities" . PHP_EOL;
                   108378: $arr = array("foo" => "b@&r", "boo" => "b><z");
                   108379: echo XML_Util::attributesToString($arr, true, false, '    ', PHP_EOL, 
                   108380:     XML_UTIL_ENTITIES_XML_REQUIRED) . PHP_EOL . PHP_EOL;
                   108381: 
                   108382: echo "TEST:  replace HTML entities" . PHP_EOL;
                   108383: $arr = array("foo" => "b@&r", "boo" => "b><z");
                   108384: echo XML_Util::attributesToString($arr, true, false, '    ', PHP_EOL, 
                   108385:     XML_UTIL_ENTITIES_HTML) . PHP_EOL . PHP_EOL;
                   108386: ?>
                   108387: --EXPECT--
                   108388: =====XML_Util::attributesToString() basic tests=====
                   108389: 
                   108390: TEST:  basic usage
                   108391:  boo="baz" foo="bar"
                   108392: 
                   108393: TEST:  explicit $sort = true
                   108394:  boo="baz" foo="bar"
                   108395: 
                   108396: TEST:  explicit $sort = false
                   108397:  foo="bar" boo="baz"
                   108398: 
                   108399: TEST:  explicit $multiline = false
                   108400:  boo="baz" foo="bar"
                   108401: 
                   108402: TEST:  explicit $multiline = true
                   108403:  boo="baz"
                   108404:     foo="bar"
                   108405: 
                   108406: TEST:  explicit $indent = '        ' (8 spaces)
                   108407:  boo="baz"
                   108408:         foo="bar"
                   108409: 
                   108410: TEST:  explicit $linebreak = '^' (some dummy char)
                   108411:  boo="baz"
                   108412: ^foo="bar"
                   108413: 
                   108414: TEST:  passing $sort array of options that includes 'sort'
                   108415:  boo="baz"
                   108416: ----foo="bar"
                   108417: 
                   108418: TEST:  passing $sort array of options that doesn't include 'sort'
                   108419:  boo="baz"
                   108420: ----foo="bar"
                   108421: 
                   108422: TEST:  do not replace entities
                   108423:  boo="b><z" foo="b@&r"
                   108424: 
                   108425: TEST:  replace all XML entities
                   108426:  boo="b&gt;&lt;z" foo="b@&amp;r"
                   108427: 
                   108428: TEST:  replace only required XML entities
                   108429:  boo="b>&lt;z" foo="b@&amp;r"
                   108430: 
                   108431: TEST:  replace HTML entities
                   108432:  boo="b&gt;&lt;z" foo="b@&amp;r"
                   108433: XML_Util-1.2.1/tests/testBasic_collapseEmptyTags.phpt100644   1750   1750        3403 11117075466  16102 --TEST--
                   108434: XML_Util::collapseEmptyTags() basic tests
                   108435: --CREDITS--
                   108436: Chuck Burgess <ashnazg@php.net>
                   108437: # created for v1.2.0a1 2008-05-04
                   108438: --FILE--
                   108439: <?php
                   108440: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   108441: echo '=====XML_Util::collapseEmptyTags() basic tests=====' . PHP_EOL . PHP_EOL;
                   108442: 
                   108443: $emptyTag = "<foo></foo>";
                   108444: $otherTag = "<bar>baz</bar>";
                   108445: $xhtmlTag = "<b></b>";
                   108446: 
                   108447: echo "TEST:  basic usage" . PHP_EOL;
                   108448: echo XML_Util::collapseEmptyTags($emptyTag) . PHP_EOL . PHP_EOL;
                   108449: 
                   108450: echo "TEST:  basic usage alongside non-empty tag" . PHP_EOL;
                   108451: echo XML_Util::collapseEmptyTags($emptyTag . $otherTag) . PHP_EOL . PHP_EOL;
                   108452: 
                   108453: echo "TEST:  one empty tag, with COLLAPSE_ALL set" . PHP_EOL;
                   108454: echo XML_Util::collapseEmptyTags($emptyTag, XML_UTIL_COLLAPSE_ALL) . PHP_EOL . PHP_EOL;
                   108455: 
                   108456: echo "TEST:  one empty tag alongside non-empty tag, with COLLAPSE_ALL set" . PHP_EOL;
                   108457: echo XML_Util::collapseEmptyTags($emptyTag . $otherTag, XML_UTIL_COLLAPSE_ALL) . PHP_EOL . PHP_EOL;
                   108458: 
                   108459: echo "TEST:  one empty tag, with COLLAPSE_XHTML_ONLY set" . PHP_EOL;
                   108460: echo XML_Util::collapseEmptyTags($emptyTag, XML_UTIL_COLLAPSE_XHTML_ONLY) . PHP_EOL . PHP_EOL;
                   108461: 
                   108462: echo "TEST:  one empty tag alongside non-empty tag, with COLLAPSE_XHTML_ONLY set" . PHP_EOL;
                   108463: echo XML_Util::collapseEmptyTags($emptyTag . $xhtmlTag . $otherTag, XML_UTIL_COLLAPSE_XHTML_ONLY) . PHP_EOL . PHP_EOL;
                   108464: ?>
                   108465: --EXPECT--
                   108466: =====XML_Util::collapseEmptyTags() basic tests=====
                   108467: 
                   108468: TEST:  basic usage
                   108469: <foo />
                   108470: 
                   108471: TEST:  basic usage alongside non-empty tag
                   108472: <foo /><bar>baz</bar>
                   108473: 
                   108474: TEST:  one empty tag, with COLLAPSE_ALL set
                   108475: <foo />
                   108476: 
                   108477: TEST:  one empty tag alongside non-empty tag, with COLLAPSE_ALL set
                   108478: <foo /><bar>baz</bar>
                   108479: 
                   108480: TEST:  one empty tag, with COLLAPSE_XHTML_ONLY set
                   108481: <foo></foo>
                   108482: 
                   108483: TEST:  one empty tag alongside non-empty tag, with COLLAPSE_XHTML_ONLY set
                   108484: <foo></foo><b></b><bar>baz</bar>
                   108485: XML_Util-1.2.1/tests/testBasic_createCDataSection.phpt100644   1750   1750         756 11117075466  16117 --TEST--
                   108486: XML_Util::createCDataSection() basic tests
                   108487: --CREDITS--
                   108488: Chuck Burgess <ashnazg@php.net>
                   108489: # created for v1.2.0a1 2008-05-04
                   108490: --FILE--
                   108491: <?php
                   108492: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   108493: echo '=====XML_Util::createCDataSection() basic tests=====' . PHP_EOL . PHP_EOL;
                   108494: 
                   108495: echo "TEST:  basic usage" . PHP_EOL;
                   108496: echo XML_Util::createCDataSection("I am content.") . PHP_EOL;
                   108497: ?>
                   108498: --EXPECT--
                   108499: =====XML_Util::createCDataSection() basic tests=====
                   108500: 
                   108501: TEST:  basic usage
                   108502: <![CDATA[I am content.]]>
                   108503: XML_Util-1.2.1/tests/testBasic_createComment.phpt100644   1750   1750         727 11117075466  15216 --TEST--
                   108504: XML_Util::createComment() basic tests
                   108505: --CREDITS--
                   108506: Chuck Burgess <ashnazg@php.net>
                   108507: # created for v1.2.0a1 2008-05-04
                   108508: --FILE--
                   108509: <?php
                   108510: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   108511: echo '=====XML_Util::createComment() basic tests=====' . PHP_EOL . PHP_EOL;
                   108512: 
                   108513: echo "TEST:  basic usage" . PHP_EOL;
                   108514: echo XML_Util::createComment("I am comment.") . PHP_EOL;
                   108515: ?>
                   108516: --EXPECT--
                   108517: =====XML_Util::createComment() basic tests=====
                   108518: 
                   108519: TEST:  basic usage
                   108520: <!-- I am comment. -->
                   108521: XML_Util-1.2.1/tests/testBasic_createEndElement.phpt100644   1750   1750        1270 11117075466  15646 --TEST--
                   108522: XML_Util::createEndElement() basic tests
                   108523: --CREDITS--
                   108524: Chuck Burgess <ashnazg@php.net>
                   108525: # created for v1.2.0a1 2008-05-04
                   108526: --FILE--
                   108527: <?php
                   108528: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   108529: echo '=====XML_Util::createEndElement() basic tests=====' . PHP_EOL . PHP_EOL;
                   108530: 
                   108531: echo "TEST:  basic usage (myTag)" . PHP_EOL;
                   108532: echo XML_Util::createEndElement("myTag") . PHP_EOL . PHP_EOL;
                   108533: 
                   108534: echo "TEST:  basic usage with a namespaced tag (myNs:myTag)" . PHP_EOL;
                   108535: echo XML_Util::createEndElement("myNs:myTag") . PHP_EOL . PHP_EOL;
                   108536: ?>
                   108537: --EXPECT--
                   108538: =====XML_Util::createEndElement() basic tests=====
                   108539: 
                   108540: TEST:  basic usage (myTag)
                   108541: </myTag>
                   108542: 
                   108543: TEST:  basic usage with a namespaced tag (myNs:myTag)
                   108544: </myNs:myTag>
                   108545: XML_Util-1.2.1/tests/testBasic_createStartElement.phpt100644   1750   1750        7275 11117075466  16250 --TEST--
                   108546: XML_Util::createStartElement() basic tests
                   108547: --CREDITS--
                   108548: Chuck Burgess <ashnazg@php.net>
                   108549: # created for v1.2.0a1 2008-05-04
                   108550: --FILE--
                   108551: <?php
                   108552: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   108553: echo '=====XML_Util::createStartElement() basic tests=====' . PHP_EOL . PHP_EOL;
                   108554: 
                   108555: echo "TEST:  tag only" . PHP_EOL;
                   108556: echo XML_Util::createStartElement(
                   108557:     "myNs:myTag"
                   108558: ) . PHP_EOL . PHP_EOL;
                   108559: 
                   108560: echo "TEST:  tag with attributes" . PHP_EOL;
                   108561: echo XML_Util::createStartElement(
                   108562:     "myNs:myTag", 
                   108563:     array("foo" => "bar")
                   108564: ) . PHP_EOL . PHP_EOL;
                   108565: 
                   108566: echo "TEST:  tag only, passing '' as attribute arg" . PHP_EOL;
                   108567: echo XML_Util::createStartElement(
                   108568:     'myNs:myTag',
                   108569:     ''
                   108570: ) . PHP_EOL . PHP_EOL;
                   108571: 
                   108572: echo "TEST:  tag with attributes and namespace" . PHP_EOL;
                   108573: echo XML_Util::createStartElement(
                   108574:     "myNs:myTag", 
                   108575:     array("foo" => "bar"),
                   108576:     "http://www.w3c.org/myNs#"
                   108577: ) . PHP_EOL . PHP_EOL;
                   108578: 
                   108579: echo "TEST:  tag with empty attributes, whose namespaceUri is not a full namespace" . PHP_EOL;
                   108580: echo XML_Util::createStartElement(
                   108581:     'myTag',
                   108582:     '',
                   108583:     'foo'
                   108584: ) . PHP_EOL . PHP_EOL;
                   108585: 
                   108586: echo "TEST:  tag with attributes, namespace, and multiline = true" . PHP_EOL;
                   108587: echo XML_Util::createStartElement(
                   108588:     "myNs:myTag", 
                   108589:     array("foo" => "bar"),
                   108590:     "http://www.w3c.org/myNs#",
                   108591:     true
                   108592: ) . PHP_EOL . PHP_EOL;
                   108593: 
                   108594: echo "TEST:  tag with attributes, namespace, multiline = true, and indent = (2 spaces only)" . PHP_EOL;
                   108595: echo XML_Util::createStartElement(
                   108596:     "myNs:myTag", 
                   108597:     array("foo" => "bar"),
                   108598:     "http://www.w3c.org/myNs#",
                   108599:     true,
                   108600:     '  '
                   108601: ) . PHP_EOL . PHP_EOL;
                   108602: 
                   108603: echo "TEST:  tag with attributes, namespace, multiline = true, indent = (2 spaces only), and linebreak = '^'" . PHP_EOL;
                   108604: echo XML_Util::createStartElement(
                   108605:     "myNs:myTag", 
                   108606:     array("foo" => "bar"),
                   108607:     "http://www.w3c.org/myNs#",
                   108608:     true,
                   108609:     '  ',
                   108610:     '^'
                   108611: ) . PHP_EOL . PHP_EOL;
                   108612: 
                   108613: echo "TEST:  tag with attributes, namespace, multiline = true, indent = (2 spaces only), linebreak = '^', and sortAttributes = true" . PHP_EOL;
                   108614: echo XML_Util::createStartElement(
                   108615:     "myNs:myTag", 
                   108616:     array("foo" => "bar", "boo" => "baz"),
                   108617:     "http://www.w3c.org/myNs#",
                   108618:     true,
                   108619:     '  ',
                   108620:     '^',
                   108621:     true
                   108622: ) . PHP_EOL . PHP_EOL;
                   108623: 
                   108624: echo "TEST:  tag with attributes, namespace, multiline = true, indent = (2 spaces only), linebreak = '^', and sortAttributes = false" . PHP_EOL;
                   108625: echo XML_Util::createStartElement(
                   108626:     "myNs:myTag", 
                   108627:     array("foo" => "bar", "boo" => "baz"),
                   108628:     "http://www.w3c.org/myNs#",
                   108629:     true,
                   108630:     '  ',
                   108631:     '^',
                   108632:     false
                   108633: ) . PHP_EOL . PHP_EOL;
                   108634: ?>
                   108635: --EXPECT--
                   108636: =====XML_Util::createStartElement() basic tests=====
                   108637: 
                   108638: TEST:  tag only
                   108639: <myNs:myTag>
                   108640: 
                   108641: TEST:  tag with attributes
                   108642: <myNs:myTag foo="bar">
                   108643: 
                   108644: TEST:  tag only, passing '' as attribute arg
                   108645: <myNs:myTag>
                   108646: 
                   108647: TEST:  tag with attributes and namespace
                   108648: <myNs:myTag foo="bar" xmlns:myNs="http://www.w3c.org/myNs#">
                   108649: 
                   108650: TEST:  tag with empty attributes, whose namespaceUri is not a full namespace
                   108651: <myTag xmlns="foo">
                   108652: 
                   108653: TEST:  tag with attributes, namespace, and multiline = true
                   108654: <myNs:myTag foo="bar"
                   108655:             xmlns:myNs="http://www.w3c.org/myNs#">
                   108656: 
                   108657: TEST:  tag with attributes, namespace, multiline = true, and indent = (2 spaces only)
                   108658: <myNs:myTag foo="bar"
                   108659:   xmlns:myNs="http://www.w3c.org/myNs#">
                   108660: 
                   108661: TEST:  tag with attributes, namespace, multiline = true, indent = (2 spaces only), and linebreak = '^'
                   108662: <myNs:myTag foo="bar"^  xmlns:myNs="http://www.w3c.org/myNs#">
                   108663: 
                   108664: TEST:  tag with attributes, namespace, multiline = true, indent = (2 spaces only), linebreak = '^', and sortAttributes = true
                   108665: <myNs:myTag boo="baz"^  foo="bar"^  xmlns:myNs="http://www.w3c.org/myNs#">
                   108666: 
                   108667: TEST:  tag with attributes, namespace, multiline = true, indent = (2 spaces only), linebreak = '^', and sortAttributes = false
                   108668: <myNs:myTag foo="bar"^  boo="baz"^  xmlns:myNs="http://www.w3c.org/myNs#">
                   108669: XML_Util-1.2.1/tests/testBasic_createTag.phpt100644   1750   1750       13434 11117075466  14366 --TEST--
                   108670: XML_Util::createTag() basic tests
                   108671: --CREDITS--
                   108672: Chuck Burgess <ashnazg@php.net>
                   108673: # created for v1.2.0a1 2008-05-04
                   108674: --FILE--
                   108675: <?php
                   108676: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   108677: echo '=====XML_Util::createTag() basic tests=====' . PHP_EOL . PHP_EOL;
                   108678: 
                   108679: echo "TEST:  tag with attribute" . PHP_EOL;
                   108680: echo XML_Util::createTag(
                   108681:     "myNs:myTag", 
                   108682:     array("foo" => "bar")
                   108683: ) . PHP_EOL . PHP_EOL;
                   108684: 
                   108685: echo "TEST:  tag with attribute and content" . PHP_EOL;
                   108686: echo XML_Util::createTag(
                   108687:     "myNs:myTag", 
                   108688:     array("foo" => "bar"), 
                   108689:     "This is inside the tag"
                   108690: ) . PHP_EOL . PHP_EOL;
                   108691: 
                   108692: echo "TEST:  tag with attribute, content, and namespace" . PHP_EOL;
                   108693: echo XML_Util::createTag(
                   108694:     "myNs:myTag", 
                   108695:     array("foo" => "bar"), 
                   108696:     "This is inside the tag",
                   108697:     "http://www.w3c.org/myNs#"
                   108698: ) . PHP_EOL . PHP_EOL;
                   108699: 
                   108700: echo "TEST:  tag with attribute, content, namespace, and REPLACE_ENTITIES" . PHP_EOL;
                   108701: echo XML_Util::createTag(
                   108702:     "myNs:myTag", 
                   108703:     array("foo" => "bar"), 
                   108704:     "This is inside the tag and has < & @ > in it",
                   108705:     "http://www.w3c.org/myNs#",
                   108706:     XML_UTIL_REPLACE_ENTITIES
                   108707: ) . PHP_EOL . PHP_EOL;
                   108708: 
                   108709: echo "TEST:  tag with attribute, content, namespace, and CDATA_SECTION" . PHP_EOL;
                   108710: echo XML_Util::createTag(
                   108711:     "myNs:myTag", 
                   108712:     array("foo" => "bar"), 
                   108713:     "This is inside the tag and has < & @ > in it",
                   108714:     "http://www.w3c.org/myNs#",
                   108715:     XML_UTIL_CDATA_SECTION
                   108716: ) . PHP_EOL . PHP_EOL;
                   108717: 
                   108718: echo "TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, and multiline = false" . PHP_EOL;
                   108719: echo XML_Util::createTag(
                   108720:     "myNs:myTag", 
                   108721:     array("foo" => "bar"), 
                   108722:     "This is inside the tag and has < & @ > in it",
                   108723:     "http://www.w3c.org/myNs#",
                   108724:     XML_UTIL_REPLACE_ENTITIES,
                   108725:     false
                   108726: ) . PHP_EOL . PHP_EOL;
                   108727: 
                   108728: echo "TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, and multiline = true" . PHP_EOL;
                   108729: echo XML_Util::createTag(
                   108730:     "myNs:myTag", 
                   108731:     array("foo" => "bar"), 
                   108732:     "This is inside the tag and has < & @ > in it",
                   108733:     "http://www.w3c.org/myNs#",
                   108734:     XML_UTIL_REPLACE_ENTITIES,
                   108735:     true
                   108736: ) . PHP_EOL . PHP_EOL;
                   108737: 
                   108738: echo "TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, and indent = (2 spaces)" . PHP_EOL;
                   108739: echo XML_Util::createTag(
                   108740:     "myNs:myTag", 
                   108741:     array("foo" => "bar"), 
                   108742:     "This is inside the tag and has < & @ > in it",
                   108743:     "http://www.w3c.org/myNs#",
                   108744:     XML_UTIL_REPLACE_ENTITIES,
                   108745:     true,
                   108746:     '  '
                   108747: ) . PHP_EOL . PHP_EOL;
                   108748: 
                   108749: echo "TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, indent = (2 spaces), and linebreak = '^'" . PHP_EOL;
                   108750: echo XML_Util::createTag(
                   108751:     "myNs:myTag", 
                   108752:     array("foo" => "bar"), 
                   108753:     "This is inside the tag and has < & @ > in it",
                   108754:     "http://www.w3c.org/myNs#",
                   108755:     XML_UTIL_REPLACE_ENTITIES,
                   108756:     true,
                   108757:     '  ',
                   108758:     '^'
                   108759: ) . PHP_EOL . PHP_EOL;
                   108760: 
                   108761: echo "TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = true" . PHP_EOL;
                   108762: echo XML_Util::createTag(
                   108763:     "myNs:myTag", 
                   108764:     array("foo" => "bar", "boo" => "baz"), 
                   108765:     "This is inside the tag and has < & @ > in it",
                   108766:     "http://www.w3c.org/myNs#",
                   108767:     XML_UTIL_REPLACE_ENTITIES,
                   108768:     true,
                   108769:     '  ',
                   108770:     '^',
                   108771:     true
                   108772: ) . PHP_EOL . PHP_EOL;
                   108773: 
                   108774: echo "TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = false" . PHP_EOL;
                   108775: echo XML_Util::createTag(
                   108776:     "myNs:myTag", 
                   108777:     array("foo" => "bar", "boo" => "baz"), 
                   108778:     "This is inside the tag and has < & @ > in it",
                   108779:     "http://www.w3c.org/myNs#",
                   108780:     XML_UTIL_REPLACE_ENTITIES,
                   108781:     true,
                   108782:     '  ',
                   108783:     '^',
                   108784:     false
                   108785: ) . PHP_EOL . PHP_EOL;
                   108786: ?>
                   108787: --EXPECT--
                   108788: =====XML_Util::createTag() basic tests=====
                   108789: 
                   108790: TEST:  tag with attribute
                   108791: <myNs:myTag foo="bar" />
                   108792: 
                   108793: TEST:  tag with attribute and content
                   108794: <myNs:myTag foo="bar">This is inside the tag</myNs:myTag>
                   108795: 
                   108796: TEST:  tag with attribute, content, and namespace
                   108797: <myNs:myTag foo="bar" xmlns:myNs="http://www.w3c.org/myNs#">This is inside the tag</myNs:myTag>
                   108798: 
                   108799: TEST:  tag with attribute, content, namespace, and REPLACE_ENTITIES
                   108800: <myNs:myTag foo="bar" xmlns:myNs="http://www.w3c.org/myNs#">This is inside the tag and has &lt; &amp; @ &gt; in it</myNs:myTag>
                   108801: 
                   108802: TEST:  tag with attribute, content, namespace, and CDATA_SECTION
                   108803: <myNs:myTag foo="bar" xmlns:myNs="http://www.w3c.org/myNs#"><![CDATA[This is inside the tag and has < & @ > in it]]></myNs:myTag>
                   108804: 
                   108805: TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, and multiline = false
                   108806: <myNs:myTag foo="bar" xmlns:myNs="http://www.w3c.org/myNs#">This is inside the tag and has &lt; &amp; @ &gt; in it</myNs:myTag>
                   108807: 
                   108808: TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, and multiline = true
                   108809: <myNs:myTag foo="bar"
                   108810:             xmlns:myNs="http://www.w3c.org/myNs#">This is inside the tag and has &lt; &amp; @ &gt; in it</myNs:myTag>
                   108811: 
                   108812: TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, and indent = (2 spaces)
                   108813: <myNs:myTag foo="bar"
                   108814:   xmlns:myNs="http://www.w3c.org/myNs#">This is inside the tag and has &lt; &amp; @ &gt; in it</myNs:myTag>
                   108815: 
                   108816: TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, indent = (2 spaces), and linebreak = '^'
                   108817: <myNs:myTag foo="bar"^  xmlns:myNs="http://www.w3c.org/myNs#">This is inside the tag and has &lt; &amp; @ &gt; in it</myNs:myTag>
                   108818: 
                   108819: TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = true
                   108820: <myNs:myTag boo="baz"^  foo="bar"^  xmlns:myNs="http://www.w3c.org/myNs#">This is inside the tag and has &lt; &amp; @ &gt; in it</myNs:myTag>
                   108821: 
                   108822: TEST:  tag with attribute, content, namespace, REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = false
                   108823: <myNs:myTag foo="bar"^  boo="baz"^  xmlns:myNs="http://www.w3c.org/myNs#">This is inside the tag and has &lt; &amp; @ &gt; in it</myNs:myTag>
                   108824: XML_Util-1.2.1/tests/testBasic_createTagFromArray.phpt100644   1750   1750       22131 11117075466  16203 --TEST--
                   108825: XML_Util::createTagFromArray() basic tests
                   108826: --CREDITS--
                   108827: Chuck Burgess <ashnazg@php.net>
                   108828: # created for v1.2.0a1 2008-05-04
                   108829: --FILE--
                   108830: <?php
                   108831: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   108832: echo '=====XML_Util::createTagFromArray() basic tests=====' . PHP_EOL . PHP_EOL;
                   108833: 
                   108834: $bad = array(
                   108835:     "foo" => "bar",
                   108836: );
                   108837: $tag1 = array(
                   108838:     "qname"        => "foo:bar",
                   108839: );
                   108840: $tag2 = array(
                   108841:     "qname"        => "foo:bar",
                   108842:     "namespaceUri" => "http://foo.com",
                   108843: );
                   108844: $tag3 = array(
                   108845:     "qname"        => "foo:bar",
                   108846:     "namespaceUri" => "http://foo.com",
                   108847:     "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
                   108848: );
                   108849: $tag4 = array(
                   108850:     "qname"        => "foo:bar",
                   108851:     "namespaceUri" => "http://foo.com",
                   108852:     "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
                   108853:     "content"      => "I'm inside the tag",
                   108854: );
                   108855: $tag5 = array(
                   108856:     "qname"        => "foo:bar",
                   108857:     "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
                   108858:     "content"      => "I'm inside the tag",
                   108859: );
                   108860: $tag6 = array(
                   108861:     "qname"        => "foo:bar",
                   108862:     "namespaceUri" => "http://foo.com",
                   108863:     "content"      => "I'm inside the tag",
                   108864: );
                   108865: $tag7 = array(
                   108866:     "namespaceUri" => "http://foo.com",
                   108867:     "attributes"   => array( "key" => "value", "argh" => "fruit&vegetable" ),
                   108868:     "content"      => "I'm inside the tag",
                   108869: );
                   108870: 
                   108871: $tag8 = array(
                   108872:     'content'      => array('foo', 'bar')
                   108873: );
                   108874: 
                   108875: $tag9 = array(
                   108876:     'qname'        => 'foo:bar',
                   108877:     'namespaces'   => array('ns1' => 'uri1', 'ns2' => 'uri2')
                   108878: );
                   108879: 
                   108880: $tag10 = array(
                   108881:     'namespace'    => 'http://foo.org',
                   108882:     'localPart'    => 'bar'
                   108883: );
                   108884: 
                   108885: $tag11 = array(
                   108886:     'namespace'    => '',
                   108887:     'localPart'    => 'bar'
                   108888: );
                   108889: 
                   108890: $tag12 = array(
                   108891:     'localPart'    => 'foo',
                   108892:     'namespaceUri' => 'http://bar.org'
                   108893: );
                   108894: 
                   108895: echo "TEST:  basic usage with an invalid array" . PHP_EOL;
                   108896: echo XML_Util::createTagFromArray($bad) . PHP_EOL . PHP_EOL;
                   108897: 
                   108898: echo "TEST:  basic usage with a valid array (qname only)" . PHP_EOL;
                   108899: echo XML_Util::createTagFromArray($tag1) . PHP_EOL . PHP_EOL;
                   108900: 
                   108901: echo "TEST:  basic usage with a valid array (qname and namespaceUri)" . PHP_EOL;
                   108902: echo XML_Util::createTagFromArray($tag2) . PHP_EOL . PHP_EOL;
                   108903: 
                   108904: echo "TEST:  basic usage with a valid array (qname, namespaceUri, and attributes)" . PHP_EOL;
                   108905: echo XML_Util::createTagFromArray($tag3) . PHP_EOL . PHP_EOL;
                   108906: 
                   108907: echo "TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content)" . PHP_EOL;
                   108908: echo XML_Util::createTagFromArray($tag4) . PHP_EOL . PHP_EOL;
                   108909: 
                   108910: echo "TEST:  basic usage with a valid array (qname, attributes, and content)" . PHP_EOL;
                   108911: echo XML_Util::createTagFromArray($tag5) . PHP_EOL . PHP_EOL;
                   108912: 
                   108913: echo "TEST:  basic usage with a valid array (qname, namespaceUri, and content)" . PHP_EOL;
                   108914: echo XML_Util::createTagFromArray($tag6) . PHP_EOL . PHP_EOL;
                   108915: 
                   108916: echo "TEST:  basic usage with a valid array (namespaceUri, attributes, and content)" . PHP_EOL;
                   108917: echo XML_Util::createTagFromArray($tag7) . PHP_EOL . PHP_EOL;
                   108918: 
                   108919: echo "TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), plus REPLACE_ENTITIES" . PHP_EOL;
                   108920: echo XML_Util::createTagFromArray($tag4, XML_UTIL_REPLACE_ENTITIES) . PHP_EOL . PHP_EOL;
                   108921: 
                   108922: echo "TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), plus ENTITIES_NONE" . PHP_EOL;
                   108923: echo XML_Util::createTagFromArray($tag4, XML_UTIL_ENTITIES_NONE) . PHP_EOL . PHP_EOL;
                   108924: 
                   108925: echo "TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, and multiline = false" . PHP_EOL;
                   108926: echo XML_Util::createTagFromArray($tag4, XML_UTIL_REPLACE_ENTITIES, false) . PHP_EOL . PHP_EOL;
                   108927: 
                   108928: echo "TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, and multiline = true" . PHP_EOL;
                   108929: echo XML_Util::createTagFromArray($tag4, XML_UTIL_REPLACE_ENTITIES, true) . PHP_EOL . PHP_EOL;
                   108930: 
                   108931: echo "TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, and indent = (2 spaces)" . PHP_EOL;
                   108932: echo XML_Util::createTagFromArray($tag4, XML_UTIL_REPLACE_ENTITIES, true, '  ') . PHP_EOL . PHP_EOL;
                   108933: 
                   108934: echo "TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, indent = (2 spaces), and linebreak = '^'" . PHP_EOL;
                   108935: echo XML_Util::createTagFromArray($tag4, XML_UTIL_REPLACE_ENTITIES, true, '  ', '^') . PHP_EOL . PHP_EOL;
                   108936: 
                   108937: echo "TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = true" . PHP_EOL;
                   108938: echo XML_Util::createTagFromArray($tag4, XML_UTIL_REPLACE_ENTITIES, true, '  ', '^', true) . PHP_EOL . PHP_EOL;
                   108939: 
                   108940: echo "TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = false" . PHP_EOL;
                   108941: echo XML_Util::createTagFromArray($tag4, XML_UTIL_REPLACE_ENTITIES, true, '  ', '^', false) . PHP_EOL . PHP_EOL;
                   108942: 
                   108943: echo 'TEST:  cause a non-scalar error on the content tag' . PHP_EOL;
                   108944: echo XML_Util::createTagFromArray($tag8) . PHP_EOL . PHP_EOL;
                   108945: 
                   108946: echo 'TEST:  handle an array of namespaces being passed' . PHP_EOL;
                   108947: echo XML_Util::createTagFromArray($tag9) . PHP_EOL . PHP_EOL;
                   108948: 
                   108949: echo 'TEST:  qname is derived from namespace + localPart' . PHP_EOL;
                   108950: echo XML_Util::createTagFromArray($tag10) . PHP_EOL . PHP_EOL;
                   108951: 
                   108952: echo 'TEST:  qname is derived from localPart only' . PHP_EOL;
                   108953: echo XML_Util::createTagFromArray($tag11) . PHP_EOL . PHP_EOL;
                   108954: 
                   108955: echo 'TEST:  namespaceUri is given, but namespace is not' . PHP_EOL;
                   108956: echo XML_Util::createTagFromArray($tag12) . PHP_EOL . PHP_EOL;
                   108957: ?>
                   108958: --EXPECT--
                   108959: =====XML_Util::createTagFromArray() basic tests=====
                   108960: 
                   108961: TEST:  basic usage with an invalid array
                   108962: You must either supply a qualified name (qname) or local tag name (localPart).
                   108963: 
                   108964: TEST:  basic usage with a valid array (qname only)
                   108965: <foo:bar />
                   108966: 
                   108967: TEST:  basic usage with a valid array (qname and namespaceUri)
                   108968: <foo:bar xmlns:foo="http://foo.com" />
                   108969: 
                   108970: TEST:  basic usage with a valid array (qname, namespaceUri, and attributes)
                   108971: <foo:bar argh="fruit&amp;vegetable" key="value" xmlns:foo="http://foo.com" />
                   108972: 
                   108973: TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content)
                   108974: <foo:bar argh="fruit&amp;vegetable" key="value" xmlns:foo="http://foo.com">I&apos;m inside the tag</foo:bar>
                   108975: 
                   108976: TEST:  basic usage with a valid array (qname, attributes, and content)
                   108977: <foo:bar argh="fruit&amp;vegetable" key="value">I&apos;m inside the tag</foo:bar>
                   108978: 
                   108979: TEST:  basic usage with a valid array (qname, namespaceUri, and content)
                   108980: <foo:bar xmlns:foo="http://foo.com">I&apos;m inside the tag</foo:bar>
                   108981: 
                   108982: TEST:  basic usage with a valid array (namespaceUri, attributes, and content)
                   108983: You must either supply a qualified name (qname) or local tag name (localPart).
                   108984: 
                   108985: TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), plus REPLACE_ENTITIES
                   108986: <foo:bar argh="fruit&amp;vegetable" key="value" xmlns:foo="http://foo.com">I&apos;m inside the tag</foo:bar>
                   108987: 
                   108988: TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), plus ENTITIES_NONE
                   108989: <foo:bar argh="fruit&vegetable" key="value" xmlns:foo="http://foo.com">I'm inside the tag</foo:bar>
                   108990: 
                   108991: TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, and multiline = false
                   108992: <foo:bar argh="fruit&amp;vegetable" key="value" xmlns:foo="http://foo.com">I&apos;m inside the tag</foo:bar>
                   108993: 
                   108994: TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, and multiline = true
                   108995: <foo:bar argh="fruit&amp;vegetable"
                   108996:          key="value"
                   108997:          xmlns:foo="http://foo.com">I&apos;m inside the tag</foo:bar>
                   108998: 
                   108999: TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, and indent = (2 spaces)
                   109000: <foo:bar argh="fruit&amp;vegetable"
                   109001:   key="value"
                   109002:   xmlns:foo="http://foo.com">I&apos;m inside the tag</foo:bar>
                   109003: 
                   109004: TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, indent = (2 spaces), and linebreak = '^'
                   109005: <foo:bar argh="fruit&amp;vegetable"^  key="value"^  xmlns:foo="http://foo.com">I&apos;m inside the tag</foo:bar>
                   109006: 
                   109007: TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = true
                   109008: <foo:bar argh="fruit&amp;vegetable"^  key="value"^  xmlns:foo="http://foo.com">I&apos;m inside the tag</foo:bar>
                   109009: 
                   109010: TEST:  basic usage with a valid array (qname, namespaceUri, attributes, and content), REPLACE_ENTITIES, multiline = true, indent = (2 spaces), linebreak = '^', and sortAttributes = false
                   109011: <foo:bar key="value"^  argh="fruit&amp;vegetable"^  xmlns:foo="http://foo.com">I&apos;m inside the tag</foo:bar>
                   109012: 
                   109013: TEST:  cause a non-scalar error on the content tag
                   109014: Supplied non-scalar value as tag content
                   109015: 
                   109016: TEST:  handle an array of namespaces being passed
                   109017: <foo:bar xmlns:ns1="uri1" xmlns:ns2="uri2" />
                   109018: 
                   109019: TEST:  qname is derived from namespace + localPart
                   109020: <http://foo.org:bar />
                   109021: 
                   109022: TEST:  qname is derived from localPart only
                   109023: <bar />
                   109024: 
                   109025: TEST:  namespaceUri is given, but namespace is not
                   109026: <foo xmlns="http://bar.org" />
                   109027: XML_Util-1.2.1/tests/testBasic_getDocTypeDeclaration.phpt100644   1750   1750        2754 11117075466  16667 --TEST--
                   109028: XML_Util::getDocTypeDeclaration() basic tests
                   109029: --CREDITS--
                   109030: Chuck Burgess <ashnazg@php.net>
                   109031: # created for v1.2.0a1 2008-05-04
                   109032: --FILE--
                   109033: <?php
                   109034: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   109035: echo '=====XML_Util::getDocTypeDeclaration() basic tests=====' . PHP_EOL . PHP_EOL;
                   109036: 
                   109037: echo "TEST:  using root only" . PHP_EOL;
                   109038: echo XML_Util::getDocTypeDeclaration("rootTag") . PHP_EOL . PHP_EOL;
                   109039: 
                   109040: echo "TEST:  using root and a string URI" . PHP_EOL;
                   109041: echo XML_Util::getDocTypeDeclaration("rootTag", "myDocType.dtd") . PHP_EOL . PHP_EOL;
                   109042: 
                   109043: $uri = array(
                   109044:     'uri' => 'http://pear.php.net/dtd/package-1.0',
                   109045:     'id' => '-//PHP//PEAR/DTD PACKAGE 0.1'
                   109046: );
                   109047: $dtdEntry = '<!ELEMENT additionalInfo (#PCDATA)>';
                   109048: 
                   109049: echo "TEST:  using root and an array URI" . PHP_EOL;
                   109050: echo XML_Util::getDocTypeDeclaration("rootTag", $uri) . PHP_EOL . PHP_EOL;
                   109051: 
                   109052: echo "TEST:  using root and an array URI and an internal DTD entry" . PHP_EOL;
                   109053: echo XML_Util::getDocTypeDeclaration("rootTag", $uri, $dtdEntry) . PHP_EOL . PHP_EOL;
                   109054: ?>
                   109055: --EXPECT--
                   109056: =====XML_Util::getDocTypeDeclaration() basic tests=====
                   109057: 
                   109058: TEST:  using root only
                   109059: <!DOCTYPE rootTag>
                   109060: 
                   109061: TEST:  using root and a string URI
                   109062: <!DOCTYPE rootTag SYSTEM "myDocType.dtd">
                   109063: 
                   109064: TEST:  using root and an array URI
                   109065: <!DOCTYPE rootTag PUBLIC "-//PHP//PEAR/DTD PACKAGE 0.1" "http://pear.php.net/dtd/package-1.0">
                   109066: 
                   109067: TEST:  using root and an array URI and an internal DTD entry
                   109068: <!DOCTYPE rootTag PUBLIC "-//PHP//PEAR/DTD PACKAGE 0.1" "http://pear.php.net/dtd/package-1.0" [
                   109069: <!ELEMENT additionalInfo (#PCDATA)>
                   109070: ]>
                   109071: XML_Util-1.2.1/tests/testBasic_getXmlDeclaration.phpt100644   1750   1750        2217 11117075466  16052 --TEST--
                   109072: XML_Util::getXmlDeclaration() basic tests
                   109073: --CREDITS--
                   109074: Chuck Burgess <ashnazg@php.net>
                   109075: # created for v1.2.0a1 2008-05-04
                   109076: --FILE--
                   109077: <?php
                   109078: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   109079: echo '=====XML_Util::getXmlDeclaration() basic tests=====' . PHP_EOL . PHP_EOL;
                   109080: 
                   109081: echo "TEST:  using version only" . PHP_EOL;
                   109082: echo XML_Util::getXMLDeclaration("1.0") . PHP_EOL . PHP_EOL;
                   109083: 
                   109084: echo "TEST:  using version and encoding" . PHP_EOL;
                   109085: echo XML_Util::getXMLDeclaration("1.0", "UTF-8") . PHP_EOL . PHP_EOL;
                   109086: 
                   109087: echo "TEST:  using version, encoding, and standalone flag" . PHP_EOL;
                   109088: echo XML_Util::getXMLDeclaration("1.0", "UTF-8", true) . PHP_EOL . PHP_EOL;
                   109089: 
                   109090: echo "TEST:  using version and standalone flag" . PHP_EOL;
                   109091: echo XML_Util::getXMLDeclaration("1.0", null, true) . PHP_EOL . PHP_EOL;
                   109092: ?>
                   109093: --EXPECT--
                   109094: =====XML_Util::getXmlDeclaration() basic tests=====
                   109095: 
                   109096: TEST:  using version only
                   109097: <?xml version="1.0"?>
                   109098: 
                   109099: TEST:  using version and encoding
                   109100: <?xml version="1.0" encoding="UTF-8"?>
                   109101: 
                   109102: TEST:  using version, encoding, and standalone flag
                   109103: <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
                   109104: 
                   109105: TEST:  using version and standalone flag
                   109106: <?xml version="1.0" standalone="yes"?>
                   109107: XML_Util-1.2.1/tests/testBasic_isValidName.phpt100644   1750   1750        2602 11117075466  14636 --TEST--
                   109108: XML_Util::isValidName() basic tests
                   109109: --CREDITS--
                   109110: Chuck Burgess <ashnazg@php.net>
                   109111: # created for v1.2.0a1 2008-05-04
                   109112: --FILE--
                   109113: <?php
                   109114: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   109115: echo '=====XML_Util::isValidName() basic tests=====' . PHP_EOL . PHP_EOL;
                   109116: 
                   109117: echo "TEST:  valid tag" . PHP_EOL;
                   109118: $result = XML_Util::isValidName("alpha-x_y_z.123");
                   109119: if (is_a($result, 'PEAR_Error')) {
                   109120:     print "Invalid XML name: " . $result->getMessage() . PHP_EOL . PHP_EOL;
                   109121: } else {
                   109122:     print "Valid XML name." . PHP_EOL . PHP_EOL;
                   109123: }
                   109124: 
                   109125: echo "TEST:  invalid tag" . PHP_EOL;
                   109126: $result = XML_Util::isValidName("invalidTag?");
                   109127: if (is_a($result, 'PEAR_Error')) {
                   109128:     print "Invalid XML name: " . $result->getMessage() . PHP_EOL . PHP_EOL;
                   109129: } else {
                   109130:     print "Valid XML name." . PHP_EOL . PHP_EOL;
                   109131: }
                   109132: 
                   109133: echo "TEST:  invalid tag that doesn't start with a letter" . PHP_EOL;
                   109134: $result = XML_Util::isValidName("1234five");
                   109135: if (is_a($result, 'PEAR_Error')) {
                   109136:     print "Invalid XML name: " . $result->getMessage() . PHP_EOL . PHP_EOL;
                   109137: } else {
                   109138:     print "Valid XML name." . PHP_EOL . PHP_EOL;
                   109139: }
                   109140: 
                   109141: ?>
                   109142: --EXPECT--
                   109143: =====XML_Util::isValidName() basic tests=====
                   109144: 
                   109145: TEST:  valid tag
                   109146: Valid XML name.
                   109147: 
                   109148: TEST:  invalid tag
                   109149: Invalid XML name: XML names may only contain alphanumeric chars, period, hyphen, colon and underscores
                   109150: 
                   109151: TEST:  invalid tag that doesn't start with a letter
                   109152: Invalid XML name: XML names may only start with letter or underscore
                   109153: XML_Util-1.2.1/tests/testBasic_raiseError.phpt100644   1750   1750         766 11117075466  14550 --TEST--
                   109154: XML_Util::raiseError() basic tests
                   109155: --CREDITS--
                   109156: Chuck Burgess <ashnazg@php.net>
                   109157: # created for v1.2.0a1 2008-05-04
                   109158: --FILE--
                   109159: <?php
                   109160: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   109161: echo '=====XML_Util::raiseError() basic tests=====' . PHP_EOL . PHP_EOL;
                   109162: 
                   109163: $error = XML_Util::raiseError("I am an error", 12345);
                   109164: if (is_a($error, 'PEAR_Error')) {
                   109165:     print "PEAR Error: " . $error->getMessage() . PHP_EOL;
                   109166: }
                   109167: ?>
                   109168: --EXPECT--
                   109169: =====XML_Util::raiseError() basic tests=====
                   109170: 
                   109171: PEAR Error: I am an error
                   109172: XML_Util-1.2.1/tests/testBasic_replaceEntities.phpt100644   1750   1750        6260 11117075466  15566 --TEST--
                   109173: XML_Util::replaceEntities() basic tests
                   109174: --CREDITS--
                   109175: Chuck Burgess <ashnazg@php.net>
                   109176: # created for v1.2.0a1 2008-05-04
                   109177: --FILE--
                   109178: <?php
                   109179: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   109180: echo '=====XML_Util::replaceEntities() basic tests=====' . PHP_EOL . PHP_EOL;
                   109181: 
                   109182: $data = 'This string contains < & >.';
                   109183: $utf8 = 'This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê';
                   109184: 
                   109185: echo "TEST:  basic usage" . PHP_EOL;
                   109186: echo XML_Util::replaceEntities($data) . PHP_EOL . PHP_EOL;
                   109187: 
                   109188: echo "TEST:  basic usage but with bogus \$replaceEntities arg" . PHP_EOL;
                   109189: echo XML_Util::replaceEntities($data, 'I_AM_BOGUS') . PHP_EOL . PHP_EOL;
                   109190: 
                   109191: echo "TEST:  basic usage with ENTITIES_XML" . PHP_EOL;
                   109192: echo XML_Util::replaceEntities($data, XML_UTIL_ENTITIES_XML) . PHP_EOL . PHP_EOL;
                   109193: 
                   109194: echo "TEST:  basic usage with ENTITIES_XML and UTF-8" . PHP_EOL;
                   109195: echo XML_Util::replaceEntities($data, XML_UTIL_ENTITIES_XML, 'UTF-8') . PHP_EOL . PHP_EOL;
                   109196: 
                   109197: echo "TEST:  utf8 usage with ENTITIES_XML and UTF-8" . PHP_EOL;
                   109198: echo XML_Util::replaceEntities($utf8, XML_UTIL_ENTITIES_XML, 'UTF-8') . PHP_EOL . PHP_EOL;
                   109199: 
                   109200: echo "TEST:  basic usage with ENTITIES_XML_REQUIRED" . PHP_EOL;
                   109201: echo XML_Util::replaceEntities($data, XML_UTIL_ENTITIES_XML_REQUIRED) . PHP_EOL . PHP_EOL;
                   109202: 
                   109203: echo "TEST:  basic usage with ENTITIES_XML_REQUIRED and UTF-8" . PHP_EOL;
                   109204: echo XML_Util::replaceEntities($data, XML_UTIL_ENTITIES_XML_REQUIRED, 'UTF-8') . PHP_EOL . PHP_EOL;
                   109205: 
                   109206: echo "TEST:  utf8 usage with ENTITIES_XML_REQUIRED and UTF-8" . PHP_EOL;
                   109207: echo XML_Util::replaceEntities($utf8, XML_UTIL_ENTITIES_XML_REQUIRED, 'UTF-8') . PHP_EOL . PHP_EOL;
                   109208: 
                   109209: echo "TEST:  basic usage with ENTITIES_HTML" . PHP_EOL;
                   109210: echo XML_Util::replaceEntities($data, XML_UTIL_ENTITIES_HTML) . PHP_EOL . PHP_EOL;
                   109211: 
                   109212: echo "TEST:  basic usage with ENTITIES_HTML and UTF-8" . PHP_EOL;
                   109213: echo XML_Util::replaceEntities($data, XML_UTIL_ENTITIES_HTML, 'UTF-8') . PHP_EOL . PHP_EOL;
                   109214: 
                   109215: echo "TEST:  utf8 usage with ENTITIES_HTML and UTF-8" . PHP_EOL;
                   109216: echo XML_Util::replaceEntities($utf8, XML_UTIL_ENTITIES_HTML, 'UTF-8') . PHP_EOL . PHP_EOL;
                   109217: ?>
                   109218: --EXPECT--
                   109219: =====XML_Util::replaceEntities() basic tests=====
                   109220: 
                   109221: TEST:  basic usage
                   109222: This string contains &lt; &amp; &gt;.
                   109223: 
                   109224: TEST:  basic usage but with bogus $replaceEntities arg
                   109225: This string contains < & >.
                   109226: 
                   109227: TEST:  basic usage with ENTITIES_XML
                   109228: This string contains &lt; &amp; &gt;.
                   109229: 
                   109230: TEST:  basic usage with ENTITIES_XML and UTF-8
                   109231: This string contains &lt; &amp; &gt;.
                   109232: 
                   109233: TEST:  utf8 usage with ENTITIES_XML and UTF-8
                   109234: This data contains special chars like &lt;, &gt;, &amp; and &quot; as well as ä, ö, ß, à and ê
                   109235: 
                   109236: TEST:  basic usage with ENTITIES_XML_REQUIRED
                   109237: This string contains &lt; &amp; >.
                   109238: 
                   109239: TEST:  basic usage with ENTITIES_XML_REQUIRED and UTF-8
                   109240: This string contains &lt; &amp; >.
                   109241: 
                   109242: TEST:  utf8 usage with ENTITIES_XML_REQUIRED and UTF-8
                   109243: This data contains special chars like &lt;, >, &amp; and &quot; as well as ä, ö, ß, à and ê
                   109244: 
                   109245: TEST:  basic usage with ENTITIES_HTML
                   109246: This string contains &lt; &amp; &gt;.
                   109247: 
                   109248: TEST:  basic usage with ENTITIES_HTML and UTF-8
                   109249: This string contains &lt; &amp; &gt;.
                   109250: 
                   109251: TEST:  utf8 usage with ENTITIES_HTML and UTF-8
                   109252: This data contains special chars like &lt;, &gt;, &amp; and &quot; as well as &auml;, &ouml;, &szlig;, &agrave; and &ecirc;
                   109253: 
                   109254: XML_Util-1.2.1/tests/testBasic_reverseEntities.phpt100644   1750   1750        6241 11117075466  15625 --TEST--
                   109255: XML_Util::reverseEntities() basic tests
                   109256: --CREDITS--
                   109257: Chuck Burgess <ashnazg@php.net>
                   109258: # created for v1.2.0a1 2008-05-04
                   109259: --FILE--
                   109260: <?php
                   109261: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   109262: echo '=====XML_Util::reverseEntities() basic tests=====' . PHP_EOL . PHP_EOL;
                   109263: 
                   109264: $data = 'This string contains &lt; &amp; &gt;.';
                   109265: $utf8 = 'This data contains special chars like &lt;, &gt;, &amp; and &quot; as well as &auml;, &ouml;, &szlig;, &agrave; and &ecirc;';
                   109266: 
                   109267: echo "TEST:  basic usage" . PHP_EOL;
                   109268: echo XML_Util::reverseEntities($data) . PHP_EOL . PHP_EOL;
                   109269: 
                   109270: echo "TEST:  basic usage but with bogus \$replaceEntities arg" . PHP_EOL;
                   109271: echo XML_Util::reverseEntities($data, 'I_AM_BOGUS') . PHP_EOL . PHP_EOL;
                   109272: 
                   109273: echo "TEST:  basic usage with ENTITIES_XML" . PHP_EOL;
                   109274: echo XML_Util::reverseEntities($data, XML_UTIL_ENTITIES_XML) . PHP_EOL . PHP_EOL;
                   109275: 
                   109276: echo "TEST:  basic usage with ENTITIES_XML and UTF-8" . PHP_EOL;
                   109277: echo XML_Util::reverseEntities($data, XML_UTIL_ENTITIES_XML, 'UTF-8') . PHP_EOL . PHP_EOL;
                   109278: 
                   109279: echo "TEST:  utf8 usage with ENTITIES_XML and UTF-8" . PHP_EOL;
                   109280: echo XML_Util::reverseEntities($utf8, XML_UTIL_ENTITIES_XML, 'UTF-8') . PHP_EOL . PHP_EOL;
                   109281: 
                   109282: echo "TEST:  basic usage with ENTITIES_XML_REQUIRED" . PHP_EOL;
                   109283: echo XML_Util::reverseEntities($data, XML_UTIL_ENTITIES_XML_REQUIRED) . PHP_EOL . PHP_EOL;
                   109284: 
                   109285: echo "TEST:  basic usage with ENTITIES_XML_REQUIRED and UTF-8" . PHP_EOL;
                   109286: echo XML_Util::reverseEntities($data, XML_UTIL_ENTITIES_XML_REQUIRED, 'UTF-8') . PHP_EOL . PHP_EOL;
                   109287: 
                   109288: echo "TEST:  utf8 usage with ENTITIES_XML_REQUIRED and UTF-8" . PHP_EOL;
                   109289: echo XML_Util::reverseEntities($utf8, XML_UTIL_ENTITIES_XML_REQUIRED, 'UTF-8') . PHP_EOL . PHP_EOL;
                   109290: 
                   109291: echo "TEST:  basic usage with ENTITIES_HTML" . PHP_EOL;
                   109292: echo XML_Util::reverseEntities($data, XML_UTIL_ENTITIES_HTML) . PHP_EOL . PHP_EOL;
                   109293: 
                   109294: echo "TEST:  basic usage with ENTITIES_HTML and UTF-8" . PHP_EOL;
                   109295: echo XML_Util::reverseEntities($data, XML_UTIL_ENTITIES_HTML, 'UTF-8') . PHP_EOL . PHP_EOL;
                   109296: 
                   109297: echo "TEST:  utf8 usage with ENTITIES_HTML and UTF-8" . PHP_EOL;
                   109298: echo XML_Util::reverseEntities($utf8, XML_UTIL_ENTITIES_HTML, 'UTF-8') . PHP_EOL . PHP_EOL;
                   109299: ?>
                   109300: --EXPECT--
                   109301: =====XML_Util::reverseEntities() basic tests=====
                   109302: 
                   109303: TEST:  basic usage
                   109304: This string contains < & >.
                   109305: 
                   109306: TEST:  basic usage but with bogus $replaceEntities arg
                   109307: This string contains &lt; &amp; &gt;.
                   109308: 
                   109309: TEST:  basic usage with ENTITIES_XML
                   109310: This string contains < & >.
                   109311: 
                   109312: TEST:  basic usage with ENTITIES_XML and UTF-8
                   109313: This string contains < & >.
                   109314: 
                   109315: TEST:  utf8 usage with ENTITIES_XML and UTF-8
                   109316: This data contains special chars like <, >, & and " as well as &auml;, &ouml;, &szlig;, &agrave; and &ecirc;
                   109317: 
                   109318: TEST:  basic usage with ENTITIES_XML_REQUIRED
                   109319: This string contains < & &gt;.
                   109320: 
                   109321: TEST:  basic usage with ENTITIES_XML_REQUIRED and UTF-8
                   109322: This string contains < & &gt;.
                   109323: 
                   109324: TEST:  utf8 usage with ENTITIES_XML_REQUIRED and UTF-8
                   109325: This data contains special chars like <, &gt;, & and " as well as &auml;, &ouml;, &szlig;, &agrave; and &ecirc;
                   109326: 
                   109327: TEST:  basic usage with ENTITIES_HTML
                   109328: This string contains < & >.
                   109329: 
                   109330: TEST:  basic usage with ENTITIES_HTML and UTF-8
                   109331: This string contains < & >.
                   109332: 
                   109333: TEST:  utf8 usage with ENTITIES_HTML and UTF-8
                   109334: This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê
                   109335: XML_Util-1.2.1/tests/testBasic_splitQualifiedName.phpt100644   1750   1750        1727 11117075466  16231 --TEST--
                   109336: XML_Util::splitQualifiedName() basic tests
                   109337: --CREDITS--
                   109338: Chuck Burgess <ashnazg@php.net>
                   109339: # created for v1.2.0a1 2008-05-04
                   109340: --FILE--
                   109341: <?php
                   109342: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   109343: echo '=====XML_Util::splitQualifiedName() basic tests=====' . PHP_EOL . PHP_EOL;
                   109344: 
                   109345: echo "TEST:  basic usage without namespace" . PHP_EOL;
                   109346: $return = XML_Util::splitQualifiedName("xslt:stylesheet");
                   109347: echo "namespace => " . $return['namespace'] . PHP_EOL;
                   109348: echo "localPart => " . $return['localPart'] . PHP_EOL;
                   109349: echo PHP_EOL;
                   109350: 
                   109351: echo "TEST:  basic usage with namespace" . PHP_EOL;
                   109352: $return = XML_Util::splitQualifiedName("stylesheet", "myNs");
                   109353: echo "namespace => " . $return['namespace'] . PHP_EOL;
                   109354: echo "localPart => " . $return['localPart'] . PHP_EOL;
                   109355: echo PHP_EOL;
                   109356: ?>
                   109357: --EXPECT--
                   109358: =====XML_Util::splitQualifiedName() basic tests=====
                   109359: 
                   109360: TEST:  basic usage without namespace
                   109361: namespace => xslt
                   109362: localPart => stylesheet
                   109363: 
                   109364: TEST:  basic usage with namespace
                   109365: namespace => myNs
                   109366: localPart => stylesheet
                   109367: XML_Util-1.2.1/tests/testBug_4950.phpt100644   1750   1750        1243 11117075466  12537 --TEST--
                   109368: XML_Util tests for Bug #4950 "Incorrect CDATA serializing"
                   109369: --CREDITS--
                   109370: Chuck Burgess <ashnazg@php.net>
                   109371: # created for v1.2.0a1 2008-05-04
                   109372: --FILE--
                   109373: <?php
                   109374: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   109375: echo '=====XML_Util tests for Bug #4950 "Incorrect CDATA serializing"=====' . PHP_EOL . PHP_EOL;
                   109376: 
                   109377: echo "TEST:  test case provided in bug report" . PHP_EOL;
                   109378: echo XML_Util::createTag("test", array(), "Content ]]></test> here!",
                   109379:     null, XML_UTIL_CDATA_SECTION) . PHP_EOL;
                   109380: 
                   109381: ?>
                   109382: --EXPECT--
                   109383: =====XML_Util tests for Bug #4950 "Incorrect CDATA serializing"=====
                   109384: 
                   109385: TEST:  test case provided in bug report
                   109386: <test><![CDATA[Content ]]]]><![CDATA[></test> here!]]></test>
                   109387: 
                   109388: XML_Util-1.2.1/tests/testBug_5392.phpt100644   1750   1750        2111 11117075466  12533 --TEST--
                   109389: XML_Util tests for Bug #5392 "encoding of ISO-8859-1 is the only supported encoding"
                   109390: --CREDITS--
                   109391: Chuck Burgess <ashnazg@php.net>
                   109392: # created for v1.2.0a1 2008-05-04
                   109393: --FILE--
                   109394: <?php
                   109395: require_once 'XML' . DIRECTORY_SEPARATOR . 'Util.php';
                   109396: echo '=====XML_Util tests for Bug #5392 "encoding of ISO-8859-1 is the only supported encoding"=====' . PHP_EOL . PHP_EOL;
                   109397: 
                   109398: echo "TEST:  test case provided in bug report" . PHP_EOL;
                   109399: $data = 'This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê';
                   109400: 
                   109401: $replaced = XML_Util::replaceEntities($data, XML_UTIL_ENTITIES_HTML, 'UTF-8');
                   109402: 
                   109403: $reversed = XML_Util::reverseEntities($replaced, XML_UTIL_ENTITIES_HTML, 'UTF-8');
                   109404: 
                   109405: echo $replaced . PHP_EOL;
                   109406: echo $reversed . PHP_EOL;
                   109407: 
                   109408: ?>
                   109409: --EXPECT--
                   109410: =====XML_Util tests for Bug #5392 "encoding of ISO-8859-1 is the only supported encoding"=====
                   109411: 
                   109412: TEST:  test case provided in bug report
                   109413: This data contains special chars like &lt;, &gt;, &amp; and &quot; as well as &auml;, &ouml;, &szlig;, &agrave; and &ecirc;
                   109414: This data contains special chars like <, >, & and " as well as ä, ö, ß, à and ê
                   109415: XML_Util-1.2.1/Util.php100644   1750   1750       73350 11117075466  10060 <?php
                   109416: 
                   109417: /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
                   109418: 
                   109419: /**
                   109420:  * XML_Util
                   109421:  *
                   109422:  * XML Utilities package
                   109423:  * 
                   109424:  * PHP versions 4 and 5
                   109425:  *
                   109426:  * LICENSE:
                   109427:  *
                   109428:  * Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
                   109429:  * All rights reserved.
                   109430:  *
                   109431:  * Redistribution and use in source and binary forms, with or without
                   109432:  * modification, are permitted provided that the following conditions
                   109433:  * are met:
                   109434:  *
                   109435:  *    * Redistributions of source code must retain the above copyright
                   109436:  *      notice, this list of conditions and the following disclaimer.
                   109437:  *    * Redistributions in binary form must reproduce the above copyright
                   109438:  *      notice, this list of conditions and the following disclaimer in the
                   109439:  *      documentation and/or other materials provided with the distribution.
                   109440:  *    * The name of the author may not be used to endorse or promote products
                   109441:  *      derived from this software without specific prior written permission.
                   109442:  *
                   109443:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
                   109444:  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
                   109445:  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                   109446:  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
                   109447:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                   109448:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                   109449:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
                   109450:  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
                   109451:  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
                   109452:  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
                   109453:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                   109454:  *
                   109455:  * @category  XML
                   109456:  * @package   XML_Util
                   109457:  * @author    Stephan Schmidt <schst@php.net>
                   109458:  * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
                   109459:  * @license   http://opensource.org/licenses/bsd-license New BSD License
                   109460:  * @version   CVS: $Id: Util.php,v 1.38 2008/11/13 00:03:38 ashnazg Exp $
                   109461:  * @link      http://pear.php.net/package/XML_Util
                   109462:  */
                   109463: 
                   109464: /**
                   109465:  * error code for invalid chars in XML name
                   109466:  */
                   109467: define('XML_UTIL_ERROR_INVALID_CHARS', 51);
                   109468: 
                   109469: /**
                   109470:  * error code for invalid chars in XML name
                   109471:  */
                   109472: define('XML_UTIL_ERROR_INVALID_START', 52);
                   109473: 
                   109474: /**
                   109475:  * error code for non-scalar tag content
                   109476:  */
                   109477: define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);
                   109478: 
                   109479: /**
                   109480:  * error code for missing tag name
                   109481:  */
                   109482: define('XML_UTIL_ERROR_NO_TAG_NAME', 61);
                   109483: 
                   109484: /**
                   109485:  * replace XML entities
                   109486:  */
                   109487: define('XML_UTIL_REPLACE_ENTITIES', 1);
                   109488: 
                   109489: /**
                   109490:  * embedd content in a CData Section
                   109491:  */
                   109492: define('XML_UTIL_CDATA_SECTION', 5);
                   109493: 
                   109494: /**
                   109495:  * do not replace entitites
                   109496:  */
                   109497: define('XML_UTIL_ENTITIES_NONE', 0);
                   109498: 
                   109499: /**
                   109500:  * replace all XML entitites
                   109501:  * This setting will replace <, >, ", ' and &
                   109502:  */
                   109503: define('XML_UTIL_ENTITIES_XML', 1);
                   109504: 
                   109505: /**
                   109506:  * replace only required XML entitites
                   109507:  * This setting will replace <, " and &
                   109508:  */
                   109509: define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);
                   109510: 
                   109511: /**
                   109512:  * replace HTML entitites
                   109513:  * @link http://www.php.net/htmlentities
                   109514:  */
                   109515: define('XML_UTIL_ENTITIES_HTML', 3);
                   109516: 
                   109517: /**
                   109518:  * Collapse all empty tags.
                   109519:  */
                   109520: define('XML_UTIL_COLLAPSE_ALL', 1);
                   109521: 
                   109522: /**
                   109523:  * Collapse only empty XHTML tags that have no end tag.
                   109524:  */
                   109525: define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);
                   109526: 
                   109527: /**
                   109528:  * utility class for working with XML documents
                   109529:  *
                   109530: 
                   109531:  * @category  XML
                   109532:  * @package   XML_Util
                   109533:  * @author    Stephan Schmidt <schst@php.net>
                   109534:  * @copyright 2003-2008 Stephan Schmidt <schst@php.net>
                   109535:  * @license   http://opensource.org/licenses/bsd-license New BSD License
                   109536:  * @version   Release: 1.2.1
                   109537:  * @link      http://pear.php.net/package/XML_Util
                   109538:  */
                   109539: class XML_Util
                   109540: {
                   109541:     /**
                   109542:      * return API version
                   109543:      *
                   109544:      * @return string $version API version
                   109545:      * @access public
                   109546:      * @static
                   109547:      */
                   109548:     function apiVersion()
                   109549:     {
                   109550:         return '1.1';
                   109551:     }
                   109552: 
                   109553:     /**
                   109554:      * replace XML entities
                   109555:      *
                   109556:      * With the optional second parameter, you may select, which
                   109557:      * entities should be replaced.
                   109558:      *
                   109559:      * <code>
                   109560:      * require_once 'XML/Util.php';
                   109561:      *
                   109562:      * // replace XML entites:
                   109563:      * $string = XML_Util::replaceEntities('This string contains < & >.');
                   109564:      * </code>
                   109565:      *
                   109566:      * With the optional third parameter, you may pass the character encoding
                   109567:      * <code>
                   109568:      * require_once 'XML/Util.php';
                   109569:      *
                   109570:      * // replace XML entites in UTF-8:
                   109571:      * $string = XML_Util::replaceEntities(
                   109572:      *     'This string contains < & > as well as ä, ö, ß, à and ê',
                   109573:      *     XML_UTIL_ENTITIES_HTML,
                   109574:      *     'UTF-8'
                   109575:      * );
                   109576:      * </code>
                   109577:      *
                   109578:      * @param string $string          string where XML special chars 
                   109579:      *                                should be replaced
                   109580:      * @param int    $replaceEntities setting for entities in attribute values 
                   109581:      *                                (one of XML_UTIL_ENTITIES_XML, 
                   109582:      *                                XML_UTIL_ENTITIES_XML_REQUIRED, 
                   109583:      *                                XML_UTIL_ENTITIES_HTML)
                   109584:      * @param string $encoding        encoding value (if any)...
                   109585:      *                                must be a valid encoding as determined
                   109586:      *                                by the htmlentities() function
                   109587:      *
                   109588:      * @return string string with replaced chars
                   109589:      * @access public
                   109590:      * @static
                   109591:      * @see reverseEntities()
                   109592:      */
                   109593:     function replaceEntities($string, $replaceEntities = XML_UTIL_ENTITIES_XML,
                   109594:         $encoding = 'ISO-8859-1')
                   109595:     {
                   109596:         switch ($replaceEntities) {
                   109597:         case XML_UTIL_ENTITIES_XML:
                   109598:             return strtr($string, array(
                   109599:                 '&'  => '&amp;',
                   109600:                 '>'  => '&gt;',
                   109601:                 '<'  => '&lt;',
                   109602:                 '"'  => '&quot;',
                   109603:                 '\'' => '&apos;' ));
                   109604:             break;
                   109605:         case XML_UTIL_ENTITIES_XML_REQUIRED:
                   109606:             return strtr($string, array(
                   109607:                 '&' => '&amp;',
                   109608:                 '<' => '&lt;',
                   109609:                 '"' => '&quot;' ));
                   109610:             break;
                   109611:         case XML_UTIL_ENTITIES_HTML:
                   109612:             return htmlentities($string, ENT_COMPAT, $encoding);
                   109613:             break;
                   109614:         }
                   109615:         return $string;
                   109616:     }
                   109617: 
                   109618:     /**
                   109619:      * reverse XML entities
                   109620:      *
                   109621:      * With the optional second parameter, you may select, which
                   109622:      * entities should be reversed.
                   109623:      *
                   109624:      * <code>
                   109625:      * require_once 'XML/Util.php';
                   109626:      *
                   109627:      * // reverse XML entites:
                   109628:      * $string = XML_Util::reverseEntities('This string contains &lt; &amp; &gt;.');
                   109629:      * </code>
                   109630:      *
                   109631:      * With the optional third parameter, you may pass the character encoding
                   109632:      * <code>
                   109633:      * require_once 'XML/Util.php';
                   109634:      *
                   109635:      * // reverse XML entites in UTF-8:
                   109636:      * $string = XML_Util::reverseEntities(
                   109637:      *     'This string contains &lt; &amp; &gt; as well as'
                   109638:      *     . ' &auml;, &ouml;, &szlig;, &agrave; and &ecirc;',
                   109639:      *     XML_UTIL_ENTITIES_HTML,
                   109640:      *     'UTF-8'
                   109641:      * );
                   109642:      * </code>
                   109643:      *
                   109644:      * @param string $string          string where XML special chars 
                   109645:      *                                should be replaced
                   109646:      * @param int    $replaceEntities setting for entities in attribute values 
                   109647:      *                                (one of XML_UTIL_ENTITIES_XML, 
                   109648:      *                                XML_UTIL_ENTITIES_XML_REQUIRED, 
                   109649:      *                                XML_UTIL_ENTITIES_HTML)
                   109650:      * @param string $encoding        encoding value (if any)...
                   109651:      *                                must be a valid encoding as determined
                   109652:      *                                by the html_entity_decode() function
                   109653:      *
                   109654:      * @return string string with replaced chars
                   109655:      * @access public
                   109656:      * @static
                   109657:      * @see replaceEntities()
                   109658:      */
                   109659:     function reverseEntities($string, $replaceEntities = XML_UTIL_ENTITIES_XML,
                   109660:         $encoding = 'ISO-8859-1')
                   109661:     {
                   109662:         switch ($replaceEntities) {
                   109663:         case XML_UTIL_ENTITIES_XML:
                   109664:             return strtr($string, array(
                   109665:                 '&amp;'  => '&',
                   109666:                 '&gt;'   => '>',
                   109667:                 '&lt;'   => '<',
                   109668:                 '&quot;' => '"',
                   109669:                 '&apos;' => '\'' ));
                   109670:             break;
                   109671:         case XML_UTIL_ENTITIES_XML_REQUIRED:
                   109672:             return strtr($string, array(
                   109673:                 '&amp;'  => '&',
                   109674:                 '&lt;'   => '<',
                   109675:                 '&quot;' => '"' ));
                   109676:             break;
                   109677:         case XML_UTIL_ENTITIES_HTML:
                   109678:             return html_entity_decode($string, ENT_COMPAT, $encoding);
                   109679:             break;
                   109680:         }
                   109681:         return $string;
                   109682:     }
                   109683: 
                   109684:     /**
                   109685:      * build an xml declaration
                   109686:      *
                   109687:      * <code>
                   109688:      * require_once 'XML/Util.php';
                   109689:      *
                   109690:      * // get an XML declaration:
                   109691:      * $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
                   109692:      * </code>
                   109693:      *
                   109694:      * @param string $version    xml version
                   109695:      * @param string $encoding   character encoding
                   109696:      * @param bool   $standalone document is standalone (or not)
                   109697:      *
                   109698:      * @return string xml declaration
                   109699:      * @access public
                   109700:      * @static
                   109701:      * @uses attributesToString() to serialize the attributes of the XML declaration
                   109702:      */
                   109703:     function getXMLDeclaration($version = '1.0', $encoding = null, 
                   109704:         $standalone = null)
                   109705:     {
                   109706:         $attributes = array(
                   109707:             'version' => $version,
                   109708:         );
                   109709:         // add encoding
                   109710:         if ($encoding !== null) {
                   109711:             $attributes['encoding'] = $encoding;
                   109712:         }
                   109713:         // add standalone, if specified
                   109714:         if ($standalone !== null) {
                   109715:             $attributes['standalone'] = $standalone ? 'yes' : 'no';
                   109716:         }
                   109717: 
                   109718:         return sprintf('<?xml%s?>', 
                   109719:             XML_Util::attributesToString($attributes, false));
                   109720:     }
                   109721: 
                   109722:     /**
                   109723:      * build a document type declaration
                   109724:      *
                   109725:      * <code>
                   109726:      * require_once 'XML/Util.php';
                   109727:      *
                   109728:      * // get a doctype declaration:
                   109729:      * $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
                   109730:      * </code>
                   109731:      *
                   109732:      * @param string $root        name of the root tag
                   109733:      * @param string $uri         uri of the doctype definition 
                   109734:      *                            (or array with uri and public id)
                   109735:      * @param string $internalDtd internal dtd entries
                   109736:      *
                   109737:      * @return string doctype declaration
                   109738:      * @access public
                   109739:      * @static
                   109740:      * @since 0.2
                   109741:      */
                   109742:     function getDocTypeDeclaration($root, $uri = null, $internalDtd = null)
                   109743:     {
                   109744:         if (is_array($uri)) {
                   109745:             $ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
                   109746:         } elseif (!empty($uri)) {
                   109747:             $ref = sprintf(' SYSTEM "%s"', $uri);
                   109748:         } else {
                   109749:             $ref = '';
                   109750:         }
                   109751: 
                   109752:         if (empty($internalDtd)) {
                   109753:             return sprintf('<!DOCTYPE %s%s>', $root, $ref);
                   109754:         } else {
                   109755:             return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
                   109756:         }
                   109757:     }
                   109758: 
                   109759:     /**
                   109760:      * create string representation of an attribute list
                   109761:      *
                   109762:      * <code>
                   109763:      * require_once 'XML/Util.php';
                   109764:      *
                   109765:      * // build an attribute string
                   109766:      * $att = array(
                   109767:      *              'foo'   =>  'bar',
                   109768:      *              'argh'  =>  'tomato'
                   109769:      *            );
                   109770:      *
                   109771:      * $attList = XML_Util::attributesToString($att);
                   109772:      * </code>
                   109773:      *
                   109774:      * @param array      $attributes attribute array
                   109775:      * @param bool|array $sort       sort attribute list alphabetically, 
                   109776:      *                               may also be an assoc array containing 
                   109777:      *                               the keys 'sort', 'multiline', 'indent', 
                   109778:      *                               'linebreak' and 'entities'
                   109779:      * @param bool       $multiline  use linebreaks, if more than 
                   109780:      *                               one attribute is given
                   109781:      * @param string     $indent     string used for indentation of 
                   109782:      *                               multiline attributes
                   109783:      * @param string     $linebreak  string used for linebreaks of 
                   109784:      *                               multiline attributes
                   109785:      * @param int        $entities   setting for entities in attribute values 
                   109786:      *                               (one of XML_UTIL_ENTITIES_NONE, 
                   109787:      *                               XML_UTIL_ENTITIES_XML, 
                   109788:      *                               XML_UTIL_ENTITIES_XML_REQUIRED, 
                   109789:      *                               XML_UTIL_ENTITIES_HTML)
                   109790:      *
                   109791:      * @return string string representation of the attributes
                   109792:      * @access public
                   109793:      * @static
                   109794:      * @uses replaceEntities() to replace XML entities in attribute values
                   109795:      * @todo allow sort also to be an options array
                   109796:      */
                   109797:     function attributesToString($attributes, $sort = true, $multiline = false, 
                   109798:         $indent = '    ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML)
                   109799:     {
                   109800:         /*
                   109801:          * second parameter may be an array
                   109802:          */
                   109803:         if (is_array($sort)) {
                   109804:             if (isset($sort['multiline'])) {
                   109805:                 $multiline = $sort['multiline'];
                   109806:             }
                   109807:             if (isset($sort['indent'])) {
                   109808:                 $indent = $sort['indent'];
                   109809:             }
                   109810:             if (isset($sort['linebreak'])) {
                   109811:                 $multiline = $sort['linebreak'];
                   109812:             }
                   109813:             if (isset($sort['entities'])) {
                   109814:                 $entities = $sort['entities'];
                   109815:             }
                   109816:             if (isset($sort['sort'])) {
                   109817:                 $sort = $sort['sort'];
                   109818:             } else {
                   109819:                 $sort = true;
                   109820:             }
                   109821:         }
                   109822:         $string = '';
                   109823:         if (is_array($attributes) && !empty($attributes)) {
                   109824:             if ($sort) {
                   109825:                 ksort($attributes);
                   109826:             }
                   109827:             if ( !$multiline || count($attributes) == 1) {
                   109828:                 foreach ($attributes as $key => $value) {
                   109829:                     if ($entities != XML_UTIL_ENTITIES_NONE) {
                   109830:                         if ($entities === XML_UTIL_CDATA_SECTION) {
                   109831:                             $entities = XML_UTIL_ENTITIES_XML;
                   109832:                         }
                   109833:                         $value = XML_Util::replaceEntities($value, $entities);
                   109834:                     }
                   109835:                     $string .= ' ' . $key . '="' . $value . '"';
                   109836:                 }
                   109837:             } else {
                   109838:                 $first = true;
                   109839:                 foreach ($attributes as $key => $value) {
                   109840:                     if ($entities != XML_UTIL_ENTITIES_NONE) {
                   109841:                         $value = XML_Util::replaceEntities($value, $entities);
                   109842:                     }
                   109843:                     if ($first) {
                   109844:                         $string .= ' ' . $key . '="' . $value . '"';
                   109845:                         $first   = false;
                   109846:                     } else {
                   109847:                         $string .= $linebreak . $indent . $key . '="' . $value . '"';
                   109848:                     }
                   109849:                 }
                   109850:             }
                   109851:         }
                   109852:         return $string;
                   109853:     }
                   109854: 
                   109855:     /**
                   109856:      * Collapses empty tags.
                   109857:      *
                   109858:      * @param string $xml  XML
                   109859:      * @param int    $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
                   109860:      *                      or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
                   109861:      *
                   109862:      * @return string XML
                   109863:      * @access public
                   109864:      * @static
                   109865:      * @todo PEAR CS - unable to avoid "space after open parens" error
                   109866:      *       in the IF branch
                   109867:      */
                   109868:     function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL) 
                   109869:     {
                   109870:         if ($mode == XML_UTIL_COLLAPSE_XHTML_ONLY) {
                   109871:             return preg_replace(
                   109872:                 '/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
                   109873:                 . 'param)([^>]*)><\/\\1>/s',
                   109874:                 '<\\1\\2 />',
                   109875:                 $xml);
                   109876:         } else {
                   109877:             return preg_replace('/<(\w+)([^>]*)><\/\\1>/s', '<\\1\\2 />', $xml);
                   109878:         }
                   109879:     }
                   109880: 
                   109881:     /**
                   109882:      * create a tag
                   109883:      *
                   109884:      * This method will call XML_Util::createTagFromArray(), which
                   109885:      * is more flexible.
                   109886:      *
                   109887:      * <code>
                   109888:      * require_once 'XML/Util.php';
                   109889:      *
                   109890:      * // create an XML tag:
                   109891:      * $tag = XML_Util::createTag('myNs:myTag', 
                   109892:      *     array('foo' => 'bar'), 
                   109893:      *     'This is inside the tag', 
                   109894:      *     'http://www.w3c.org/myNs#');
                   109895:      * </code>
                   109896:      *
                   109897:      * @param string $qname           qualified tagname (including namespace)
                   109898:      * @param array  $attributes      array containg attributes
                   109899:      * @param mixed  $content         the content
                   109900:      * @param string $namespaceUri    URI of the namespace
                   109901:      * @param int    $replaceEntities whether to replace XML special chars in 
                   109902:      *                                content, embedd it in a CData section 
                   109903:      *                                or none of both
                   109904:      * @param bool   $multiline       whether to create a multiline tag where 
                   109905:      *                                each attribute gets written to a single line
                   109906:      * @param string $indent          string used to indent attributes 
                   109907:      *                                (_auto indents attributes so they start 
                   109908:      *                                at the same column)
                   109909:      * @param string $linebreak       string used for linebreaks
                   109910:      * @param bool   $sortAttributes  Whether to sort the attributes or not
                   109911:      *
                   109912:      * @return string XML tag
                   109913:      * @access public
                   109914:      * @static
                   109915:      * @see createTagFromArray()
                   109916:      * @uses createTagFromArray() to create the tag
                   109917:      */
                   109918:     function createTag($qname, $attributes = array(), $content = null, 
                   109919:         $namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES, 
                   109920:         $multiline = false, $indent = '_auto', $linebreak = "\n", 
                   109921:         $sortAttributes = true)
                   109922:     {
                   109923:         $tag = array(
                   109924:             'qname'      => $qname,
                   109925:             'attributes' => $attributes
                   109926:         );
                   109927: 
                   109928:         // add tag content
                   109929:         if ($content !== null) {
                   109930:             $tag['content'] = $content;
                   109931:         }
                   109932: 
                   109933:         // add namespace Uri
                   109934:         if ($namespaceUri !== null) {
                   109935:             $tag['namespaceUri'] = $namespaceUri;
                   109936:         }
                   109937: 
                   109938:         return XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, 
                   109939:             $indent, $linebreak, $sortAttributes);
                   109940:     }
                   109941: 
                   109942:     /**
                   109943:      * create a tag from an array
                   109944:      * this method awaits an array in the following format
                   109945:      * <pre>
                   109946:      * array(
                   109947:      *     // qualified name of the tag
                   109948:      *     'qname' => $qname        
                   109949:      *
                   109950:      *     // namespace prefix (optional, if qname is specified or no namespace)
                   109951:      *     'namespace' => $namespace    
                   109952:      *
                   109953:      *     // local part of the tagname (optional, if qname is specified)
                   109954:      *     'localpart' => $localpart,   
                   109955:      *
                   109956:      *     // array containing all attributes (optional)
                   109957:      *     'attributes' => array(),      
                   109958:      *
                   109959:      *     // tag content (optional)
                   109960:      *     'content' => $content,     
                   109961:      *
                   109962:      *     // namespaceUri for the given namespace (optional)
                   109963:      *     'namespaceUri' => $namespaceUri 
                   109964:      * )
                   109965:      * </pre>
                   109966:      *
                   109967:      * <code>
                   109968:      * require_once 'XML/Util.php';
                   109969:      *
                   109970:      * $tag = array(
                   109971:      *     'qname'        => 'foo:bar',
                   109972:      *     'namespaceUri' => 'http://foo.com',
                   109973:      *     'attributes'   => array('key' => 'value', 'argh' => 'fruit&vegetable'),
                   109974:      *     'content'      => 'I\'m inside the tag',
                   109975:      * );
                   109976:      * // creating a tag with qualified name and namespaceUri
                   109977:      * $string = XML_Util::createTagFromArray($tag);
                   109978:      * </code>
                   109979:      *
                   109980:      * @param array  $tag             tag definition
                   109981:      * @param int    $replaceEntities whether to replace XML special chars in 
                   109982:      *                                content, embedd it in a CData section 
                   109983:      *                                or none of both
                   109984:      * @param bool   $multiline       whether to create a multiline tag where each 
                   109985:      *                                attribute gets written to a single line
                   109986:      * @param string $indent          string used to indent attributes 
                   109987:      *                                (_auto indents attributes so they start 
                   109988:      *                                at the same column)
                   109989:      * @param string $linebreak       string used for linebreaks
                   109990:      * @param bool   $sortAttributes  Whether to sort the attributes or not
                   109991:      *
                   109992:      * @return string XML tag
                   109993:      * @access public
                   109994:      * @static
                   109995:      * @see createTag()
                   109996:      * @uses attributesToString() to serialize the attributes of the tag
                   109997:      * @uses splitQualifiedName() to get local part and namespace of a qualified name
                   109998:      * @uses createCDataSection()
                   109999:      * @uses raiseError()
                   110000:      */
                   110001:     function createTagFromArray($tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
                   110002:         $multiline = false, $indent = '_auto', $linebreak = "\n", 
                   110003:         $sortAttributes = true)
                   110004:     {
                   110005:         if (isset($tag['content']) && !is_scalar($tag['content'])) {
                   110006:             return XML_Util::raiseError('Supplied non-scalar value as tag content',
                   110007:             XML_UTIL_ERROR_NON_SCALAR_CONTENT);
                   110008:         }
                   110009: 
                   110010:         if (!isset($tag['qname']) && !isset($tag['localPart'])) {
                   110011:             return XML_Util::raiseError('You must either supply a qualified name '
                   110012:                 . '(qname) or local tag name (localPart).', 
                   110013:                 XML_UTIL_ERROR_NO_TAG_NAME);
                   110014:         }
                   110015: 
                   110016:         // if no attributes hav been set, use empty attributes
                   110017:         if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
                   110018:             $tag['attributes'] = array();
                   110019:         }
                   110020: 
                   110021:         if (isset($tag['namespaces'])) {
                   110022:             foreach ($tag['namespaces'] as $ns => $uri) {
                   110023:                 $tag['attributes']['xmlns:' . $ns] = $uri;
                   110024:             }
                   110025:         }
                   110026: 
                   110027:         if (!isset($tag['qname'])) {
                   110028:             // qualified name is not given
                   110029: 
                   110030:             // check for namespace
                   110031:             if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                   110032:                 $tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
                   110033:             } else {
                   110034:                 $tag['qname'] = $tag['localPart'];
                   110035:             }
                   110036:         } elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
                   110037:             // namespace URI is set, but no namespace
                   110038: 
                   110039:             $parts = XML_Util::splitQualifiedName($tag['qname']);
                   110040: 
                   110041:             $tag['localPart'] = $parts['localPart'];
                   110042:             if (isset($parts['namespace'])) {
                   110043:                 $tag['namespace'] = $parts['namespace'];
                   110044:             }
                   110045:         }
                   110046: 
                   110047:         if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
                   110048:             // is a namespace given
                   110049:             if (isset($tag['namespace']) && !empty($tag['namespace'])) {
                   110050:                 $tag['attributes']['xmlns:' . $tag['namespace']] =
                   110051:                     $tag['namespaceUri'];
                   110052:             } else {
                   110053:                 // define this Uri as the default namespace
                   110054:                 $tag['attributes']['xmlns'] = $tag['namespaceUri'];
                   110055:             }
                   110056:         }
                   110057: 
                   110058:         // check for multiline attributes
                   110059:         if ($multiline === true) {
                   110060:             if ($indent === '_auto') {
                   110061:                 $indent = str_repeat(' ', (strlen($tag['qname'])+2));
                   110062:             }
                   110063:         }
                   110064: 
                   110065:         // create attribute list
                   110066:         $attList = XML_Util::attributesToString($tag['attributes'], 
                   110067:             $sortAttributes, $multiline, $indent, $linebreak, $replaceEntities);
                   110068:         if (!isset($tag['content']) || (string)$tag['content'] == '') {
                   110069:             $tag = sprintf('<%s%s />', $tag['qname'], $attList);
                   110070:         } else {
                   110071:             switch ($replaceEntities) {
                   110072:             case XML_UTIL_ENTITIES_NONE:
                   110073:                 break;
                   110074:             case XML_UTIL_CDATA_SECTION:
                   110075:                 $tag['content'] = XML_Util::createCDataSection($tag['content']);
                   110076:                 break;
                   110077:             default:
                   110078:                 $tag['content'] = XML_Util::replaceEntities($tag['content'], 
                   110079:                     $replaceEntities);
                   110080:                 break;
                   110081:             }
                   110082:             $tag = sprintf('<%s%s>%s</%s>', $tag['qname'], $attList, $tag['content'],
                   110083:                 $tag['qname']);
                   110084:         }
                   110085:         return $tag;
                   110086:     }
                   110087: 
                   110088:     /**
                   110089:      * create a start element
                   110090:      *
                   110091:      * <code>
                   110092:      * require_once 'XML/Util.php';
                   110093:      *
                   110094:      * // create an XML start element:
                   110095:      * $tag = XML_Util::createStartElement('myNs:myTag', 
                   110096:      *     array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
                   110097:      * </code>
                   110098:      *
                   110099:      * @param string $qname          qualified tagname (including namespace)
                   110100:      * @param array  $attributes     array containg attributes
                   110101:      * @param string $namespaceUri   URI of the namespace
                   110102:      * @param bool   $multiline      whether to create a multiline tag where each 
                   110103:      *                               attribute gets written to a single line
                   110104:      * @param string $indent         string used to indent attributes (_auto indents
                   110105:      *                               attributes so they start at the same column)
                   110106:      * @param string $linebreak      string used for linebreaks
                   110107:      * @param bool   $sortAttributes Whether to sort the attributes or not
                   110108:      *
                   110109:      * @return string XML start element
                   110110:      * @access public
                   110111:      * @static
                   110112:      * @see createEndElement(), createTag()
                   110113:      */
                   110114:     function createStartElement($qname, $attributes = array(), $namespaceUri = null,
                   110115:         $multiline = false, $indent = '_auto', $linebreak = "\n", 
                   110116:         $sortAttributes = true)
                   110117:     {
                   110118:         // if no attributes hav been set, use empty attributes
                   110119:         if (!isset($attributes) || !is_array($attributes)) {
                   110120:             $attributes = array();
                   110121:         }
                   110122: 
                   110123:         if ($namespaceUri != null) {
                   110124:             $parts = XML_Util::splitQualifiedName($qname);
                   110125:         }
                   110126: 
                   110127:         // check for multiline attributes
                   110128:         if ($multiline === true) {
                   110129:             if ($indent === '_auto') {
                   110130:                 $indent = str_repeat(' ', (strlen($qname)+2));
                   110131:             }
                   110132:         }
                   110133: 
                   110134:         if ($namespaceUri != null) {
                   110135:             // is a namespace given
                   110136:             if (isset($parts['namespace']) && !empty($parts['namespace'])) {
                   110137:                 $attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
                   110138:             } else {
                   110139:                 // define this Uri as the default namespace
                   110140:                 $attributes['xmlns'] = $namespaceUri;
                   110141:             }
                   110142:         }
                   110143: 
                   110144:         // create attribute list
                   110145:         $attList = XML_Util::attributesToString($attributes, $sortAttributes, 
                   110146:             $multiline, $indent, $linebreak);
                   110147:         $element = sprintf('<%s%s>', $qname, $attList);
                   110148:         return  $element;
                   110149:     }
                   110150: 
                   110151:     /**
                   110152:      * create an end element
                   110153:      *
                   110154:      * <code>
                   110155:      * require_once 'XML/Util.php';
                   110156:      *
                   110157:      * // create an XML start element:
                   110158:      * $tag = XML_Util::createEndElement('myNs:myTag');
                   110159:      * </code>
                   110160:      *
                   110161:      * @param string $qname qualified tagname (including namespace)
                   110162:      *
                   110163:      * @return string XML end element
                   110164:      * @access public
                   110165:      * @static
                   110166:      * @see createStartElement(), createTag()
                   110167:      */
                   110168:     function createEndElement($qname)
                   110169:     {
                   110170:         $element = sprintf('</%s>', $qname);
                   110171:         return $element;
                   110172:     }
                   110173: 
                   110174:     /**
                   110175:      * create an XML comment
                   110176:      *
                   110177:      * <code>
                   110178:      * require_once 'XML/Util.php';
                   110179:      *
                   110180:      * // create an XML start element:
                   110181:      * $tag = XML_Util::createComment('I am a comment');
                   110182:      * </code>
                   110183:      *
                   110184:      * @param string $content content of the comment
                   110185:      *
                   110186:      * @return string XML comment
                   110187:      * @access public
                   110188:      * @static
                   110189:      */
                   110190:     function createComment($content)
                   110191:     {
                   110192:         $comment = sprintf('<!-- %s -->', $content);
                   110193:         return $comment;
                   110194:     }
                   110195: 
                   110196:     /**
                   110197:      * create a CData section
                   110198:      *
                   110199:      * <code>
                   110200:      * require_once 'XML/Util.php';
                   110201:      *
                   110202:      * // create a CData section
                   110203:      * $tag = XML_Util::createCDataSection('I am content.');
                   110204:      * </code>
                   110205:      *
                   110206:      * @param string $data data of the CData section
                   110207:      *
                   110208:      * @return string CData section with content
                   110209:      * @access public
                   110210:      * @static
                   110211:      */
                   110212:     function createCDataSection($data)
                   110213:     {
                   110214:         return sprintf('<![CDATA[%s]]>', 
                   110215:             preg_replace('/\]\]>/', ']]]]><![CDATA[>', strval($data)));
                   110216: 
                   110217:     }
                   110218: 
                   110219:     /**
                   110220:      * split qualified name and return namespace and local part
                   110221:      *
                   110222:      * <code>
                   110223:      * require_once 'XML/Util.php';
                   110224:      *
                   110225:      * // split qualified tag
                   110226:      * $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
                   110227:      * </code>
                   110228:      * the returned array will contain two elements:
                   110229:      * <pre>
                   110230:      * array(
                   110231:      *     'namespace' => 'xslt',
                   110232:      *     'localPart' => 'stylesheet'
                   110233:      * );
                   110234:      * </pre>
                   110235:      *
                   110236:      * @param string $qname     qualified tag name
                   110237:      * @param string $defaultNs default namespace (optional)
                   110238:      *
                   110239:      * @return array array containing namespace and local part
                   110240:      * @access public
                   110241:      * @static
                   110242:      */
                   110243:     function splitQualifiedName($qname, $defaultNs = null)
                   110244:     {
                   110245:         if (strstr($qname, ':')) {
                   110246:             $tmp = explode(':', $qname);
                   110247:             return array(
                   110248:                 'namespace' => $tmp[0],
                   110249:                 'localPart' => $tmp[1]
                   110250:             );
                   110251:         }
                   110252:         return array(
                   110253:             'namespace' => $defaultNs,
                   110254:             'localPart' => $qname
                   110255:         );
                   110256:     }
                   110257: 
                   110258:     /**
                   110259:      * check, whether string is valid XML name
                   110260:      *
                   110261:      * <p>XML names are used for tagname, attribute names and various
                   110262:      * other, lesser known entities.</p>
                   110263:      * <p>An XML name may only consist of alphanumeric characters,
                   110264:      * dashes, undescores and periods, and has to start with a letter
                   110265:      * or an underscore.</p>
                   110266:      *
                   110267:      * <code>
                   110268:      * require_once 'XML/Util.php';
                   110269:      *
                   110270:      * // verify tag name
                   110271:      * $result = XML_Util::isValidName('invalidTag?');
                   110272:      * if (is_a($result, 'PEAR_Error')) {
                   110273:      *    print 'Invalid XML name: ' . $result->getMessage();
                   110274:      * }
                   110275:      * </code>
                   110276:      *
                   110277:      * @param string $string string that should be checked
                   110278:      *
                   110279:      * @return mixed true, if string is a valid XML name, PEAR error otherwise
                   110280:      * @access public
                   110281:      * @static
                   110282:      * @todo support for other charsets
                   110283:      * @todo PEAR CS - unable to avoid 85-char limit on second preg_match
                   110284:      */
                   110285:     function isValidName($string)
                   110286:     {
                   110287:         // check for invalid chars
                   110288:         if (!preg_match('/^[[:alpha:]_]$/', $string{0})) {
                   110289:             return XML_Util::raiseError('XML names may only start with letter '
                   110290:                 . 'or underscore', XML_UTIL_ERROR_INVALID_START);
                   110291:         }
                   110292: 
                   110293:         // check for invalid chars
                   110294:         if (!preg_match('/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?[[:alpha:]_]([[:alnum:]\_\-\.]+)?$/',
                   110295:             $string)
                   110296:         ) {
                   110297:             return XML_Util::raiseError('XML names may only contain alphanumeric '
                   110298:                 . 'chars, period, hyphen, colon and underscores', 
                   110299:                 XML_UTIL_ERROR_INVALID_CHARS);
                   110300:         }
                   110301:         // XML name is valid
                   110302:         return true;
                   110303:     }
                   110304: 
                   110305:     /**
                   110306:      * replacement for XML_Util::raiseError
                   110307:      *
                   110308:      * Avoids the necessity to always require
                   110309:      * PEAR.php
                   110310:      *
                   110311:      * @param string $msg  error message
                   110312:      * @param int    $code error code
                   110313:      *
                   110314:      * @return PEAR_Error
                   110315:      * @access public
                   110316:      * @static
                   110317:      * @todo PEAR CS - should this use include_once instead?
                   110318:      */
                   110319:     function raiseError($msg, $code)
                   110320:     {
                   110321:         require_once 'PEAR.php';
                   110322:         return PEAR::raiseError($msg, $code);
                   110323:     }
                   110324: }
                   110325: ?>
                   110326: package.sig100644   1750   1750         305 11117075544   6362 -----BEGIN PGP SIGNATURE-----
                   110327: Version: GnuPG v1.4.9 (GNU/Linux)
                   110328: 
                   110329: iEYEABECAAYFAkk8e2QACgkQcqMhusJF8XULZgCg0iwVLWueraJzK5s1AesDkVzv
                   110330: GucAn22sSv3QiTSUWG9BmakiW9hFsb4V
                   110331: =g2mr
                   110332: -----END PGP SIGNATURE-----
1.1.1.2 ! misho    110333: ¼§’Ó\ÌÚ„c³vî83HÈüGBMB

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>